diff --git a/.github/workflows/build-xmake.yml b/.github/workflows/build-xmake.yml index 0f8c11694..e5565a61e 100644 --- a/.github/workflows/build-xmake.yml +++ b/.github/workflows/build-xmake.yml @@ -55,15 +55,20 @@ jobs: submodules: recursive - name: "Install Dependencies" run: | - brew install llvm molten-vk ninja cmake xmake + if [ "${{ matrix.compiler }}" = "homebrew-clang" ]; then + brew install llvm + fi + brew install molten-vk ninja cmake xmake curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - name: "Configure and Build" run: | + xmake lua setup.lua if [ "${{ matrix.compiler }}" = "homebrew-clang" ]; then export PATH=/usr/local/opt/llvm/bin:$PATH + xmake f -p macosx --toolchain=llvm -m ${{ matrix.config }} --mm=clang --mxx=clang++ --metal_backend=true --enable_dsl=true --enable_gui=true --enable_unity_build=false --enable_tests=true --enable_mimalloc=false --check -c -y + else + xmake f -p macosx --toolchain=clang -m ${{ matrix.config }} --mm=clang --mxx=clang++ --metal_backend=true --enable_dsl=true --enable_gui=true --enable_unity_build=false --enable_tests=true --enable_mimalloc=false --check -c -y fi - xmake lua setup.lua - xmake f -p macosx --toolchain=llvm -m ${{ matrix.config }} --mm=clang --mxx=clang++ --metal_backend=true --enable_dsl=true --enable_gui=true --enable_unity_build=false --enable_tests=true --enable_mimalloc=false --check -c -y xmake -v build-windows: diff --git a/CMakeLists.txt b/CMakeLists.txt index ca4f8d712..1b765607f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,12 +29,13 @@ if (NOT SKBUILD AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/options.cmake") else () option(LUISA_COMPUTE_ENABLE_DSL "Enable C++ DSL" ON) option(LUISA_COMPUTE_ENABLE_TENSOR "Enable C++ DSL tensor extension" ON) - option(LUISA_COMPUTE_ENABLE_DX "Enable DirectX backend" ON) - option(LUISA_COMPUTE_ENABLE_METAL "Enable Metal backend" ON) + option(LUISA_COMPUTE_ENABLE_DX "Enable DirectX backend" OFF) + option(LUISA_COMPUTE_ENABLE_METAL "Enable Metal backend" OFF) option(LUISA_COMPUTE_ENABLE_CUDA "Enable CUDA backend" ON) option(LUISA_COMPUTE_ENABLE_CUDA_EXT_LCUB "Enable CUDA extension: LCUB" OFF) - option(LUISA_COMPUTE_ENABLE_VULKAN "Enable Vulkan backend" ON) - option(LUISA_COMPUTE_ENABLE_CPU "Enable CPU backend" ON) + option(LUISA_COMPUTE_ENABLE_VULKAN "Enable Vulkan backend" OFF) + option(LUISA_COMPUTE_ENABLE_CPU "Enable CPU backend" OFF) + option(LUISA_COMPUTE_ENABLE_FALLBACK "Enable Fallback backend" ON) option(LUISA_COMPUTE_ENABLE_REMOTE "Enable Remote backend" ON) option(LUISA_COMPUTE_ENABLE_GUI "Enable GUI support" ON) option(LUISA_COMPUTE_ENABLE_CLANG_CXX "Enable ClangTooling-based C++ shading language" OFF) diff --git a/include/luisa/core/basic_types.h b/include/luisa/core/basic_types.h index 8855804f4..cf0d4d0a8 100644 --- a/include/luisa/core/basic_types.h +++ b/include/luisa/core/basic_types.h @@ -1,777 +1,779 @@ -#pragma once - -#include -#include - -#include -#include - -namespace luisa { - -// vectors -namespace detail { - -template -struct vector_alignment { - static constexpr size_t _a = sizeof(T) * (N == 3 ? 4 : N); - static constexpr size_t value = _a > 16u ? 16u : _a; -}; -template -static constexpr size_t vector_alignment_v = vector_alignment::value; - -/// Vector storage only allows size of 2, 3, 4 -template -struct VectorStorage { - static_assert(always_false_v, "Invalid vector storage"); -}; - -/// Vector storage of size 2 -template -struct alignas(vector_alignment_v) VectorStorage { - T x, y; - explicit constexpr VectorStorage(T s = {}) noexcept : x{s}, y{s} {} - constexpr VectorStorage(T x, T y) noexcept : x{x}, y{y} {} -#include -}; - -/// Vector storage of size 3 -template -struct alignas(vector_alignment_v) VectorStorage { - T x, y, z; - explicit constexpr VectorStorage(T s = {}) noexcept : x{s}, y{s}, z{s} {} - constexpr VectorStorage(T x, T y, T z) noexcept : x{x}, y{y}, z{z} {} -#include -}; - -/// Vector storage of size 4 -template -struct alignas(vector_alignment_v) VectorStorage { - T x, y, z, w; - explicit constexpr VectorStorage(T s = {}) noexcept : x{s}, y{s}, z{s}, w{s} {} - constexpr VectorStorage(T x, T y, T z, T w) noexcept : x{x}, y{y}, z{z}, w{w} {} -#include -}; - -}// namespace detail - -/** - * @brief Vector class - * - * We only support vector of size 2, 3, 4 and type bool, float, half, 16/32/64-bit int/uint. - * Any other kind of template parameters will fail on compilation. - * - * @tparam T bool/float/int/uint - * @tparam N 2/3/4 - */ -template -struct Vector : public detail::VectorStorage { - static constexpr auto dimension = N; - static Vector zero() noexcept { return Vector(static_cast(0)); } - static Vector one() noexcept { return Vector(static_cast(1)); } - using value_type = T; - using Storage = detail::VectorStorage; - static_assert(is_scalar_v, "Invalid vector type"); - static_assert(N == 2 || N == 3 || N == 4, "Invalid vector dimension"); - using Storage::VectorStorage; - [[nodiscard]] constexpr T &operator[](size_t index) noexcept { return (&(this->x))[index]; } - [[nodiscard]] constexpr const T &operator[](size_t index) const noexcept { return (&(this->x))[index]; } -}; - -template -struct hash> { - using is_avalanching = void; - [[nodiscard]] uint64_t operator()(const Vector &v, - uint64_t seed = hash64_default_seed) const noexcept { - return hash64(&v, sizeof(T) * N, seed); - } -}; - -/** - * @brief Make vector types of size 2, 3, 4 - * - * Ex. LUISA_MAKE_VECTOR_TYPES(int) -> int2, int3, int4 - */ -#define LUISA_MAKE_VECTOR_TYPES(T) \ - using T##2 = Vector; \ - using T##3 = Vector; \ - using T##4 = Vector; - -LUISA_MAKE_VECTOR_TYPES(bool) - -LUISA_MAKE_VECTOR_TYPES(short) -LUISA_MAKE_VECTOR_TYPES(ushort) - -LUISA_MAKE_VECTOR_TYPES(byte) -LUISA_MAKE_VECTOR_TYPES(ubyte) - -LUISA_MAKE_VECTOR_TYPES(int) -LUISA_MAKE_VECTOR_TYPES(uint) - -LUISA_MAKE_VECTOR_TYPES(ulong) -LUISA_MAKE_VECTOR_TYPES(slong) - -LUISA_MAKE_VECTOR_TYPES(half) -LUISA_MAKE_VECTOR_TYPES(float) -LUISA_MAKE_VECTOR_TYPES(double) - -#undef LUISA_MAKE_VECTOR_TYPES - -/// Matrix only allows size of 2, 3, 4 -template -struct Matrix { - static_assert(always_false_v>, "Invalid matrix type"); -}; - -/// 2x2 matrix -template<> -struct Matrix<2> { - - float2 cols[2]; - - constexpr Matrix() noexcept - : cols{float2{1.0f, 0.0f}, float2{0.0f, 1.0f}} {} - - constexpr Matrix(const float2 c0, const float2 c1) noexcept - : cols{c0, c1} {} - - static constexpr Matrix eye(const float c) noexcept { - return Matrix{ - float2{c, 0.0f}, - float2{0.0f, c}}; - } - - static constexpr Matrix fill(const float c) noexcept { - return Matrix{ - float2{c, c}, - float2{c, c}}; - } - - [[nodiscard]] constexpr float2 &operator[](size_t i) noexcept { return cols[i]; } - [[nodiscard]] constexpr const float2 &operator[](size_t i) const noexcept { return cols[i]; } -}; - -/// 3x3 matrix -template<> -struct Matrix<3> { - - float3 cols[3]; - - constexpr Matrix() noexcept - : cols{float3{1.0f, 0.0f, 0.0f}, float3{0.0f, 1.0f, 0.0f}, float3{0.0f, 0.0f, 1.0f}} {} - - constexpr Matrix(const float3 c0, const float3 c1, const float3 c2) noexcept - : cols{c0, c1, c2} {} - - static constexpr Matrix eye(const float c) noexcept { - return Matrix{ - float3{c, 0.0f, 0.0f}, - float3{0.0f, c, 0.0f}, - float3{0.0f, 0.0f, c}}; - } - - static constexpr Matrix fill(const float c) noexcept { - return Matrix{ - float3{c, c, c}, - float3{c, c, c}, - float3{c, c, c}}; - } - - [[nodiscard]] constexpr float3 &operator[](size_t i) noexcept { return cols[i]; } - [[nodiscard]] constexpr const float3 &operator[](size_t i) const noexcept { return cols[i]; } -}; - -/// 4x4 matrix -template<> -struct Matrix<4> { - - float4 cols[4]; - - constexpr Matrix() noexcept - : cols{float4{1.0f, 0.0f, 0.0f, 0.0f}, - float4{0.0f, 1.0f, 0.0f, 0.0f}, - float4{0.0f, 0.0f, 1.0f, 0.0f}, - float4{0.0f, 0.0f, 0.0f, 1.0f}} {} - - constexpr Matrix(const float4 c0, const float4 c1, const float4 c2, const float4 c3) noexcept - : cols{c0, c1, c2, c3} {} - - static constexpr Matrix eye(const float c) noexcept { - return Matrix{ - float4{c, 0.0f, 0.0f, 0.0f}, - float4{0.0f, c, 0.0f, 0.0f}, - float4{0.0f, 0.0f, c, 0.0f}, - float4{0.0f, 0.0f, 0.0f, c}}; - } - - static constexpr Matrix fill(const float c) noexcept { - return Matrix{ - float4{c, c, c, c}, - float4{c, c, c, c}, - float4{c, c, c, c}, - float4{c, c, c, c}}; - } - - [[nodiscard]] constexpr float4 &operator[](size_t i) noexcept { return cols[i]; } - [[nodiscard]] constexpr const float4 &operator[](size_t i) const noexcept { return cols[i]; } -}; - -template -struct hash> { - using is_avalanching = void; - [[nodiscard]] uint64_t operator()(Matrix m, uint64_t seed = hash64_default_seed) const noexcept { - std::array data{}; - for (size_t i = 0u; i < N; i++) { - for (size_t j = 0u; j < N; j++) { - data[i * N + j] = m[i][j]; - } - } - return hash64(data.data(), data.size() * sizeof(float), seed); - } -}; - -using float2x2 = Matrix<2>; -using float3x3 = Matrix<3>; -using float4x4 = Matrix<4>; - -using basic_types = std::tuple< - bool, float, int, uint, short, ushort, slong, ulong, half, double, byte, ubyte, - bool2, float2, int2, uint2, short2, ushort2, byte2, ubyte2, slong2, ulong2, half2, double2, - bool3, float3, int3, uint3, short3, ushort3, byte3, ubyte3, slong3, ulong3, half3, double3, - bool4, float4, int4, uint4, short4, ushort4, byte4, ubyte4, slong4, ulong4, half4, double4, - float2x2, float3x3, float4x4>; - -/// any of bool2 is true -[[nodiscard]] constexpr auto any(const bool2 v) noexcept { return v.x || v.y; } -/// any of bool3 is true -[[nodiscard]] constexpr auto any(const bool3 v) noexcept { return v.x || v.y || v.z; } -/// any of bool4 is true -[[nodiscard]] constexpr auto any(const bool4 v) noexcept { return v.x || v.y || v.z || v.w; } - -/// all of bool2 is true -[[nodiscard]] constexpr auto all(const bool2 v) noexcept { return v.x && v.y; } -/// all of bool3 is true -[[nodiscard]] constexpr auto all(const bool3 v) noexcept { return v.x && v.y && v.z; } -/// all of bool4 is true -[[nodiscard]] constexpr auto all(const bool4 v) noexcept { return v.x && v.y && v.z && v.w; } - -/// none of bool2 is true -[[nodiscard]] constexpr auto none(const bool2 v) noexcept { return !any(v); } -/// none of bool3 is true -[[nodiscard]] constexpr auto none(const bool3 v) noexcept { return !any(v); } -/// none of bool4 is true -[[nodiscard]] constexpr auto none(const bool4 v) noexcept { return !any(v); } - -}// namespace luisa - -/// Unary plus operator of vector. Bool vector is not allowed. -template>, int> = 0> -[[nodiscard]] constexpr auto operator+(const luisa::Vector v) noexcept { return v; } - -/// Unary minus operator of vector. Bool vector is not allowed. -template>, int> = 0> -[[nodiscard]] constexpr auto operator-(const luisa::Vector v) noexcept { - using R = luisa::Vector; - if constexpr (N == 2) { - return R{static_cast(-v.x), static_cast(-v.y)}; - } else if constexpr (N == 3) { - return R{static_cast(-v.x), static_cast(-v.y), static_cast(-v.z)}; - } else { - return R{static_cast(-v.x), static_cast(-v.y), static_cast(-v.z), static_cast(-v.w)}; - } -} - -/// Unary not operator of vector -template -[[nodiscard]] constexpr auto operator!(const luisa::Vector v) noexcept { - if constexpr (N == 2u) { - return luisa::bool2{!v.x, !v.y}; - } else if constexpr (N == 3u) { - return luisa::bool3{!v.x, !v.y, !v.z}; - } else { - return luisa::bool4{!v.x, !v.y, !v.z, !v.w}; - } -} - -/// Unary xor operator of vector. Only int vector is allowed. -template, int> = 0> -[[nodiscard]] constexpr auto operator~(const luisa::Vector v) noexcept { - using R = luisa::Vector; - if constexpr (N == 2) { - return R{static_cast(~v.x), static_cast(~v.y)}; - } else if constexpr (N == 3) { - return R{static_cast(~v.x), static_cast(~v.y), static_cast(~v.z)}; - } else { - return R{static_cast(~v.x), static_cast(~v.y), static_cast(~v.z), static_cast(~v.w)}; - } -} - -/// Binary & Assignment operators -#define LUISA_MAKE_VECTOR_BINARY_OPERATOR(op, ...) \ - template = 0> \ - [[nodiscard]] constexpr auto operator op( \ - luisa::Vector lhs, luisa::Vector rhs) noexcept { \ - if constexpr (N == 2) { \ - return luisa::Vector{ \ - static_cast(lhs.x op rhs.x), \ - static_cast(lhs.y op rhs.y)}; \ - } else if constexpr (N == 3) { \ - return luisa::Vector{ \ - static_cast(lhs.x op rhs.x), \ - static_cast(lhs.y op rhs.y), \ - static_cast(lhs.z op rhs.z)}; \ - } else { \ - return luisa::Vector{ \ - static_cast(lhs.x op rhs.x), \ - static_cast(lhs.y op rhs.y), \ - static_cast(lhs.z op rhs.z), \ - static_cast(lhs.w op rhs.w)}; \ - } \ - } \ - template = 0> \ - [[nodiscard]] constexpr auto operator op(luisa::Vector lhs, T rhs) noexcept { \ - return lhs op luisa::Vector{rhs}; \ - } \ - template = 0> \ - [[nodiscard]] constexpr auto operator op(T lhs, luisa::Vector rhs) noexcept { \ - return luisa::Vector{lhs} op rhs; \ - } -LUISA_MAKE_VECTOR_BINARY_OPERATOR(+, std::negation_v>) -LUISA_MAKE_VECTOR_BINARY_OPERATOR(-, std::negation_v>) -LUISA_MAKE_VECTOR_BINARY_OPERATOR(*, std::negation_v>) -LUISA_MAKE_VECTOR_BINARY_OPERATOR(/, std::negation_v>) -LUISA_MAKE_VECTOR_BINARY_OPERATOR(%, luisa::is_integral_v) -LUISA_MAKE_VECTOR_BINARY_OPERATOR(<<, luisa::is_integral_v) -LUISA_MAKE_VECTOR_BINARY_OPERATOR(>>, luisa::is_integral_v) -LUISA_MAKE_VECTOR_BINARY_OPERATOR(|, std::negation_v>) -LUISA_MAKE_VECTOR_BINARY_OPERATOR(&, std::negation_v>) -LUISA_MAKE_VECTOR_BINARY_OPERATOR(^, std::negation_v>) - -/// Binary logic operators -#define LUISA_MAKE_VECTOR_LOGIC_OPERATOR(op, ...) \ - template = 0> \ - [[nodiscard]] constexpr auto operator op( \ - luisa::Vector lhs, luisa::Vector rhs) noexcept { \ - if constexpr (N == 2) { \ - return luisa::bool2{ \ - lhs.x op rhs.x, \ - lhs.y op rhs.y}; \ - } else if constexpr (N == 3) { \ - return luisa::bool3{ \ - lhs.x op rhs.x, \ - lhs.y op rhs.y, \ - lhs.z op rhs.z}; \ - } else { \ - return luisa::bool4{ \ - lhs.x op rhs.x, \ - lhs.y op rhs.y, \ - lhs.z op rhs.z, \ - lhs.w op rhs.w}; \ - } \ - } \ - template = 0> \ - [[nodiscard]] constexpr auto operator op(luisa::Vector lhs, T rhs) noexcept { \ - return lhs op luisa::Vector{rhs}; \ - } \ - template = 0> \ - [[nodiscard]] constexpr auto operator op(T lhs, luisa::Vector rhs) noexcept { \ - return luisa::Vector{lhs} op rhs; \ - } -LUISA_MAKE_VECTOR_LOGIC_OPERATOR(||, luisa::is_boolean_v) -LUISA_MAKE_VECTOR_LOGIC_OPERATOR(&&, luisa::is_boolean_v) -LUISA_MAKE_VECTOR_LOGIC_OPERATOR(==, true) -LUISA_MAKE_VECTOR_LOGIC_OPERATOR(!=, true) -LUISA_MAKE_VECTOR_LOGIC_OPERATOR(<, std::negation_v>) -LUISA_MAKE_VECTOR_LOGIC_OPERATOR(>, std::negation_v>) -LUISA_MAKE_VECTOR_LOGIC_OPERATOR(<=, std::negation_v>) -LUISA_MAKE_VECTOR_LOGIC_OPERATOR(>=, std::negation_v>) - -/// Assign operators -#define LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(op, ...) \ - template = 0> \ - constexpr decltype(auto) operator op( \ - luisa::Vector &lhs, luisa::Vector rhs) noexcept { \ - lhs.x op rhs.x; \ - lhs.y op rhs.y; \ - if constexpr (N >= 3) { lhs.z op rhs.z; } \ - if constexpr (N == 4) { lhs.w op rhs.w; } \ - return (lhs); \ - } \ - template = 0> \ - constexpr decltype(auto) operator op( \ - luisa::Vector &lhs, T rhs) noexcept { \ - return (lhs op luisa::Vector{rhs}); \ - } -LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(+=, std::negation_v>) -LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(-=, std::negation_v>) -LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(*=, std::negation_v>) -LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(/=, std::negation_v>) -LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(%=, luisa::is_integral_v) -LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(<<=, luisa::is_integral_v) -LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(>>=, luisa::is_integral_v) -LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(|=, std::negation_v>) -LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(&=, std::negation_v>) -LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(^=, std::negation_v>) - -#undef LUISA_MAKE_VECTOR_BINARY_OPERATOR -#undef LUISA_MAKE_VECTOR_LOGIC_OPERATOR -#undef LUISA_MAKE_VECTOR_ASSIGN_OPERATOR - -/// float2x2 multiplied by float -[[nodiscard]] constexpr auto operator*(const luisa::float2x2 m, float s) noexcept { - return luisa::float2x2{m[0] * s, m[1] * s}; -} - -/// float2x2 multiplied by float -[[nodiscard]] constexpr auto operator*(float s, const luisa::float2x2 m) noexcept { - return m * s; -} - -/// float2x2 divided by float -[[nodiscard]] constexpr auto operator/(const luisa::float2x2 m, float s) noexcept { - return m * (1.0f / s); -} - -/// float2x2 dot float2 -[[nodiscard]] constexpr auto operator*(const luisa::float2x2 m, const luisa::float2 v) noexcept { - return v.x * m[0] + v.y * m[1]; -} - -/// float2x2 multiply(matmul) -[[nodiscard]] constexpr auto operator*(const luisa::float2x2 lhs, const luisa::float2x2 rhs) noexcept { - return luisa::float2x2{lhs * rhs[0], lhs * rhs[1]}; -} - -/// float2x2 plus -[[nodiscard]] constexpr auto operator+(const luisa::float2x2 lhs, const luisa::float2x2 rhs) noexcept { - return luisa::float2x2{lhs[0] + rhs[0], lhs[1] + rhs[1]}; -} - -/// float2x2 minus -[[nodiscard]] constexpr auto operator-(const luisa::float2x2 lhs, const luisa::float2x2 rhs) noexcept { - return luisa::float2x2{lhs[0] - rhs[0], lhs[1] - rhs[1]}; -} - -/// float3x3 multiplied by float -[[nodiscard]] constexpr auto operator*(const luisa::float3x3 m, float s) noexcept { - return luisa::float3x3{m[0] * s, m[1] * s, m[2] * s}; -} - -/// float3x3 multiplied by float -[[nodiscard]] constexpr auto operator*(float s, const luisa::float3x3 m) noexcept { - return m * s; -} - -/// float 3x3 divided by float -[[nodiscard]] constexpr auto operator/(const luisa::float3x3 m, float s) noexcept { - return m * (1.0f / s); -} - -/// float3x3 dot float3 -[[nodiscard]] constexpr auto operator*(const luisa::float3x3 m, const luisa::float3 v) noexcept { - return v.x * m[0] + v.y * m[1] + v.z * m[2]; -} - -/// float3x3 multiply(matmul) -[[nodiscard]] constexpr auto operator*(const luisa::float3x3 lhs, const luisa::float3x3 rhs) noexcept { - return luisa::float3x3{lhs * rhs[0], lhs * rhs[1], lhs * rhs[2]}; -} - -/// float3x3 plus -[[nodiscard]] constexpr auto operator+(const luisa::float3x3 lhs, const luisa::float3x3 rhs) noexcept { - return luisa::float3x3{lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2]}; -} - -/// float3x3 minus -[[nodiscard]] constexpr auto operator-(const luisa::float3x3 lhs, const luisa::float3x3 rhs) noexcept { - return luisa::float3x3{lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2]}; -} - -/// float4x4 multiplied by float -[[nodiscard]] constexpr auto operator*(const luisa::float4x4 m, float s) noexcept { - return luisa::float4x4{m[0] * s, m[1] * s, m[2] * s, m[3] * s}; -} - -/// float4x4 multiplied by float -[[nodiscard]] constexpr auto operator*(float s, const luisa::float4x4 m) noexcept { - return m * s; -} - -/// float4x4 divided by float -[[nodiscard]] constexpr auto operator/(const luisa::float4x4 m, float s) noexcept { - return m * (1.0f / s); -} - -/// floa4x4 dot float4 -[[nodiscard]] constexpr auto operator*(const luisa::float4x4 m, const luisa::float4 v) noexcept { - return v.x * m[0] + v.y * m[1] + v.z * m[2] + v.w * m[3]; -} - -/// float4x4 multiply(matmul) -[[nodiscard]] constexpr auto operator*(const luisa::float4x4 lhs, const luisa::float4x4 rhs) noexcept { - return luisa::float4x4{lhs * rhs[0], lhs * rhs[1], lhs * rhs[2], lhs * rhs[3]}; -} - -/// float4x4 plus -[[nodiscard]] constexpr auto operator+(const luisa::float4x4 lhs, const luisa::float4x4 rhs) noexcept { - return luisa::float4x4{lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2], lhs[3] + rhs[3]}; -} - -/// float4x4 minus -[[nodiscard]] constexpr auto operator-(const luisa::float4x4 lhs, const luisa::float4x4 rhs) noexcept { - return luisa::float4x4{lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2], lhs[3] - rhs[3]}; -} - -namespace luisa { - -/// make_typeN definitions -#define LUISA_MAKE_TYPE_N(type) \ - [[nodiscard]] constexpr auto make_##type##2(type s = {}) noexcept { return type##2(s); } \ - [[nodiscard]] constexpr auto make_##type##2(type x, type y) noexcept { return type##2(x, y); } \ - template \ - [[nodiscard]] constexpr auto make_##type##2(Vector v) noexcept { \ - return type##2( \ - static_cast(v.x), \ - static_cast(v.y)); \ - } \ - [[nodiscard]] constexpr auto make_##type##2(type##3 v) noexcept { return type##2(v.x, v.y); } \ - [[nodiscard]] constexpr auto make_##type##2(type##4 v) noexcept { return type##2(v.x, v.y); } \ - \ - [[nodiscard]] constexpr auto make_##type##3(type s = {}) noexcept { return type##3(s); } \ - [[nodiscard]] constexpr auto make_##type##3(type x, type y, type z) noexcept { return type##3(x, y, z); } \ - template \ - [[nodiscard]] constexpr auto make_##type##3(Vector v) noexcept { \ - return type##3( \ - static_cast(v.x), \ - static_cast(v.y), \ - static_cast(v.z)); \ - } \ - [[nodiscard]] constexpr auto make_##type##3(type##2 v, type z) noexcept { return type##3(v.x, v.y, z); } \ - [[nodiscard]] constexpr auto make_##type##3(type x, type##2 v) noexcept { return type##3(x, v.x, v.y); } \ - [[nodiscard]] constexpr auto make_##type##3(type##4 v) noexcept { return type##3(v.x, v.y, v.z); } \ - \ - [[nodiscard]] constexpr auto make_##type##4(type s = {}) noexcept { return type##4(s); } \ - [[nodiscard]] constexpr auto make_##type##4(type x, type y, type z, type w) noexcept { return type##4(x, y, z, w); } \ - template \ - [[nodiscard]] constexpr auto make_##type##4(Vector v) noexcept { \ - return type##4( \ - static_cast(v.x), \ - static_cast(v.y), \ - static_cast(v.z), \ - static_cast(v.w)); \ - } \ - [[nodiscard]] constexpr auto make_##type##4(type##2 v, type z, type w) noexcept { return type##4(v.x, v.y, z, w); } \ - [[nodiscard]] constexpr auto make_##type##4(type x, type##2 v, type w) noexcept { return type##4(x, v.x, v.y, w); } \ - [[nodiscard]] constexpr auto make_##type##4(type x, type y, type##2 v) noexcept { return type##4(x, y, v.x, v.y); } \ - [[nodiscard]] constexpr auto make_##type##4(type##2 xy, type##2 zw) noexcept { return type##4(xy.x, xy.y, zw.x, zw.y); } \ - [[nodiscard]] constexpr auto make_##type##4(type##3 v, type w) noexcept { return type##4(v.x, v.y, v.z, w); } \ - [[nodiscard]] constexpr auto make_##type##4(type x, type##3 v) noexcept { return type##4(x, v.x, v.y, v.z); } - -LUISA_MAKE_TYPE_N(bool) -LUISA_MAKE_TYPE_N(float) -LUISA_MAKE_TYPE_N(int) -LUISA_MAKE_TYPE_N(uint) -LUISA_MAKE_TYPE_N(short) -LUISA_MAKE_TYPE_N(ushort) -LUISA_MAKE_TYPE_N(slong) -LUISA_MAKE_TYPE_N(ulong) -LUISA_MAKE_TYPE_N(half) -LUISA_MAKE_TYPE_N(double) - -#undef LUISA_MAKE_TYPE_N - -/// make float2x2 -[[nodiscard]] constexpr auto make_float2x2(float s = 1.0f) noexcept { - return float2x2{float2{s, 0.0f}, - float2{0.0f, s}}; -} - -/// make float2x2 -[[nodiscard]] constexpr auto make_float2x2( - float m00, float m01, - float m10, float m11) noexcept { - return float2x2{float2{m00, m01}, - float2{m10, m11}}; -} - -/// make float2x2 -[[nodiscard]] constexpr auto make_float2x2(float2 c0, float2 c1) noexcept { - return float2x2{c0, c1}; -} - -/// make float2x2 -[[nodiscard]] constexpr auto make_float2x2(float2x2 m) noexcept { - return m; -} - -/// make float2x2 -[[nodiscard]] constexpr auto make_float2x2(float3x3 m) noexcept { - return float2x2{float2{m[0].x, m[0].y}, - float2{m[1].x, m[1].y}}; -} - -/// make float2x2 -[[nodiscard]] constexpr auto make_float2x2(float4x4 m) noexcept { - return float2x2{float2{m[0].x, m[0].y}, - float2{m[1].x, m[1].y}}; -} - -/// make float3x3 -[[nodiscard]] constexpr auto make_float3x3(float s = 1.0f) noexcept { - return float3x3{float3{s, 0.0f, 0.0f}, - float3{0.0f, s, 0.0f}, - float3{0.0f, 0.0f, s}}; -} - -/// make float3x3 -[[nodiscard]] constexpr auto make_float3x3(float3 c0, float3 c1, float3 c2) noexcept { - return float3x3{c0, c1, c2}; -} - -/// make float3x3 -[[nodiscard]] constexpr auto make_float3x3( - float m00, float m01, float m02, - float m10, float m11, float m12, - float m20, float m21, float m22) noexcept { - return float3x3{float3{m00, m01, m02}, - float3{m10, m11, m12}, - float3{m20, m21, m22}}; -} - -/// make float3x3 -[[nodiscard]] constexpr auto make_float3x3(float2x2 m) noexcept { - return float3x3{make_float3(m[0], 0.0f), - make_float3(m[1], 0.0f), - make_float3(0.f, 0.f, 1.0f)}; -} - -/// make float3x3 -[[nodiscard]] constexpr auto make_float3x3(float3x3 m) noexcept { - return m; -} - -/// make float3x3 -[[nodiscard]] constexpr auto make_float3x3(float4x4 m) noexcept { - return float3x3{make_float3(m[0]), - make_float3(m[1]), - make_float3(m[2])}; -} - -/// make float4x4 -[[nodiscard]] constexpr auto make_float4x4(float s = 1.0f) noexcept { - return float4x4{float4{s, 0.0f, 0.0f, 0.0f}, - float4{0.0f, s, 0.0f, 0.0f}, - float4{0.0f, 0.0f, s, 0.0f}, - float4{0.0f, 0.0f, 0.0f, s}}; -} - -/// make float4x4 -[[nodiscard]] constexpr auto make_float4x4(float4 c0, float4 c1, float4 c2, float4 c3) noexcept { - return float4x4{c0, c1, c2, c3}; -} - -/// make float4x4 -[[nodiscard]] constexpr auto make_float4x4( - float m00, float m01, float m02, float m03, - float m10, float m11, float m12, float m13, - float m20, float m21, float m22, float m23, - float m30, float m31, float m32, float m33) noexcept { - return float4x4{float4{m00, m01, m02, m03}, - float4{m10, m11, m12, m13}, - float4{m20, m21, m22, m23}, - float4{m30, m31, m32, m33}}; -} - -/// make float4x4 -[[nodiscard]] constexpr auto make_float4x4(float2x2 m) noexcept { - return float4x4{make_float4(m[0], 0.0f, 0.0f), - make_float4(m[1], 0.0f, 0.0f), - float4{0.0f, 0.0f, 1.0f, 0.0f}, - float4{0.0f, 0.0f, 0.0f, 1.0f}}; -} - -/// make float4x4 -[[nodiscard]] constexpr auto make_float4x4(float3x3 m) noexcept { - return float4x4{make_float4(m[0], 0.0f), - make_float4(m[1], 0.0f), - make_float4(m[2], 0.0f), - float4{0.0f, 0.0f, 0.0f, 1.0f}}; -} - -/// make float4x4 -[[nodiscard]] constexpr auto make_float4x4(float4x4 m) noexcept { - return m; -} - -}// namespace luisa - -//template -//constexpr auto operator*(std::array a, float s) noexcept { -// std::array r; -// for (auto i = 0u; i < N; i++) { r[i] = a[i] * s; } -// return a; -//} -// -//template -//constexpr auto operator*(float s, std::array a) noexcept { -// return a * s; -//} -// -//template -//constexpr auto operator*(std::array lhs, std::array rhs) noexcept { -// std::array r; -// for (auto i = 0u; i < N; i++) { r[i] = lhs[i] * rhs[i]; } -// return r; -//} -// -//template -//constexpr auto operator+(std::array lhs, std::array rhs) noexcept { -// std::array r; -// for (auto i = 0u; i < N; i++) { r[i] = lhs[i] + rhs[i]; } -// return r; -//} -// -//template -//constexpr auto operator-(std::array lhs, std::array rhs) noexcept { -// std::array r; -// for (auto i = 0u; i < N; i++) { r[i] = lhs[i] - rhs[i]; } -// return r; -//} -// -//template -//constexpr auto operator*(std::array, N> m, float s) noexcept { -// std::array, N> r; -// for (auto i = 0u; i < N; i++) { r[i] = m[i] * s; } -//} -// -//template -//constexpr auto operator*(float s, std::array, N> m) noexcept { -// return m * s; -//} -// -//template -//constexpr auto operator*(std::array, N> m, std::array v) noexcept { -// std::array r{}; -// for (auto i = 0u; i < N; i++) { r = r + m[i] * v[i]; } -//} -// -//template -//constexpr auto operator*(std::array, N> lhs, std::array, P> rhs) noexcept { -// std::array, P> r; -// for (auto i = 0u; i < P; i++) { r[i] = lhs * rhs[i]; } -// return r; -//} -// -//template -//constexpr auto operator+(std::array, N> lhs, std::array, N> rhs) noexcept { -// std::array, N> r; -// for (auto i = 0u; i < N; i++) { r[i] = lhs + rhs[i]; } -// return r; -//} -// -//template -//constexpr auto operator-(std::array, N> lhs, std::array, N> rhs) noexcept { -// std::array, N> r; -// for (auto i = 0u; i < N; i++) { r[i] = lhs - rhs[i]; } -// return r; -//} +#pragma once + +#include +#include + +#include +#include + +namespace luisa { + +// vectors +namespace detail { + +template +struct vector_alignment { + static constexpr size_t _a = sizeof(T) * (N == 3 ? 4 : N); + static constexpr size_t value = _a > 16u ? 16u : _a; +}; +template +static constexpr size_t vector_alignment_v = vector_alignment::value; + +/// Vector storage only allows size of 2, 3, 4 +template +struct VectorStorage { + static_assert(always_false_v, "Invalid vector storage"); +}; + +/// Vector storage of size 2 +template +struct alignas(vector_alignment_v) VectorStorage { + T x, y; + explicit constexpr VectorStorage(T s = {}) noexcept : x{s}, y{s} {} + constexpr VectorStorage(T x, T y) noexcept : x{x}, y{y} {} +#include +}; + +/// Vector storage of size 3 +template +struct alignas(vector_alignment_v) VectorStorage { + T x, y, z; + explicit constexpr VectorStorage(T s = {}) noexcept : x{s}, y{s}, z{s} {} + constexpr VectorStorage(T x, T y, T z) noexcept : x{x}, y{y}, z{z} {} +#include +}; + +/// Vector storage of size 4 +template +struct alignas(vector_alignment_v) VectorStorage { + T x, y, z, w; + explicit constexpr VectorStorage(T s = {}) noexcept : x{s}, y{s}, z{s}, w{s} {} + constexpr VectorStorage(T x, T y, T z, T w) noexcept : x{x}, y{y}, z{z}, w{w} {} +#include +}; + +}// namespace detail + +/** + * @brief Vector class + * + * We only support vector of size 2, 3, 4 and type bool, float, half, 16/32/64-bit int/uint. + * Any other kind of template parameters will fail on compilation. + * + * @tparam T bool/float/int/uint + * @tparam N 2/3/4 + */ +template +struct Vector : public detail::VectorStorage { + static constexpr auto dimension = N; + static Vector zero() noexcept { return Vector(static_cast(0)); } + static Vector one() noexcept { return Vector(static_cast(1)); } + using value_type = T; + using Storage = detail::VectorStorage; + static_assert(is_scalar_v, "Invalid vector type"); + static_assert(N == 2 || N == 3 || N == 4, "Invalid vector dimension"); + using Storage::VectorStorage; + [[nodiscard]] constexpr T &operator[](size_t index) noexcept { return (&(this->x))[index]; } + [[nodiscard]] constexpr const T &operator[](size_t index) const noexcept { return (&(this->x))[index]; } +}; + +template +struct hash> { + using is_avalanching = void; + [[nodiscard]] uint64_t operator()(const Vector &v, + uint64_t seed = hash64_default_seed) const noexcept { + return hash64(&v, sizeof(T) * N, seed); + } +}; + +/** + * @brief Make vector types of size 2, 3, 4 + * + * Ex. LUISA_MAKE_VECTOR_TYPES(int) -> int2, int3, int4 + */ +#define LUISA_MAKE_VECTOR_TYPES(T) \ + using T##2 = Vector; \ + using T##3 = Vector; \ + using T##4 = Vector; + +LUISA_MAKE_VECTOR_TYPES(bool) + +LUISA_MAKE_VECTOR_TYPES(short) +LUISA_MAKE_VECTOR_TYPES(ushort) + +LUISA_MAKE_VECTOR_TYPES(byte) +LUISA_MAKE_VECTOR_TYPES(ubyte) + +LUISA_MAKE_VECTOR_TYPES(int) +LUISA_MAKE_VECTOR_TYPES(uint) + +LUISA_MAKE_VECTOR_TYPES(ulong) +LUISA_MAKE_VECTOR_TYPES(slong) + +LUISA_MAKE_VECTOR_TYPES(half) +LUISA_MAKE_VECTOR_TYPES(float) +LUISA_MAKE_VECTOR_TYPES(double) + +#undef LUISA_MAKE_VECTOR_TYPES + +/// Matrix only allows size of 2, 3, 4 +template +struct Matrix { + static_assert(always_false_v>, "Invalid matrix type"); +}; + +/// 2x2 matrix +template<> +struct Matrix<2> { + + float2 cols[2]; + + constexpr Matrix() noexcept + : cols{float2{1.0f, 0.0f}, float2{0.0f, 1.0f}} {} + + constexpr Matrix(const float2 c0, const float2 c1) noexcept + : cols{c0, c1} {} + + static constexpr Matrix eye(const float c) noexcept { + return Matrix{ + float2{c, 0.0f}, + float2{0.0f, c}}; + } + + static constexpr Matrix fill(const float c) noexcept { + return Matrix{ + float2{c, c}, + float2{c, c}}; + } + + [[nodiscard]] constexpr float2 &operator[](size_t i) noexcept { return cols[i]; } + [[nodiscard]] constexpr const float2 &operator[](size_t i) const noexcept { return cols[i]; } +}; + +/// 3x3 matrix +template<> +struct Matrix<3> { + + float3 cols[3]; + + constexpr Matrix() noexcept + : cols{float3{1.0f, 0.0f, 0.0f}, float3{0.0f, 1.0f, 0.0f}, float3{0.0f, 0.0f, 1.0f}} {} + + constexpr Matrix(const float3 c0, const float3 c1, const float3 c2) noexcept + : cols{c0, c1, c2} {} + + static constexpr Matrix eye(const float c) noexcept { + return Matrix{ + float3{c, 0.0f, 0.0f}, + float3{0.0f, c, 0.0f}, + float3{0.0f, 0.0f, c}}; + } + + static constexpr Matrix fill(const float c) noexcept { + return Matrix{ + float3{c, c, c}, + float3{c, c, c}, + float3{c, c, c}}; + } + + [[nodiscard]] constexpr float3 &operator[](size_t i) noexcept { return cols[i]; } + [[nodiscard]] constexpr const float3 &operator[](size_t i) const noexcept { return cols[i]; } +}; + +/// 4x4 matrix +template<> +struct Matrix<4> { + + float4 cols[4]; + + constexpr Matrix() noexcept + : cols{float4{1.0f, 0.0f, 0.0f, 0.0f}, + float4{0.0f, 1.0f, 0.0f, 0.0f}, + float4{0.0f, 0.0f, 1.0f, 0.0f}, + float4{0.0f, 0.0f, 0.0f, 1.0f}} {} + + constexpr Matrix(const float4 c0, const float4 c1, const float4 c2, const float4 c3) noexcept + : cols{c0, c1, c2, c3} {} + + static constexpr Matrix eye(const float c) noexcept { + return Matrix{ + float4{c, 0.0f, 0.0f, 0.0f}, + float4{0.0f, c, 0.0f, 0.0f}, + float4{0.0f, 0.0f, c, 0.0f}, + float4{0.0f, 0.0f, 0.0f, c}}; + } + + static constexpr Matrix fill(const float c) noexcept { + return Matrix{ + float4{c, c, c, c}, + float4{c, c, c, c}, + float4{c, c, c, c}, + float4{c, c, c, c}}; + } + + [[nodiscard]] constexpr float4 &operator[](size_t i) noexcept { return cols[i]; } + [[nodiscard]] constexpr const float4 &operator[](size_t i) const noexcept { return cols[i]; } +}; + +template +struct hash> { + using is_avalanching = void; + [[nodiscard]] uint64_t operator()(Matrix m, uint64_t seed = hash64_default_seed) const noexcept { + std::array data{}; + for (size_t i = 0u; i < N; i++) { + for (size_t j = 0u; j < N; j++) { + data[i * N + j] = m[i][j]; + } + } + return hash64(data.data(), data.size() * sizeof(float), seed); + } +}; + +using float2x2 = Matrix<2>; +using float3x3 = Matrix<3>; +using float4x4 = Matrix<4>; + +using basic_types = std::tuple< + bool, float, int, uint, short, ushort, slong, ulong, half, double, byte, ubyte, + bool2, float2, int2, uint2, short2, ushort2, byte2, ubyte2, slong2, ulong2, half2, double2, + bool3, float3, int3, uint3, short3, ushort3, byte3, ubyte3, slong3, ulong3, half3, double3, + bool4, float4, int4, uint4, short4, ushort4, byte4, ubyte4, slong4, ulong4, half4, double4, + float2x2, float3x3, float4x4>; + +/// any of bool2 is true +[[nodiscard]] constexpr auto any(const bool2 v) noexcept { return v.x || v.y; } +/// any of bool3 is true +[[nodiscard]] constexpr auto any(const bool3 v) noexcept { return v.x || v.y || v.z; } +/// any of bool4 is true +[[nodiscard]] constexpr auto any(const bool4 v) noexcept { return v.x || v.y || v.z || v.w; } + +/// all of bool2 is true +[[nodiscard]] constexpr auto all(const bool2 v) noexcept { return v.x && v.y; } +/// all of bool3 is true +[[nodiscard]] constexpr auto all(const bool3 v) noexcept { return v.x && v.y && v.z; } +/// all of bool4 is true +[[nodiscard]] constexpr auto all(const bool4 v) noexcept { return v.x && v.y && v.z && v.w; } + +/// none of bool2 is true +[[nodiscard]] constexpr auto none(const bool2 v) noexcept { return !any(v); } +/// none of bool3 is true +[[nodiscard]] constexpr auto none(const bool3 v) noexcept { return !any(v); } +/// none of bool4 is true +[[nodiscard]] constexpr auto none(const bool4 v) noexcept { return !any(v); } + +}// namespace luisa + +/// Unary plus operator of vector. Bool vector is not allowed. +template>, int> = 0> +[[nodiscard]] constexpr auto operator+(const luisa::Vector v) noexcept { return v; } + +/// Unary minus operator of vector. Bool vector is not allowed. +template>, int> = 0> +[[nodiscard]] constexpr auto operator-(const luisa::Vector v) noexcept { + using R = luisa::Vector; + if constexpr (N == 2) { + return R{static_cast(-v.x), static_cast(-v.y)}; + } else if constexpr (N == 3) { + return R{static_cast(-v.x), static_cast(-v.y), static_cast(-v.z)}; + } else { + return R{static_cast(-v.x), static_cast(-v.y), static_cast(-v.z), static_cast(-v.w)}; + } +} + +/// Unary not operator of vector +template +[[nodiscard]] constexpr auto operator!(const luisa::Vector v) noexcept { + if constexpr (N == 2u) { + return luisa::bool2{!v.x, !v.y}; + } else if constexpr (N == 3u) { + return luisa::bool3{!v.x, !v.y, !v.z}; + } else { + return luisa::bool4{!v.x, !v.y, !v.z, !v.w}; + } +} + +/// Unary xor operator of vector. Only int vector is allowed. +template, int> = 0> +[[nodiscard]] constexpr auto operator~(const luisa::Vector v) noexcept { + using R = luisa::Vector; + if constexpr (N == 2) { + return R{static_cast(~v.x), static_cast(~v.y)}; + } else if constexpr (N == 3) { + return R{static_cast(~v.x), static_cast(~v.y), static_cast(~v.z)}; + } else { + return R{static_cast(~v.x), static_cast(~v.y), static_cast(~v.z), static_cast(~v.w)}; + } +} + +/// Binary & Assignment operators +#define LUISA_MAKE_VECTOR_BINARY_OPERATOR(op, ...) \ + template = 0> \ + [[nodiscard]] constexpr auto operator op( \ + luisa::Vector lhs, luisa::Vector rhs) noexcept { \ + if constexpr (N == 2) { \ + return luisa::Vector{ \ + static_cast(lhs.x op rhs.x), \ + static_cast(lhs.y op rhs.y)}; \ + } else if constexpr (N == 3) { \ + return luisa::Vector{ \ + static_cast(lhs.x op rhs.x), \ + static_cast(lhs.y op rhs.y), \ + static_cast(lhs.z op rhs.z)}; \ + } else { \ + return luisa::Vector{ \ + static_cast(lhs.x op rhs.x), \ + static_cast(lhs.y op rhs.y), \ + static_cast(lhs.z op rhs.z), \ + static_cast(lhs.w op rhs.w)}; \ + } \ + } \ + template = 0> \ + [[nodiscard]] constexpr auto operator op(luisa::Vector lhs, T rhs) noexcept { \ + return lhs op luisa::Vector{rhs}; \ + } \ + template = 0> \ + [[nodiscard]] constexpr auto operator op(T lhs, luisa::Vector rhs) noexcept { \ + return luisa::Vector{lhs} op rhs; \ + } +LUISA_MAKE_VECTOR_BINARY_OPERATOR(+, std::negation_v>) +LUISA_MAKE_VECTOR_BINARY_OPERATOR(-, std::negation_v>) +LUISA_MAKE_VECTOR_BINARY_OPERATOR(*, std::negation_v>) +LUISA_MAKE_VECTOR_BINARY_OPERATOR(/, std::negation_v>) +LUISA_MAKE_VECTOR_BINARY_OPERATOR(%, luisa::is_integral_v) +LUISA_MAKE_VECTOR_BINARY_OPERATOR(<<, luisa::is_integral_v) +LUISA_MAKE_VECTOR_BINARY_OPERATOR(>>, luisa::is_integral_v) +LUISA_MAKE_VECTOR_BINARY_OPERATOR(|, std::negation_v>) +LUISA_MAKE_VECTOR_BINARY_OPERATOR(&, std::negation_v>) +LUISA_MAKE_VECTOR_BINARY_OPERATOR(^, std::negation_v>) + +/// Binary logic operators +#define LUISA_MAKE_VECTOR_LOGIC_OPERATOR(op, ...) \ + template = 0> \ + [[nodiscard]] constexpr auto operator op( \ + luisa::Vector lhs, luisa::Vector rhs) noexcept { \ + if constexpr (N == 2) { \ + return luisa::bool2{ \ + lhs.x op rhs.x, \ + lhs.y op rhs.y}; \ + } else if constexpr (N == 3) { \ + return luisa::bool3{ \ + lhs.x op rhs.x, \ + lhs.y op rhs.y, \ + lhs.z op rhs.z}; \ + } else { \ + return luisa::bool4{ \ + lhs.x op rhs.x, \ + lhs.y op rhs.y, \ + lhs.z op rhs.z, \ + lhs.w op rhs.w}; \ + } \ + } \ + template = 0> \ + [[nodiscard]] constexpr auto operator op(luisa::Vector lhs, T rhs) noexcept { \ + return lhs op luisa::Vector{rhs}; \ + } \ + template = 0> \ + [[nodiscard]] constexpr auto operator op(T lhs, luisa::Vector rhs) noexcept { \ + return luisa::Vector{lhs} op rhs; \ + } +LUISA_MAKE_VECTOR_LOGIC_OPERATOR(||, luisa::is_boolean_v) +LUISA_MAKE_VECTOR_LOGIC_OPERATOR(&&, luisa::is_boolean_v) +LUISA_MAKE_VECTOR_LOGIC_OPERATOR(==, true) +LUISA_MAKE_VECTOR_LOGIC_OPERATOR(!=, true) +LUISA_MAKE_VECTOR_LOGIC_OPERATOR(<, std::negation_v>) +LUISA_MAKE_VECTOR_LOGIC_OPERATOR(>, std::negation_v>) +LUISA_MAKE_VECTOR_LOGIC_OPERATOR(<=, std::negation_v>) +LUISA_MAKE_VECTOR_LOGIC_OPERATOR(>=, std::negation_v>) + +/// Assign operators +#define LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(op, ...) \ + template = 0> \ + constexpr decltype(auto) operator op( \ + luisa::Vector &lhs, luisa::Vector rhs) noexcept { \ + lhs.x op rhs.x; \ + lhs.y op rhs.y; \ + if constexpr (N >= 3) { lhs.z op rhs.z; } \ + if constexpr (N == 4) { lhs.w op rhs.w; } \ + return (lhs); \ + } \ + template = 0> \ + constexpr decltype(auto) operator op( \ + luisa::Vector &lhs, T rhs) noexcept { \ + return (lhs op luisa::Vector{rhs}); \ + } +LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(+=, std::negation_v>) +LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(-=, std::negation_v>) +LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(*=, std::negation_v>) +LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(/=, std::negation_v>) +LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(%=, luisa::is_integral_v) +LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(<<=, luisa::is_integral_v) +LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(>>=, luisa::is_integral_v) +LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(|=, std::negation_v>) +LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(&=, std::negation_v>) +LUISA_MAKE_VECTOR_ASSIGN_OPERATOR(^=, std::negation_v>) + +#undef LUISA_MAKE_VECTOR_BINARY_OPERATOR +#undef LUISA_MAKE_VECTOR_LOGIC_OPERATOR +#undef LUISA_MAKE_VECTOR_ASSIGN_OPERATOR + +/// float2x2 multiplied by float +[[nodiscard]] constexpr auto operator*(const luisa::float2x2 m, float s) noexcept { + return luisa::float2x2{m[0] * s, m[1] * s}; +} + +/// float2x2 multiplied by float +[[nodiscard]] constexpr auto operator*(float s, const luisa::float2x2 m) noexcept { + return m * s; +} + +/// float2x2 divided by float +[[nodiscard]] constexpr auto operator/(const luisa::float2x2 m, float s) noexcept { + return m * (1.0f / s); +} + +/// float2x2 dot float2 +[[nodiscard]] constexpr auto operator*(const luisa::float2x2 m, const luisa::float2 v) noexcept { + return v.x * m[0] + v.y * m[1]; +} + +/// float2x2 multiply(matmul) +[[nodiscard]] constexpr auto operator*(const luisa::float2x2 lhs, const luisa::float2x2 rhs) noexcept { + return luisa::float2x2{lhs * rhs[0], lhs * rhs[1]}; +} + +/// float2x2 plus +[[nodiscard]] constexpr auto operator+(const luisa::float2x2 lhs, const luisa::float2x2 rhs) noexcept { + return luisa::float2x2{lhs[0] + rhs[0], lhs[1] + rhs[1]}; +} + +/// float2x2 minus +[[nodiscard]] constexpr auto operator-(const luisa::float2x2 lhs, const luisa::float2x2 rhs) noexcept { + return luisa::float2x2{lhs[0] - rhs[0], lhs[1] - rhs[1]}; +} + +/// float3x3 multiplied by float +[[nodiscard]] constexpr auto operator*(const luisa::float3x3 m, float s) noexcept { + return luisa::float3x3{m[0] * s, m[1] * s, m[2] * s}; +} + +/// float3x3 multiplied by float +[[nodiscard]] constexpr auto operator*(float s, const luisa::float3x3 m) noexcept { + return m * s; +} + +/// float 3x3 divided by float +[[nodiscard]] constexpr auto operator/(const luisa::float3x3 m, float s) noexcept { + return m * (1.0f / s); +} + +/// float3x3 dot float3 +[[nodiscard]] constexpr auto operator*(const luisa::float3x3 m, const luisa::float3 v) noexcept { + return v.x * m[0] + v.y * m[1] + v.z * m[2]; +} + +/// float3x3 multiply(matmul) +[[nodiscard]] constexpr auto operator*(const luisa::float3x3 lhs, const luisa::float3x3 rhs) noexcept { + return luisa::float3x3{lhs * rhs[0], lhs * rhs[1], lhs * rhs[2]}; +} + +/// float3x3 plus +[[nodiscard]] constexpr auto operator+(const luisa::float3x3 lhs, const luisa::float3x3 rhs) noexcept { + return luisa::float3x3{lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2]}; +} + +/// float3x3 minus +[[nodiscard]] constexpr auto operator-(const luisa::float3x3 lhs, const luisa::float3x3 rhs) noexcept { + return luisa::float3x3{lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2]}; +} + +/// float4x4 multiplied by float +[[nodiscard]] constexpr auto operator*(const luisa::float4x4 m, float s) noexcept { + return luisa::float4x4{m[0] * s, m[1] * s, m[2] * s, m[3] * s}; +} + +/// float4x4 multiplied by float +[[nodiscard]] constexpr auto operator*(float s, const luisa::float4x4 m) noexcept { + return m * s; +} + +/// float4x4 divided by float +[[nodiscard]] constexpr auto operator/(const luisa::float4x4 m, float s) noexcept { + return m * (1.0f / s); +} + +/// floa4x4 dot float4 +[[nodiscard]] constexpr auto operator*(const luisa::float4x4 m, const luisa::float4 v) noexcept { + return v.x * m[0] + v.y * m[1] + v.z * m[2] + v.w * m[3]; +} + +/// float4x4 multiply(matmul) +[[nodiscard]] constexpr auto operator*(const luisa::float4x4 lhs, const luisa::float4x4 rhs) noexcept { + return luisa::float4x4{lhs * rhs[0], lhs * rhs[1], lhs * rhs[2], lhs * rhs[3]}; +} + +/// float4x4 plus +[[nodiscard]] constexpr auto operator+(const luisa::float4x4 lhs, const luisa::float4x4 rhs) noexcept { + return luisa::float4x4{lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2], lhs[3] + rhs[3]}; +} + +/// float4x4 minus +[[nodiscard]] constexpr auto operator-(const luisa::float4x4 lhs, const luisa::float4x4 rhs) noexcept { + return luisa::float4x4{lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2], lhs[3] - rhs[3]}; +} + +namespace luisa { + +/// make_typeN definitions +#define LUISA_MAKE_TYPE_N(type) \ + [[nodiscard]] constexpr auto make_##type##2(type s = {}) noexcept { return type##2(s); } \ + [[nodiscard]] constexpr auto make_##type##2(type x, type y) noexcept { return type##2(x, y); } \ + template \ + [[nodiscard]] constexpr auto make_##type##2(Vector v) noexcept { \ + return type##2( \ + static_cast(v.x), \ + static_cast(v.y)); \ + } \ + [[nodiscard]] constexpr auto make_##type##2(type##3 v) noexcept { return type##2(v.x, v.y); } \ + [[nodiscard]] constexpr auto make_##type##2(type##4 v) noexcept { return type##2(v.x, v.y); } \ + \ + [[nodiscard]] constexpr auto make_##type##3(type s = {}) noexcept { return type##3(s); } \ + [[nodiscard]] constexpr auto make_##type##3(type x, type y, type z) noexcept { return type##3(x, y, z); } \ + template \ + [[nodiscard]] constexpr auto make_##type##3(Vector v) noexcept { \ + return type##3( \ + static_cast(v.x), \ + static_cast(v.y), \ + static_cast(v.z)); \ + } \ + [[nodiscard]] constexpr auto make_##type##3(type##2 v, type z) noexcept { return type##3(v.x, v.y, z); } \ + [[nodiscard]] constexpr auto make_##type##3(type x, type##2 v) noexcept { return type##3(x, v.x, v.y); } \ + [[nodiscard]] constexpr auto make_##type##3(type##4 v) noexcept { return type##3(v.x, v.y, v.z); } \ + \ + [[nodiscard]] constexpr auto make_##type##4(type s = {}) noexcept { return type##4(s); } \ + [[nodiscard]] constexpr auto make_##type##4(type x, type y, type z, type w) noexcept { return type##4(x, y, z, w); } \ + template \ + [[nodiscard]] constexpr auto make_##type##4(Vector v) noexcept { \ + return type##4( \ + static_cast(v.x), \ + static_cast(v.y), \ + static_cast(v.z), \ + static_cast(v.w)); \ + } \ + [[nodiscard]] constexpr auto make_##type##4(type##2 v, type z, type w) noexcept { return type##4(v.x, v.y, z, w); } \ + [[nodiscard]] constexpr auto make_##type##4(type x, type##2 v, type w) noexcept { return type##4(x, v.x, v.y, w); } \ + [[nodiscard]] constexpr auto make_##type##4(type x, type y, type##2 v) noexcept { return type##4(x, y, v.x, v.y); } \ + [[nodiscard]] constexpr auto make_##type##4(type##2 xy, type##2 zw) noexcept { return type##4(xy.x, xy.y, zw.x, zw.y); } \ + [[nodiscard]] constexpr auto make_##type##4(type##3 v, type w) noexcept { return type##4(v.x, v.y, v.z, w); } \ + [[nodiscard]] constexpr auto make_##type##4(type x, type##3 v) noexcept { return type##4(x, v.x, v.y, v.z); } + +LUISA_MAKE_TYPE_N(bool) +LUISA_MAKE_TYPE_N(float) +LUISA_MAKE_TYPE_N(int) +LUISA_MAKE_TYPE_N(uint) +LUISA_MAKE_TYPE_N(byte) +LUISA_MAKE_TYPE_N(ubyte) +LUISA_MAKE_TYPE_N(short) +LUISA_MAKE_TYPE_N(ushort) +LUISA_MAKE_TYPE_N(slong) +LUISA_MAKE_TYPE_N(ulong) +LUISA_MAKE_TYPE_N(half) +LUISA_MAKE_TYPE_N(double) + +#undef LUISA_MAKE_TYPE_N + +/// make float2x2 +[[nodiscard]] constexpr auto make_float2x2(float s = 1.0f) noexcept { + return float2x2{float2{s, 0.0f}, + float2{0.0f, s}}; +} + +/// make float2x2 +[[nodiscard]] constexpr auto make_float2x2( + float m00, float m01, + float m10, float m11) noexcept { + return float2x2{float2{m00, m01}, + float2{m10, m11}}; +} + +/// make float2x2 +[[nodiscard]] constexpr auto make_float2x2(float2 c0, float2 c1) noexcept { + return float2x2{c0, c1}; +} + +/// make float2x2 +[[nodiscard]] constexpr auto make_float2x2(float2x2 m) noexcept { + return m; +} + +/// make float2x2 +[[nodiscard]] constexpr auto make_float2x2(float3x3 m) noexcept { + return float2x2{float2{m[0].x, m[0].y}, + float2{m[1].x, m[1].y}}; +} + +/// make float2x2 +[[nodiscard]] constexpr auto make_float2x2(float4x4 m) noexcept { + return float2x2{float2{m[0].x, m[0].y}, + float2{m[1].x, m[1].y}}; +} + +/// make float3x3 +[[nodiscard]] constexpr auto make_float3x3(float s = 1.0f) noexcept { + return float3x3{float3{s, 0.0f, 0.0f}, + float3{0.0f, s, 0.0f}, + float3{0.0f, 0.0f, s}}; +} + +/// make float3x3 +[[nodiscard]] constexpr auto make_float3x3(float3 c0, float3 c1, float3 c2) noexcept { + return float3x3{c0, c1, c2}; +} + +/// make float3x3 +[[nodiscard]] constexpr auto make_float3x3( + float m00, float m01, float m02, + float m10, float m11, float m12, + float m20, float m21, float m22) noexcept { + return float3x3{float3{m00, m01, m02}, + float3{m10, m11, m12}, + float3{m20, m21, m22}}; +} + +/// make float3x3 +[[nodiscard]] constexpr auto make_float3x3(float2x2 m) noexcept { + return float3x3{make_float3(m[0], 0.0f), + make_float3(m[1], 0.0f), + make_float3(0.f, 0.f, 1.0f)}; +} + +/// make float3x3 +[[nodiscard]] constexpr auto make_float3x3(float3x3 m) noexcept { + return m; +} + +/// make float3x3 +[[nodiscard]] constexpr auto make_float3x3(float4x4 m) noexcept { + return float3x3{make_float3(m[0]), + make_float3(m[1]), + make_float3(m[2])}; +} + +/// make float4x4 +[[nodiscard]] constexpr auto make_float4x4(float s = 1.0f) noexcept { + return float4x4{float4{s, 0.0f, 0.0f, 0.0f}, + float4{0.0f, s, 0.0f, 0.0f}, + float4{0.0f, 0.0f, s, 0.0f}, + float4{0.0f, 0.0f, 0.0f, s}}; +} + +/// make float4x4 +[[nodiscard]] constexpr auto make_float4x4(float4 c0, float4 c1, float4 c2, float4 c3) noexcept { + return float4x4{c0, c1, c2, c3}; +} + +/// make float4x4 +[[nodiscard]] constexpr auto make_float4x4( + float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33) noexcept { + return float4x4{float4{m00, m01, m02, m03}, + float4{m10, m11, m12, m13}, + float4{m20, m21, m22, m23}, + float4{m30, m31, m32, m33}}; +} + +/// make float4x4 +[[nodiscard]] constexpr auto make_float4x4(float2x2 m) noexcept { + return float4x4{make_float4(m[0], 0.0f, 0.0f), + make_float4(m[1], 0.0f, 0.0f), + float4{0.0f, 0.0f, 1.0f, 0.0f}, + float4{0.0f, 0.0f, 0.0f, 1.0f}}; +} + +/// make float4x4 +[[nodiscard]] constexpr auto make_float4x4(float3x3 m) noexcept { + return float4x4{make_float4(m[0], 0.0f), + make_float4(m[1], 0.0f), + make_float4(m[2], 0.0f), + float4{0.0f, 0.0f, 0.0f, 1.0f}}; +} + +/// make float4x4 +[[nodiscard]] constexpr auto make_float4x4(float4x4 m) noexcept { + return m; +} + +}// namespace luisa + +//template +//constexpr auto operator*(std::array a, float s) noexcept { +// std::array r; +// for (auto i = 0u; i < N; i++) { r[i] = a[i] * s; } +// return a; +//} +// +//template +//constexpr auto operator*(float s, std::array a) noexcept { +// return a * s; +//} +// +//template +//constexpr auto operator*(std::array lhs, std::array rhs) noexcept { +// std::array r; +// for (auto i = 0u; i < N; i++) { r[i] = lhs[i] * rhs[i]; } +// return r; +//} +// +//template +//constexpr auto operator+(std::array lhs, std::array rhs) noexcept { +// std::array r; +// for (auto i = 0u; i < N; i++) { r[i] = lhs[i] + rhs[i]; } +// return r; +//} +// +//template +//constexpr auto operator-(std::array lhs, std::array rhs) noexcept { +// std::array r; +// for (auto i = 0u; i < N; i++) { r[i] = lhs[i] - rhs[i]; } +// return r; +//} +// +//template +//constexpr auto operator*(std::array, N> m, float s) noexcept { +// std::array, N> r; +// for (auto i = 0u; i < N; i++) { r[i] = m[i] * s; } +//} +// +//template +//constexpr auto operator*(float s, std::array, N> m) noexcept { +// return m * s; +//} +// +//template +//constexpr auto operator*(std::array, N> m, std::array v) noexcept { +// std::array r{}; +// for (auto i = 0u; i < N; i++) { r = r + m[i] * v[i]; } +//} +// +//template +//constexpr auto operator*(std::array, N> lhs, std::array, P> rhs) noexcept { +// std::array, P> r; +// for (auto i = 0u; i < P; i++) { r[i] = lhs * rhs[i]; } +// return r; +//} +// +//template +//constexpr auto operator+(std::array, N> lhs, std::array, N> rhs) noexcept { +// std::array, N> r; +// for (auto i = 0u; i < N; i++) { r[i] = lhs + rhs[i]; } +// return r; +//} +// +//template +//constexpr auto operator-(std::array, N> lhs, std::array, N> rhs) noexcept { +// std::array, N> r; +// for (auto i = 0u; i < N; i++) { r[i] = lhs - rhs[i]; } +// return r; +//} diff --git a/include/luisa/core/stl/format.h b/include/luisa/core/stl/format.h index 70de7a369..54465f2a1 100644 --- a/include/luisa/core/stl/format.h +++ b/include/luisa/core/stl/format.h @@ -7,6 +7,7 @@ #pragma warning(disable : 4996) #endif +#include // for std::copy #include #include diff --git a/include/luisa/luisa-compute.h b/include/luisa/luisa-compute.h index ddea26a02..dcae0893a 100644 --- a/include/luisa/luisa-compute.h +++ b/include/luisa/luisa-compute.h @@ -207,6 +207,7 @@ #include #include #include +#include #include #include #include diff --git a/include/luisa/runtime/rhi/pixel.h b/include/luisa/runtime/rhi/pixel.h index 0375aba8f..e79853be2 100644 --- a/include/luisa/runtime/rhi/pixel.h +++ b/include/luisa/runtime/rhi/pixel.h @@ -1,376 +1,378 @@ -#pragma once - -#include // - -#include -#include - -namespace luisa::compute { - -namespace detail { -[[noreturn]] LC_RUNTIME_API void error_pixel_invalid_format(const char *name) noexcept; -}// namespace detail - -enum struct PixelStorage : uint32_t { - - BYTE1, - BYTE2, - BYTE4, - - SHORT1, - SHORT2, - SHORT4, - - INT1, - INT2, - INT4, - - HALF1, - HALF2, - HALF4, - - FLOAT1, - FLOAT2, - FLOAT4, - - R10G10B10A2, - R11G11B10, - - BC1, - BC2, - BC3, - BC4, - BC5, - BC6, - BC7, - //TODO: ASTC -}; - -enum struct PixelFormat : uint32_t { - - R8SInt, - R8UInt, - R8UNorm, - - RG8SInt, - RG8UInt, - RG8UNorm, - - RGBA8SInt, - RGBA8UInt, - RGBA8UNorm, - - R16SInt, - R16UInt, - R16UNorm, - - RG16SInt, - RG16UInt, - RG16UNorm, - - RGBA16SInt, - RGBA16UInt, - RGBA16UNorm, - - R32SInt, - R32UInt, - - RG32SInt, - RG32UInt, - - RGBA32SInt, - RGBA32UInt, - - R16F, - RG16F, - RGBA16F, - - R32F, - RG32F, - RGBA32F, - - R10G10B10A2UInt, - R10G10B10A2UNorm, - R11G11B10F, - - BC1UNorm, - BC2UNorm, - BC3UNorm, - BC4UNorm, - BC5UNorm, - BC6HUF16, - BC7UNorm, - - //TODO: ASTC -}; - -constexpr auto pixel_storage_count = to_underlying(PixelStorage::BC7) + 1u; -constexpr auto pixel_format_count = to_underlying(PixelFormat::BC7UNorm) + 1u; - -[[nodiscard]] constexpr auto is_block_compressed(PixelStorage s) noexcept { - return luisa::to_underlying(s) >= luisa::to_underlying(PixelStorage::BC1) && - luisa::to_underlying(s) <= luisa::to_underlying(PixelStorage::BC7); -} - -[[nodiscard]] constexpr auto is_block_compressed(PixelFormat f) noexcept { - return luisa::to_underlying(f) >= luisa::to_underlying(PixelFormat::BC1UNorm) && - luisa::to_underlying(f) <= luisa::to_underlying(PixelFormat::BC7UNorm); -} - -[[nodiscard]] constexpr auto pixel_format_to_storage(PixelFormat format) noexcept { - switch (format) { - case PixelFormat::R8SInt: - case PixelFormat::R8UInt: - case PixelFormat::R8UNorm: - return PixelStorage::BYTE1; - case PixelFormat::RG8SInt: - case PixelFormat::RG8UInt: - case PixelFormat::RG8UNorm: - return PixelStorage::BYTE2; - case PixelFormat::RGBA8SInt: - case PixelFormat::RGBA8UInt: - case PixelFormat::RGBA8UNorm: - return PixelStorage::BYTE4; - case PixelFormat::R16SInt: - case PixelFormat::R16UInt: - case PixelFormat::R16UNorm: - return PixelStorage::SHORT1; - case PixelFormat::RG16SInt: - case PixelFormat::RG16UInt: - case PixelFormat::RG16UNorm: - return PixelStorage::SHORT2; - case PixelFormat::RGBA16SInt: - case PixelFormat::RGBA16UInt: - case PixelFormat::RGBA16UNorm: - return PixelStorage::SHORT4; - case PixelFormat::R32SInt: - case PixelFormat::R32UInt: - return PixelStorage::INT1; - case PixelFormat::RG32SInt: - case PixelFormat::RG32UInt: - return PixelStorage::INT2; - case PixelFormat::RGBA32SInt: - case PixelFormat::RGBA32UInt: - return PixelStorage::INT4; - case PixelFormat::R16F: - return PixelStorage::HALF1; - case PixelFormat::RG16F: - return PixelStorage::HALF2; - case PixelFormat::RGBA16F: - return PixelStorage::HALF4; - case PixelFormat::R32F: - return PixelStorage::FLOAT1; - case PixelFormat::RG32F: - return PixelStorage::FLOAT2; - case PixelFormat::RGBA32F: - return PixelStorage::FLOAT4; - case PixelFormat::BC6HUF16: - return PixelStorage::BC6; - case PixelFormat::BC7UNorm: - return PixelStorage::BC7; - case PixelFormat::BC5UNorm: - return PixelStorage::BC5; - case PixelFormat::BC4UNorm: - return PixelStorage::BC4; - case PixelFormat::BC3UNorm: - return PixelStorage::BC3; - case PixelFormat::BC2UNorm: - return PixelStorage::BC2; - case PixelFormat::BC1UNorm: - return PixelStorage::BC1; - case PixelFormat::R10G10B10A2UNorm: - case PixelFormat::R10G10B10A2UInt: - return PixelStorage::R10G10B10A2; - case PixelFormat::R11G11B10F: - return PixelStorage::R11G11B10; - default: - break; - } - return PixelStorage{}; -} -[[nodiscard]] constexpr size_t pixel_storage_align(PixelStorage storage) noexcept { - if (is_block_compressed(storage)) { - switch (storage) { - case PixelStorage::BC1: - case PixelStorage::BC4: return 8u; - case PixelStorage::BC2: - case PixelStorage::BC3: - case PixelStorage::BC5: - case PixelStorage::BC6: - case PixelStorage::BC7: return 16u; - default: break; - } - detail::error_pixel_invalid_format("unknown."); - } - switch (storage) { - case PixelStorage::BYTE1: return alignof(std::byte) * 1u; - case PixelStorage::BYTE2: return alignof(std::byte) * 2u; - case PixelStorage::BYTE4: return alignof(std::byte) * 4u; - case PixelStorage::SHORT1: return alignof(short) * 1u; - case PixelStorage::SHORT2: return alignof(short) * 2u; - case PixelStorage::SHORT4: return alignof(short) * 4u; - case PixelStorage::INT1: return alignof(int) * 1u; - case PixelStorage::INT2: return alignof(int) * 2u; - case PixelStorage::INT4: return alignof(int) * 4u; - case PixelStorage::HALF1: return alignof(short) * 1u; - case PixelStorage::HALF2: return alignof(short) * 2u; - case PixelStorage::HALF4: return alignof(short) * 4u; - case PixelStorage::FLOAT1: return alignof(float) * 1u; - case PixelStorage::FLOAT2: return alignof(float) * 2u; - case PixelStorage::FLOAT4: return alignof(float) * 4u; - case PixelStorage::R10G10B10A2: - case PixelStorage::R11G11B10: - return 4; - default: break; - } - detail::error_pixel_invalid_format("unknown"); -} -[[nodiscard]] constexpr size_t pixel_storage_size(PixelStorage storage, uint3 size) noexcept { - if (is_block_compressed(storage)) { - auto block_width = (size.x + 3u) / 4u; - auto block_height = (size.y + 3u) / 4u; - auto block_count = block_width * block_height * std::max(size.z, 1u); - switch (storage) { - case PixelStorage::BC1: - case PixelStorage::BC4: return block_count * 8u; - case PixelStorage::BC2: - case PixelStorage::BC3: - case PixelStorage::BC5: - case PixelStorage::BC6: - case PixelStorage::BC7: return block_count * 16u; - default: break; - } - detail::error_pixel_invalid_format("unknown."); - } - auto pixel_count = size.x * size.y * size.z; - switch (storage) { - case PixelStorage::BYTE1: return pixel_count * sizeof(std::byte) * 1u; - case PixelStorage::BYTE2: return pixel_count * sizeof(std::byte) * 2u; - case PixelStorage::BYTE4: return pixel_count * sizeof(std::byte) * 4u; - case PixelStorage::SHORT1: return pixel_count * sizeof(short) * 1u; - case PixelStorage::SHORT2: return pixel_count * sizeof(short) * 2u; - case PixelStorage::SHORT4: return pixel_count * sizeof(short) * 4u; - case PixelStorage::INT1: return pixel_count * sizeof(int) * 1u; - case PixelStorage::INT2: return pixel_count * sizeof(int) * 2u; - case PixelStorage::INT4: return pixel_count * sizeof(int) * 4u; - case PixelStorage::HALF1: return pixel_count * sizeof(short) * 1u; - case PixelStorage::HALF2: return pixel_count * sizeof(short) * 2u; - case PixelStorage::HALF4: return pixel_count * sizeof(short) * 4u; - case PixelStorage::FLOAT1: return pixel_count * sizeof(float) * 1u; - case PixelStorage::FLOAT2: return pixel_count * sizeof(float) * 2u; - case PixelStorage::FLOAT4: return pixel_count * sizeof(float) * 4u; - case PixelStorage::R10G10B10A2: - case PixelStorage::R11G11B10: - return pixel_count * 4; - default: break; - } - detail::error_pixel_invalid_format("unknown"); -} - -[[nodiscard]] constexpr size_t pixel_format_align(PixelFormat format) noexcept { - return pixel_storage_align(pixel_format_to_storage(format)); -} - -[[nodiscard]] constexpr auto pixel_storage_channel_count(PixelStorage storage) noexcept { - switch (storage) { - case PixelStorage::BYTE1: return 1u; - case PixelStorage::BYTE2: return 2u; - case PixelStorage::BYTE4: return 4u; - case PixelStorage::SHORT1: return 1u; - case PixelStorage::SHORT2: return 2u; - case PixelStorage::SHORT4: return 4u; - case PixelStorage::INT1: return 1u; - case PixelStorage::INT2: return 2u; - case PixelStorage::INT4: return 4u; - case PixelStorage::HALF1: return 1u; - case PixelStorage::HALF2: return 2u; - case PixelStorage::HALF4: return 4u; - case PixelStorage::FLOAT1: return 1u; - case PixelStorage::FLOAT2: return 2u; - case PixelStorage::FLOAT4: return 4u; - - case PixelStorage::R11G11B10: return 3u; - case PixelStorage::R10G10B10A2: return 4u; - - case PixelStorage::BC4: return 1u; - case PixelStorage::BC5: return 2u; - case PixelStorage::BC1: - case PixelStorage::BC6: return 3u; - case PixelStorage::BC2: - case PixelStorage::BC3: - case PixelStorage::BC7: return 4u; - default: break; - } - return 0u; -} - -template -[[nodiscard]] constexpr auto pixel_storage_to_format(PixelStorage storage) noexcept { - if constexpr (std::is_same_v) { - switch (storage) { - case PixelStorage::BYTE1: return PixelFormat::R8UNorm; - case PixelStorage::BYTE2: return PixelFormat::RG8UNorm; - case PixelStorage::BYTE4: return PixelFormat::RGBA8UNorm; - case PixelStorage::SHORT1: return PixelFormat::R16UNorm; - case PixelStorage::SHORT2: return PixelFormat::RG16UNorm; - case PixelStorage::SHORT4: return PixelFormat::RGBA16UNorm; - case PixelStorage::HALF1: return PixelFormat::R16F; - case PixelStorage::HALF2: return PixelFormat::RG16F; - case PixelStorage::HALF4: return PixelFormat::RGBA16F; - case PixelStorage::FLOAT1: return PixelFormat::R32F; - case PixelStorage::FLOAT2: return PixelFormat::RG32F; - case PixelStorage::FLOAT4: return PixelFormat::RGBA32F; - case PixelStorage::R11G11B10: return PixelFormat::R11G11B10F; - case PixelStorage::R10G10B10A2: return PixelFormat::R10G10B10A2UNorm; - case PixelStorage::BC1: return PixelFormat ::BC1UNorm; - case PixelStorage::BC2: return PixelFormat ::BC2UNorm; - case PixelStorage::BC3: return PixelFormat ::BC3UNorm; - case PixelStorage::BC4: return PixelFormat ::BC4UNorm; - case PixelStorage::BC5: return PixelFormat ::BC5UNorm; - case PixelStorage::BC6: return PixelFormat ::BC6HUF16; - case PixelStorage::BC7: return PixelFormat ::BC7UNorm; - default: detail::error_pixel_invalid_format("float"); - } - } else if constexpr (std::is_same_v) { - switch (storage) { - case PixelStorage::BYTE1: return PixelFormat::R8SInt; - case PixelStorage::BYTE2: return PixelFormat::RG8SInt; - case PixelStorage::BYTE4: return PixelFormat::RGBA8SInt; - case PixelStorage::SHORT1: return PixelFormat::R16SInt; - case PixelStorage::SHORT2: return PixelFormat::RG16SInt; - case PixelStorage::SHORT4: return PixelFormat::RGBA16SInt; - case PixelStorage::INT1: return PixelFormat::R32SInt; - case PixelStorage::INT2: return PixelFormat::RG32SInt; - case PixelStorage::INT4: return PixelFormat::RGBA32SInt; - default: detail::error_pixel_invalid_format("int"); - } - } else if constexpr (std::is_same_v) { - switch (storage) { - case PixelStorage::BYTE1: return PixelFormat::R8UInt; - case PixelStorage::BYTE2: return PixelFormat::RG8UInt; - case PixelStorage::BYTE4: return PixelFormat::RGBA8UInt; - case PixelStorage::SHORT1: return PixelFormat::R16UInt; - case PixelStorage::SHORT2: return PixelFormat::RG16UInt; - case PixelStorage::SHORT4: return PixelFormat::RGBA16UInt; - case PixelStorage::INT1: return PixelFormat::R32UInt; - case PixelStorage::INT2: return PixelFormat::RG32UInt; - case PixelStorage::INT4: return PixelFormat::RGBA32UInt; - case PixelStorage::R10G10B10A2: return PixelFormat::R10G10B10A2UInt; - default: detail::error_pixel_invalid_format("uint"); - } - } else { - static_assert(always_false_v); - } - // unreachable - return PixelFormat{}; -} - -[[nodiscard]] constexpr auto pixel_format_size(PixelFormat format, uint3 size) noexcept { - return pixel_storage_size(pixel_format_to_storage(format), size); -} - -[[nodiscard]] constexpr auto pixel_format_channel_count(PixelFormat format) noexcept { - return pixel_storage_channel_count(pixel_format_to_storage(format)); -} - -}// namespace luisa::compute +#pragma once + +#include // + +#include +#include + +namespace luisa::compute { + +namespace detail { +[[noreturn]] LC_RUNTIME_API void error_pixel_invalid_format(const char *name) noexcept; +}// namespace detail + +enum struct PixelStorage : uint32_t { + + BYTE1, + BYTE2, + BYTE4, + + SHORT1, + SHORT2, + SHORT4, + + INT1, + INT2, + INT4, + + HALF1, + HALF2, + HALF4, + + FLOAT1, + FLOAT2, + FLOAT4, + + R10G10B10A2, + R11G11B10, + + BC1, + BC2, + BC3, + BC4, + BC5, + BC6, + BC7, + //TODO: ASTC +}; + +enum struct PixelFormat : uint32_t { + + R8SInt, + R8UInt, + R8UNorm, + + RG8SInt, + RG8UInt, + RG8UNorm, + + RGBA8SInt, + RGBA8UInt, + RGBA8UNorm, + + R16SInt, + R16UInt, + R16UNorm, + + RG16SInt, + RG16UInt, + RG16UNorm, + + RGBA16SInt, + RGBA16UInt, + RGBA16UNorm, + + R32SInt, + R32UInt, + + RG32SInt, + RG32UInt, + + RGBA32SInt, + RGBA32UInt, + + R16F, + RG16F, + RGBA16F, + + R32F, + RG32F, + RGBA32F, + + R10G10B10A2UInt, + R10G10B10A2UNorm, + R11G11B10F, + + BC1UNorm, + BC2UNorm, + BC3UNorm, + BC4UNorm, + BC5UNorm, + BC6HUF16, + BC7UNorm, + + //TODO: ASTC +}; + +constexpr auto pixel_storage_count = to_underlying(PixelStorage::BC7) + 1u; +constexpr auto pixel_format_count = to_underlying(PixelFormat::BC7UNorm) + 1u; + +[[nodiscard]] constexpr auto is_block_compressed(PixelStorage s) noexcept { + return luisa::to_underlying(s) >= luisa::to_underlying(PixelStorage::BC1) && + luisa::to_underlying(s) <= luisa::to_underlying(PixelStorage::BC7); +} + +[[nodiscard]] constexpr auto is_block_compressed(PixelFormat f) noexcept { + return luisa::to_underlying(f) >= luisa::to_underlying(PixelFormat::BC1UNorm) && + luisa::to_underlying(f) <= luisa::to_underlying(PixelFormat::BC7UNorm); +} + +[[nodiscard]] constexpr auto pixel_format_to_storage(PixelFormat format) noexcept { + switch (format) { + case PixelFormat::R8SInt: + case PixelFormat::R8UInt: + case PixelFormat::R8UNorm: + return PixelStorage::BYTE1; + case PixelFormat::RG8SInt: + case PixelFormat::RG8UInt: + case PixelFormat::RG8UNorm: + return PixelStorage::BYTE2; + case PixelFormat::RGBA8SInt: + case PixelFormat::RGBA8UInt: + case PixelFormat::RGBA8UNorm: + return PixelStorage::BYTE4; + case PixelFormat::R16SInt: + case PixelFormat::R16UInt: + case PixelFormat::R16UNorm: + return PixelStorage::SHORT1; + case PixelFormat::RG16SInt: + case PixelFormat::RG16UInt: + case PixelFormat::RG16UNorm: + return PixelStorage::SHORT2; + case PixelFormat::RGBA16SInt: + case PixelFormat::RGBA16UInt: + case PixelFormat::RGBA16UNorm: + return PixelStorage::SHORT4; + case PixelFormat::R32SInt: + case PixelFormat::R32UInt: + return PixelStorage::INT1; + case PixelFormat::RG32SInt: + case PixelFormat::RG32UInt: + return PixelStorage::INT2; + case PixelFormat::RGBA32SInt: + case PixelFormat::RGBA32UInt: + return PixelStorage::INT4; + case PixelFormat::R16F: + return PixelStorage::HALF1; + case PixelFormat::RG16F: + return PixelStorage::HALF2; + case PixelFormat::RGBA16F: + return PixelStorage::HALF4; + case PixelFormat::R32F: + return PixelStorage::FLOAT1; + case PixelFormat::RG32F: + return PixelStorage::FLOAT2; + case PixelFormat::RGBA32F: + return PixelStorage::FLOAT4; + case PixelFormat::BC6HUF16: + return PixelStorage::BC6; + case PixelFormat::BC7UNorm: + return PixelStorage::BC7; + case PixelFormat::BC5UNorm: + return PixelStorage::BC5; + case PixelFormat::BC4UNorm: + return PixelStorage::BC4; + case PixelFormat::BC3UNorm: + return PixelStorage::BC3; + case PixelFormat::BC2UNorm: + return PixelStorage::BC2; + case PixelFormat::BC1UNorm: + return PixelStorage::BC1; + case PixelFormat::R10G10B10A2UNorm: + case PixelFormat::R10G10B10A2UInt: + return PixelStorage::R10G10B10A2; + case PixelFormat::R11G11B10F: + return PixelStorage::R11G11B10; + default: + break; + } + return PixelStorage{}; +} + +[[nodiscard]] constexpr size_t pixel_storage_align(PixelStorage storage) noexcept { + if (is_block_compressed(storage)) { + switch (storage) { + case PixelStorage::BC1: + case PixelStorage::BC4: return 8u; + case PixelStorage::BC2: + case PixelStorage::BC3: + case PixelStorage::BC5: + case PixelStorage::BC6: + case PixelStorage::BC7: return 16u; + default: break; + } + detail::error_pixel_invalid_format("unknown."); + } + switch (storage) { + case PixelStorage::BYTE1: return alignof(std::byte) * 1u; + case PixelStorage::BYTE2: return alignof(std::byte) * 2u; + case PixelStorage::BYTE4: return alignof(std::byte) * 4u; + case PixelStorage::SHORT1: return alignof(short) * 1u; + case PixelStorage::SHORT2: return alignof(short) * 2u; + case PixelStorage::SHORT4: return alignof(short) * 4u; + case PixelStorage::INT1: return alignof(int) * 1u; + case PixelStorage::INT2: return alignof(int) * 2u; + case PixelStorage::INT4: return alignof(int) * 4u; + case PixelStorage::HALF1: return alignof(short) * 1u; + case PixelStorage::HALF2: return alignof(short) * 2u; + case PixelStorage::HALF4: return alignof(short) * 4u; + case PixelStorage::FLOAT1: return alignof(float) * 1u; + case PixelStorage::FLOAT2: return alignof(float) * 2u; + case PixelStorage::FLOAT4: return alignof(float) * 4u; + case PixelStorage::R10G10B10A2: + case PixelStorage::R11G11B10: + return 4; + default: break; + } + detail::error_pixel_invalid_format("unknown"); +} + +[[nodiscard]] constexpr size_t pixel_storage_size(PixelStorage storage, uint3 size) noexcept { + if (is_block_compressed(storage)) { + auto block_width = (size.x + 3u) / 4u; + auto block_height = (size.y + 3u) / 4u; + auto block_count = block_width * block_height * std::max(size.z, 1u); + switch (storage) { + case PixelStorage::BC1: + case PixelStorage::BC4: return block_count * 8u; + case PixelStorage::BC2: + case PixelStorage::BC3: + case PixelStorage::BC5: + case PixelStorage::BC6: + case PixelStorage::BC7: return block_count * 16u; + default: break; + } + detail::error_pixel_invalid_format("unknown."); + } + auto pixel_count = size.x * size.y * size.z; + switch (storage) { + case PixelStorage::BYTE1: return pixel_count * sizeof(std::byte) * 1u; + case PixelStorage::BYTE2: return pixel_count * sizeof(std::byte) * 2u; + case PixelStorage::BYTE4: return pixel_count * sizeof(std::byte) * 4u; + case PixelStorage::SHORT1: return pixel_count * sizeof(short) * 1u; + case PixelStorage::SHORT2: return pixel_count * sizeof(short) * 2u; + case PixelStorage::SHORT4: return pixel_count * sizeof(short) * 4u; + case PixelStorage::INT1: return pixel_count * sizeof(int) * 1u; + case PixelStorage::INT2: return pixel_count * sizeof(int) * 2u; + case PixelStorage::INT4: return pixel_count * sizeof(int) * 4u; + case PixelStorage::HALF1: return pixel_count * sizeof(short) * 1u; + case PixelStorage::HALF2: return pixel_count * sizeof(short) * 2u; + case PixelStorage::HALF4: return pixel_count * sizeof(short) * 4u; + case PixelStorage::FLOAT1: return pixel_count * sizeof(float) * 1u; + case PixelStorage::FLOAT2: return pixel_count * sizeof(float) * 2u; + case PixelStorage::FLOAT4: return pixel_count * sizeof(float) * 4u; + case PixelStorage::R10G10B10A2: + case PixelStorage::R11G11B10: + return pixel_count * 4; + default: break; + } + detail::error_pixel_invalid_format("unknown"); +} + +[[nodiscard]] constexpr size_t pixel_format_align(PixelFormat format) noexcept { + return pixel_storage_align(pixel_format_to_storage(format)); +} + +[[nodiscard]] constexpr auto pixel_storage_channel_count(PixelStorage storage) noexcept { + switch (storage) { + case PixelStorage::BYTE1: return 1u; + case PixelStorage::BYTE2: return 2u; + case PixelStorage::BYTE4: return 4u; + case PixelStorage::SHORT1: return 1u; + case PixelStorage::SHORT2: return 2u; + case PixelStorage::SHORT4: return 4u; + case PixelStorage::INT1: return 1u; + case PixelStorage::INT2: return 2u; + case PixelStorage::INT4: return 4u; + case PixelStorage::HALF1: return 1u; + case PixelStorage::HALF2: return 2u; + case PixelStorage::HALF4: return 4u; + case PixelStorage::FLOAT1: return 1u; + case PixelStorage::FLOAT2: return 2u; + case PixelStorage::FLOAT4: return 4u; + + case PixelStorage::R11G11B10: return 3u; + case PixelStorage::R10G10B10A2: return 4u; + + case PixelStorage::BC4: return 1u; + case PixelStorage::BC5: return 2u; + case PixelStorage::BC1: + case PixelStorage::BC6: return 3u; + case PixelStorage::BC2: + case PixelStorage::BC3: + case PixelStorage::BC7: return 4u; + default: break; + } + return 0u; +} + +template +[[nodiscard]] constexpr auto pixel_storage_to_format(PixelStorage storage) noexcept { + if constexpr (std::is_same_v) { + switch (storage) { + case PixelStorage::BYTE1: return PixelFormat::R8UNorm; + case PixelStorage::BYTE2: return PixelFormat::RG8UNorm; + case PixelStorage::BYTE4: return PixelFormat::RGBA8UNorm; + case PixelStorage::SHORT1: return PixelFormat::R16UNorm; + case PixelStorage::SHORT2: return PixelFormat::RG16UNorm; + case PixelStorage::SHORT4: return PixelFormat::RGBA16UNorm; + case PixelStorage::HALF1: return PixelFormat::R16F; + case PixelStorage::HALF2: return PixelFormat::RG16F; + case PixelStorage::HALF4: return PixelFormat::RGBA16F; + case PixelStorage::FLOAT1: return PixelFormat::R32F; + case PixelStorage::FLOAT2: return PixelFormat::RG32F; + case PixelStorage::FLOAT4: return PixelFormat::RGBA32F; + case PixelStorage::R11G11B10: return PixelFormat::R11G11B10F; + case PixelStorage::R10G10B10A2: return PixelFormat::R10G10B10A2UNorm; + case PixelStorage::BC1: return PixelFormat ::BC1UNorm; + case PixelStorage::BC2: return PixelFormat ::BC2UNorm; + case PixelStorage::BC3: return PixelFormat ::BC3UNorm; + case PixelStorage::BC4: return PixelFormat ::BC4UNorm; + case PixelStorage::BC5: return PixelFormat ::BC5UNorm; + case PixelStorage::BC6: return PixelFormat ::BC6HUF16; + case PixelStorage::BC7: return PixelFormat ::BC7UNorm; + default: detail::error_pixel_invalid_format("float"); + } + } else if constexpr (std::is_same_v) { + switch (storage) { + case PixelStorage::BYTE1: return PixelFormat::R8SInt; + case PixelStorage::BYTE2: return PixelFormat::RG8SInt; + case PixelStorage::BYTE4: return PixelFormat::RGBA8SInt; + case PixelStorage::SHORT1: return PixelFormat::R16SInt; + case PixelStorage::SHORT2: return PixelFormat::RG16SInt; + case PixelStorage::SHORT4: return PixelFormat::RGBA16SInt; + case PixelStorage::INT1: return PixelFormat::R32SInt; + case PixelStorage::INT2: return PixelFormat::RG32SInt; + case PixelStorage::INT4: return PixelFormat::RGBA32SInt; + default: detail::error_pixel_invalid_format("int"); + } + } else if constexpr (std::is_same_v) { + switch (storage) { + case PixelStorage::BYTE1: return PixelFormat::R8UInt; + case PixelStorage::BYTE2: return PixelFormat::RG8UInt; + case PixelStorage::BYTE4: return PixelFormat::RGBA8UInt; + case PixelStorage::SHORT1: return PixelFormat::R16UInt; + case PixelStorage::SHORT2: return PixelFormat::RG16UInt; + case PixelStorage::SHORT4: return PixelFormat::RGBA16UInt; + case PixelStorage::INT1: return PixelFormat::R32UInt; + case PixelStorage::INT2: return PixelFormat::RG32UInt; + case PixelStorage::INT4: return PixelFormat::RGBA32UInt; + case PixelStorage::R10G10B10A2: return PixelFormat::R10G10B10A2UInt; + default: detail::error_pixel_invalid_format("uint"); + } + } else { + static_assert(always_false_v); + } + // unreachable + return PixelFormat{}; +} + +[[nodiscard]] constexpr auto pixel_format_size(PixelFormat format, uint3 size) noexcept { + return pixel_storage_size(pixel_format_to_storage(format), size); +} + +[[nodiscard]] constexpr auto pixel_format_channel_count(PixelFormat format) noexcept { + return pixel_storage_channel_count(pixel_format_to_storage(format)); +} + +}// namespace luisa::compute diff --git a/include/luisa/xir/builder.h b/include/luisa/xir/builder.h index f1de1201d..3db3d918e 100644 --- a/include/luisa/xir/builder.h +++ b/include/luisa/xir/builder.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -69,6 +70,7 @@ class LC_XIR_API Builder { ReturnInst *return_void() noexcept; AssertInst *assert_(Value *condition, luisa::string_view message = {}) noexcept; + AssumeInst *assume_(Value *condition, luisa::string_view message = {}) noexcept; CallInst *call(const Type *type, Value *callee, luisa::span arguments) noexcept; CallInst *call(const Type *type, Value *callee, std::initializer_list arguments) noexcept; diff --git a/include/luisa/xir/constant.h b/include/luisa/xir/constant.h index f22fb5147..d7f1956f2 100644 --- a/include/luisa/xir/constant.h +++ b/include/luisa/xir/constant.h @@ -16,6 +16,7 @@ class LC_XIR_API Constant : public IntrusiveForwardNode diff --git a/include/luisa/xir/instruction.h b/include/luisa/xir/instruction.h index 1a68f9b54..556021bde 100644 --- a/include/luisa/xir/instruction.h +++ b/include/luisa/xir/instruction.h @@ -35,7 +35,9 @@ enum struct DerivedInstructionTag { INTRINSIC,// intrinsic function calls CAST, // type casts PRINT, // kernel print - ASSERT, // assertion + + ASSERT,// assertion + ASSUME,// assumption OUTLINE, // mark that the body might be outlined (e.g., for faster compilation) AUTO_DIFF,// automatic differentiation diff --git a/include/luisa/xir/instructions/assume.h b/include/luisa/xir/instructions/assume.h new file mode 100644 index 000000000..411e5550f --- /dev/null +++ b/include/luisa/xir/instructions/assume.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +namespace luisa::compute::xir { + +class LC_XIR_API AssumeInst final : public DerivedInstruction { + +public: + static constexpr size_t operand_index_condition = 0u; + +private: + luisa::string _message; + +public: + explicit AssumeInst(Value *condition = nullptr, + luisa::string message = {}) noexcept; + + void set_condition(Value *condition) noexcept; + [[nodiscard]] Value *condition() noexcept; + [[nodiscard]] const Value *condition() const noexcept; + + void set_message(luisa::string_view message) noexcept; + [[nodiscard]] luisa::string_view message() const noexcept; +}; + +}// namespace luisa::compute::xir + diff --git a/include/luisa/xir/instructions/intrinsic.h b/include/luisa/xir/instructions/intrinsic.h index 175b9fa60..f3ebb68ca 100644 --- a/include/luisa/xir/instructions/intrinsic.h +++ b/include/luisa/xir/instructions/intrinsic.h @@ -41,10 +41,6 @@ enum struct IntrinsicOp { BINARY_EQUAL, BINARY_NOT_EQUAL, - // optimization/debugging - ASSUME, - ASSERT, - // thread coordination THREAD_ID, BLOCK_ID, @@ -115,6 +111,7 @@ enum struct IntrinsicOp { FRACT,// (floatN) TRUNC,// (floatN) ROUND,// (floatN) + RINT, // (floatN) FMA, // (a: floatN, b: floatN, c: floatN): return a * b + c COPYSIGN,// (floatN, floatN) @@ -127,19 +124,22 @@ enum struct IntrinsicOp { FACEFORWARD, // (floatN, floatN, floatN) REFLECT, // (floatN, floatN) - REDUCE_SUM, // (floatN) - REDUCE_PRODUCT,// (floatN) - REDUCE_MIN, // (floatN) - REDUCE_MAX, // (floatN) + REDUCE_SUM, // (floatN) -> float + REDUCE_PRODUCT,// (floatN) -> float + REDUCE_MIN, // (floatN) -> float + REDUCE_MAX, // (floatN) -> float - OUTER_PRODUCT, // (floatN | floatNxN) - MATRIX_COMP_MUL,// (floatNxN, floatNxN) - DETERMINANT, // (floatNxN) - TRANSPOSE, // (floatNxN) - INVERSE, // (floatNxN) + OUTER_PRODUCT,// (floatN, floatN) -> floatNxN | (floatNxN, floatNxN) -> floatNxN - ZERO,// () -> T - ONE, // () -> T + MATRIX_COMP_NEG, // (floatNxN) -> floatNxN + MATRIX_COMP_ADD, // (floatNxN, floatNxN) -> floatNxN | (floatNxN, float) -> floatNxN | (float, floatNxN) -> floatNxN + MATRIX_COMP_SUB, // (floatNxN, floatNxN) -> floatNxN | (floatNxN, float) -> floatNxN | (float, floatNxN) -> floatNxN + MATRIX_COMP_MUL, // (floatNxN, floatNxN) -> floatNxN | (floatNxN, float) -> floatNxN | (float, floatNxN) -> floatNxN + MATRIX_COMP_DIV, // (floatNxN, floatNxN) -> floatNxN | (floatNxN, float) -> floatNxN | (float, floatNxN) -> floatNxN + MATRIX_LINALG_MUL, // (floatNxN, floatNxN) -> floatNxN | (floatNxN, floatN) -> floatN + MATRIX_DETERMINANT,// (floatNxN) -> float + MATRIX_TRANSPOSE, // (floatNxN) -> floatNxN + MATRIX_INVERSE, // (floatNxN) -> floatNxN // atomic operations ATOMIC_EXCHANGE, /// [(atomic_ref, desired) -> old]: stores desired, returns old. @@ -164,18 +164,18 @@ enum struct IntrinsicOp { TEXTURE2D_READ, /// [(texture, coord) -> value] TEXTURE2D_WRITE, /// [(texture, coord, value) -> void] TEXTURE2D_SIZE, /// [(texture) -> Vector] - TEXTURE2D_SAMPLE, // (tex, uv: float2, filter: uint, address: uint): float4 - TEXTURE2D_SAMPLE_LEVEL, // (tex, uv: float2, level: float, filter: uint, address: uint): float4 - TEXTURE2D_SAMPLE_GRAD, // (tex, uv: float2, ddx: float2, ddy: float2, filter: uint, address: uint): float4 - TEXTURE2D_SAMPLE_GRAD_LEVEL,// (tex, uv: float2, ddx: float2, ddy: float2, mip_clamp: float, filter: uint, address: uint): float4 + TEXTURE2D_SAMPLE, // (tex, uv: float2, filter: uint, level: uint): float4 + TEXTURE2D_SAMPLE_LEVEL, // (tex, uv: float2, level: float, filter: uint, level: uint): float4 + TEXTURE2D_SAMPLE_GRAD, // (tex, uv: float2, ddx: float2, ddy: float2, filter: uint, level: uint): float4 + TEXTURE2D_SAMPLE_GRAD_LEVEL,// (tex, uv: float2, ddx: float2, ddy: float2, mip_clamp: float, filter: uint, level: uint): float4 TEXTURE3D_READ, /// [(texture, coord) -> value] TEXTURE3D_WRITE, /// [(texture, coord, value) -> void] TEXTURE3D_SIZE, /// [(texture) -> Vector] - TEXTURE3D_SAMPLE, // (tex, uv: float3, filter: uint, address: uint): float4 - TEXTURE3D_SAMPLE_LEVEL, // (tex, uv: float3, level: float, filter: uint, address: uint): float4 - TEXTURE3D_SAMPLE_GRAD, // (tex, uv: float3, ddx: float3, ddy: float3, filter: uint, address: uint): float4 - TEXTURE3D_SAMPLE_GRAD_LEVEL,// (tex, uv: float3, ddx: float3, ddy: float3, mip_clamp: float, filter: uint, address: uint): float4 + TEXTURE3D_SAMPLE, // (tex, uv: float3, filter: uint, level: uint): float4 + TEXTURE3D_SAMPLE_LEVEL, // (tex, uv: float3, level: float, filter: uint, level: uint): float4 + TEXTURE3D_SAMPLE_GRAD, // (tex, uv: float3, ddx: float3, ddy: float3, filter: uint, level: uint): float4 + TEXTURE3D_SAMPLE_GRAD_LEVEL,// (tex, uv: float3, ddx: float3, ddy: float3, mip_clamp: float, filter: uint, level: uint): float4 // bindless array operations BINDLESS_TEXTURE2D_SAMPLE, // (bindless_array, index: uint, uv: float2): float4 @@ -187,14 +187,14 @@ enum struct IntrinsicOp { BINDLESS_TEXTURE3D_SAMPLE_GRAD, // (bindless_array, index: uint, uv: float3, ddx: float3, ddy: float3): float4 BINDLESS_TEXTURE3D_SAMPLE_GRAD_LEVEL,// (bindless_array, index: uint, uv: float3, ddx: float3, ddy: float3, mip_clamp: float): float4 - BINDLESS_TEXTURE2D_SAMPLE_SAMPLER, // (bindless_array, index: uint, uv: float2, filter: uint, address: uint): float4 - BINDLESS_TEXTURE2D_SAMPLE_LEVEL_SAMPLER, // (bindless_array, index: uint, uv: float2, level: float, filter: uint, address: uint): float4 - BINDLESS_TEXTURE2D_SAMPLE_GRAD_SAMPLER, // (bindless_array, index: uint, uv: float2, ddx: float2, ddy: float2, filter: uint, address: uint): float4 - BINDLESS_TEXTURE2D_SAMPLE_GRAD_LEVEL_SAMPLER,// (bindless_array, index: uint, uv: float2, ddx: float2, ddy: float2, mip_clamp: float, filter: uint, address: uint): float4 - BINDLESS_TEXTURE3D_SAMPLE_SAMPLER, // (bindless_array, index: uint, uv: float3, filter: uint, address: uint): float4 - BINDLESS_TEXTURE3D_SAMPLE_LEVEL_SAMPLER, // (bindless_array, index: uint, uv: float3, level: float, filter: uint, address: uint): float4 - BINDLESS_TEXTURE3D_SAMPLE_GRAD_SAMPLER, // (bindless_array, index: uint, uv: float3, ddx: float3, ddy: float3, filter: uint, address: uint): float4 - BINDLESS_TEXTURE3D_SAMPLE_GRAD_LEVEL_SAMPLER,// (bindless_array, index: uint, uv: float3, ddx: float3, ddy: float3, mip_clamp: float, filter: uint, address: uint): float4 + BINDLESS_TEXTURE2D_SAMPLE_SAMPLER, // (bindless_array, index: uint, uv: float2, filter: uint, level: uint): float4 + BINDLESS_TEXTURE2D_SAMPLE_LEVEL_SAMPLER, // (bindless_array, index: uint, uv: float2, level: float, filter: uint, level: uint): float4 + BINDLESS_TEXTURE2D_SAMPLE_GRAD_SAMPLER, // (bindless_array, index: uint, uv: float2, ddx: float2, ddy: float2, filter: uint, level: uint): float4 + BINDLESS_TEXTURE2D_SAMPLE_GRAD_LEVEL_SAMPLER,// (bindless_array, index: uint, uv: float2, ddx: float2, ddy: float2, mip_clamp: float, filter: uint, level: uint): float4 + BINDLESS_TEXTURE3D_SAMPLE_SAMPLER, // (bindless_array, index: uint, uv: float3, filter: uint, level: uint): float4 + BINDLESS_TEXTURE3D_SAMPLE_LEVEL_SAMPLER, // (bindless_array, index: uint, uv: float3, level: float, filter: uint, level: uint): float4 + BINDLESS_TEXTURE3D_SAMPLE_GRAD_SAMPLER, // (bindless_array, index: uint, uv: float3, ddx: float3, ddy: float3, filter: uint, level: uint): float4 + BINDLESS_TEXTURE3D_SAMPLE_GRAD_LEVEL_SAMPLER,// (bindless_array, index: uint, uv: float3, ddx: float3, ddy: float3, mip_clamp: float, filter: uint, level: uint): float4 BINDLESS_TEXTURE2D_READ, // (bindless_array, index: uint, coord: uint2): float4 BINDLESS_TEXTURE3D_READ, // (bindless_array, index: uint, coord: uint3): float4 diff --git a/include/luisa/xir/module.h b/include/luisa/xir/module.h index 33adc7c40..99744d5e2 100644 --- a/include/luisa/xir/module.h +++ b/include/luisa/xir/module.h @@ -26,14 +26,11 @@ class LC_XIR_API Module : public PooledObject, [[nodiscard]] auto &functions() const noexcept { return _functions; } void add_constant(Constant *constant) noexcept; - [[nodiscard]] Constant *create_constant(const Type *type, const void *data) noexcept; + [[nodiscard]] Constant *create_constant(const Type *type, const void *data = nullptr) noexcept; + [[nodiscard]] Constant *create_constant_zero(const Type *type) noexcept; + [[nodiscard]] Constant *create_constant_one(const Type *type) noexcept; [[nodiscard]] auto &constants() noexcept { return _constants; } [[nodiscard]] auto &constants() const noexcept { return _constants; } - - template - [[nodiscard]] Constant *create_constant(const T &value) noexcept { - return create_constant(Type::of(), &value); - } }; }// namespace luisa::compute::xir diff --git a/scripts/validate_options.cmake b/scripts/validate_options.cmake index 4718f3438..491a714ec 100644 --- a/scripts/validate_options.cmake +++ b/scripts/validate_options.cmake @@ -1,140 +1,149 @@ -if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8) - message(FATAL_ERROR "LuisaCompute only supports 64-bit platforms") -endif () - -message(STATUS "Build for ${CMAKE_SYSTEM} (${CMAKE_SYSTEM_PROCESSOR})") - -if (WIN32) - find_file(LUISA_COMPUTE_WINDOWS_SDK_MANIFEST_PATH "SDKManifest.xml" HINTS "$ENV{WINDOWSSDKDIR}" NO_DEFAULT_PATH) - if (LUISA_COMPUTE_WINDOWS_SDK_MANIFEST_PATH) - file(STRINGS "${LUISA_COMPUTE_WINDOWS_SDK_MANIFEST_PATH}" LUISA_COMPUTE_WINDOWS_SDK_IDENTITY REGEX "PlatformIdentity") - if (LUISA_COMPUTE_WINDOWS_SDK_IDENTITY) - string(REGEX REPLACE "PlatformIdentity = \".*Version=([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)\"" "\\1" LUISA_COMPUTE_WINDOWS_SDK_VERSION "${LUISA_COMPUTE_WINDOWS_SDK_IDENTITY}") - string(STRIP "${LUISA_COMPUTE_WINDOWS_SDK_VERSION}" LUISA_COMPUTE_WINDOWS_SDK_VERSION) - if (LUISA_COMPUTE_WINDOWS_SDK_VERSION MATCHES "PlatformIdentity") - set(LUISA_COMPUTE_WINDOWS_SDK_VERSION "") - endif () - endif () - if (LUISA_COMPUTE_WINDOWS_SDK_VERSION) - message(STATUS "Windows SDK found: ${LUISA_COMPUTE_WINDOWS_SDK_VERSION}") - else () - message(WARNING "Windows SDK found but failed to parse the version. DirectX backend may not build correctly.") - endif () - else () - message(WARNING "Windows SDK not found. DirectX backend may not build correctly.") - endif () -endif () - -if (LUISA_COMPUTE_BUILD_TESTS) - if (NOT LUISA_COMPUTE_ENABLE_DSL) - message(WARNING "DSL is required for tests. The DSL will be enabled.") - set(LUISA_COMPUTE_ENABLE_DSL ON CACHE BOOL "Enable C++ DSL" FORCE) - endif () -endif () - -# check Rust support -if (NOT DEFINED CARGO_HOME) - if ("$ENV{CARGO_HOME}" STREQUAL "") - if (CMAKE_HOST_WIN32) - set(CARGO_HOME "$ENV{USERPROFILE}/.cargo") - else () - set(CARGO_HOME "$ENV{HOME}/.cargo") - endif () - else () - set(CARGO_HOME "$ENV{CARGO_HOME}") - endif () -endif () - -if (NOT DEFINED LUISA_COMPUTE_ENABLE_RUST) - set(LUISA_COMPUTE_ENABLE_RUST ON) -endif () - -if (LUISA_COMPUTE_ENABLE_RUST OR LUISA_COMPUTE_ENABLE_CPU OR LUISA_COMPUTE_ENABLE_REMOTE) - find_program(CARGO_EXE cargo NO_CACHE HINTS "${CARGO_HOME}" PATH_SUFFIXES "bin") - if (CARGO_EXE) - set(LUISA_COMPUTE_ENABLE_RUST ON) - else () - set(LUISA_COMPUTE_ENABLE_RUST OFF) - endif () - if (LUISA_COMPUTE_ENABLE_RUST) - message(STATUS "Enable Rust support (toolchain found at ${CARGO_EXE})") - else () - message(WARNING "\nRust-dependent features are enabled but the Rust toolchain is not found on your system. \n\ - To install Rust, run `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh` on unix environment\n\ - or download and run the installer from https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe on windows environment.\n") - endif () -endif () - -function(report_feature_not_available option_name feature_name) - if (LUISA_COMPUTE_CHECK_BACKEND_DEPENDENCIES) - message(WARNING "The ${feature_name} is not available. The ${feature_name} will be disabled.") - set(LUISA_COMPUTE_ENABLE_${option_name} OFF CACHE BOOL "Enable ${feature_name}" FORCE) - else () - message(FATAL_ERROR "The ${feature_name} is not available. Please install the dependencies to enable the ${feature_name}.") - endif () -endfunction() - -if (LUISA_COMPUTE_ENABLE_DX) - set(LUISA_COMPUTE_EXPECTED_WINDOWS_SDK_VERSION "10.0.20348") - if (NOT WIN32) - report_feature_not_available(DX "DirectX backend") - elseif (LUISA_COMPUTE_WINDOWS_SDK_VERSION) - if (${LUISA_COMPUTE_WINDOWS_SDK_VERSION} VERSION_LESS ${LUISA_COMPUTE_EXPECTED_WINDOWS_SDK_VERSION}) - message(WARNING "Expected Windows SDK >= ${LUISA_COMPUTE_EXPECTED_WINDOWS_SDK_VERSION} for DirectML support but you are using ${LUISA_COMPUTE_WINDOWS_SDK_VERSION}. The DirectX backend will be disabled. Please consider update the SDK with Visual Studio Installer.") - report_feature_not_available(DX "DirectX backend") - endif () - endif () -endif () - -if (LUISA_COMPUTE_ENABLE_METAL) - if (NOT APPLE OR NOT ${CMAKE_C_COMPILER_ID} MATCHES "Clang" OR NOT ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") - report_feature_not_available(METAL "Metal backend") - endif () -endif () - -if (LUISA_COMPUTE_ENABLE_CUDA) - find_package(CUDAToolkit 11.7 QUIET) - if (NOT CUDAToolkit_FOUND) - report_feature_not_available(CUDA "CUDA backend") - endif () -endif () - -if (LUISA_COMPUTE_ENABLE_VULKAN) - find_package(Vulkan QUIET) - if (NOT Vulkan_FOUND) - report_feature_not_available(VULKAN "Vulkan backend") - endif () -endif () - -if (NOT LUISA_COMPUTE_ENABLE_RUST) - if (LUISA_COMPUTE_ENABLE_CPU OR LUISA_COMPUTE_ENABLE_REMOTE) - report_feature_not_available(CPU "CPU backend") - report_feature_not_available(REMOTE "Remote backend") - endif () -endif () - -if (UNIX AND NOT APPLE AND LUISA_COMPUTE_ENABLE_WAYLAND) - find_program(LUISA_COMPUTE_WAYLAND_SCANNER wayland-scanner) - find_package(PkgConfig QUIET) - if (PKG_CONFIG_FOUND) - pkg_check_modules(Wayland QUIET wayland-client) - endif () - if (NOT LUISA_COMPUTE_WAYLAND_SCANNER OR NOT Wayland_FOUND) - report_feature_not_available(WAYLAND "Wayland support") - endif () -endif () - -if (SKBUILD OR LUISA_COMPUTE_FORCE_PYTHON_BINDINGS) - find_package(Python3 COMPONENTS Interpreter Development.Module QUIET REQUIRED) -endif () - -if (LUISA_COMPUTE_ENABLE_GUI) - # currently nothing to check -endif () - -if (LUISA_COMPUTE_ENABLE_CLANG_CXX) - find_package(Clang CONFIG QUIET) - if (NOT Clang_FOUND) - report_feature_not_available(CLANG_CXX "Clang C++") - endif () -endif () +if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8) + message(FATAL_ERROR "LuisaCompute only supports 64-bit platforms") +endif () + +message(STATUS "Build for ${CMAKE_SYSTEM} (${CMAKE_SYSTEM_PROCESSOR})") + +if (WIN32) + find_file(LUISA_COMPUTE_WINDOWS_SDK_MANIFEST_PATH "SDKManifest.xml" HINTS "$ENV{WINDOWSSDKDIR}" NO_DEFAULT_PATH) + if (LUISA_COMPUTE_WINDOWS_SDK_MANIFEST_PATH) + file(STRINGS "${LUISA_COMPUTE_WINDOWS_SDK_MANIFEST_PATH}" LUISA_COMPUTE_WINDOWS_SDK_IDENTITY REGEX "PlatformIdentity") + if (LUISA_COMPUTE_WINDOWS_SDK_IDENTITY) + string(REGEX REPLACE "PlatformIdentity = \".*Version=([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)\"" "\\1" LUISA_COMPUTE_WINDOWS_SDK_VERSION "${LUISA_COMPUTE_WINDOWS_SDK_IDENTITY}") + string(STRIP "${LUISA_COMPUTE_WINDOWS_SDK_VERSION}" LUISA_COMPUTE_WINDOWS_SDK_VERSION) + if (LUISA_COMPUTE_WINDOWS_SDK_VERSION MATCHES "PlatformIdentity") + set(LUISA_COMPUTE_WINDOWS_SDK_VERSION "") + endif () + endif () + if (LUISA_COMPUTE_WINDOWS_SDK_VERSION) + message(STATUS "Windows SDK found: ${LUISA_COMPUTE_WINDOWS_SDK_VERSION}") + else () + message(WARNING "Windows SDK found but failed to parse the version. DirectX backend may not build correctly.") + endif () + else () + message(WARNING "Windows SDK not found. DirectX backend may not build correctly.") + endif () +endif () + +if (LUISA_COMPUTE_BUILD_TESTS) + if (NOT LUISA_COMPUTE_ENABLE_DSL) + message(WARNING "DSL is required for tests. The DSL will be enabled.") + set(LUISA_COMPUTE_ENABLE_DSL ON CACHE BOOL "Enable C++ DSL" FORCE) + endif () +endif () + +# check Rust support +if (NOT DEFINED CARGO_HOME) + if ("$ENV{CARGO_HOME}" STREQUAL "") + if (CMAKE_HOST_WIN32) + set(CARGO_HOME "$ENV{USERPROFILE}/.cargo") + else () + set(CARGO_HOME "$ENV{HOME}/.cargo") + endif () + else () + set(CARGO_HOME "$ENV{CARGO_HOME}") + endif () +endif () + +if (NOT DEFINED LUISA_COMPUTE_ENABLE_RUST) + set(LUISA_COMPUTE_ENABLE_RUST ON) +endif () + +if (LUISA_COMPUTE_ENABLE_RUST OR LUISA_COMPUTE_ENABLE_CPU OR LUISA_COMPUTE_ENABLE_REMOTE) + find_program(CARGO_EXE cargo NO_CACHE HINTS "${CARGO_HOME}" PATH_SUFFIXES "bin") + if (CARGO_EXE) + set(LUISA_COMPUTE_ENABLE_RUST ON) + else () + set(LUISA_COMPUTE_ENABLE_RUST OFF) + endif () + if (LUISA_COMPUTE_ENABLE_RUST) + message(STATUS "Enable Rust support (toolchain found at ${CARGO_EXE})") + else () + message(WARNING "\nRust-dependent features are enabled but the Rust toolchain is not found on your system. \n\ + To install Rust, run `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh` on unix environment\n\ + or download and run the installer from https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe on windows environment.\n") + endif () +endif () + +function(report_feature_not_available option_name feature_name) + if (LUISA_COMPUTE_CHECK_BACKEND_DEPENDENCIES) + message(WARNING "The ${feature_name} is not available. The ${feature_name} will be disabled.") + set(LUISA_COMPUTE_ENABLE_${option_name} OFF CACHE BOOL "Enable ${feature_name}" FORCE) + else () + message(FATAL_ERROR "The ${feature_name} is not available. Please install the dependencies to enable the ${feature_name}.") + endif () +endfunction() + +if (LUISA_COMPUTE_ENABLE_DX) + set(LUISA_COMPUTE_EXPECTED_WINDOWS_SDK_VERSION "10.0.20348") + if (NOT WIN32) + report_feature_not_available(DX "DirectX backend") + elseif (LUISA_COMPUTE_WINDOWS_SDK_VERSION) + if (${LUISA_COMPUTE_WINDOWS_SDK_VERSION} VERSION_LESS ${LUISA_COMPUTE_EXPECTED_WINDOWS_SDK_VERSION}) + message(WARNING "Expected Windows SDK >= ${LUISA_COMPUTE_EXPECTED_WINDOWS_SDK_VERSION} for DirectML support but you are using ${LUISA_COMPUTE_WINDOWS_SDK_VERSION}. The DirectX backend will be disabled. Please consider update the SDK with Visual Studio Installer.") + report_feature_not_available(DX "DirectX backend") + endif () + endif () +endif () + +if (LUISA_COMPUTE_ENABLE_METAL) + if (NOT APPLE OR NOT ${CMAKE_C_COMPILER_ID} MATCHES "Clang" OR NOT ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") + report_feature_not_available(METAL "Metal backend") + endif () +endif () + +if (LUISA_COMPUTE_ENABLE_CUDA) + find_package(CUDAToolkit 12 QUIET) + if (NOT CUDAToolkit_FOUND) + report_feature_not_available(CUDA "CUDA backend") + endif () +endif () + +if (LUISA_COMPUTE_ENABLE_VULKAN) + find_package(Vulkan QUIET) + if (NOT Vulkan_FOUND) + report_feature_not_available(VULKAN "Vulkan backend") + endif () +endif () + +if (LUISA_COMPUTE_ENABLE_FALLBACK) + find_package(LLVM CONFIG) + find_package(embree CONFIG) + if (NOT LLVM_FOUND OR LLVM_VERSION VERSION_LESS 16 OR + NOT embree_FOUND OR embree_VERSION VERSION_LESS 3) + report_feature_not_available(FALLBACK "fallback backend") + endif () +endif () + +if (NOT LUISA_COMPUTE_ENABLE_RUST) + if (LUISA_COMPUTE_ENABLE_CPU OR LUISA_COMPUTE_ENABLE_REMOTE) + report_feature_not_available(CPU "CPU backend") + report_feature_not_available(REMOTE "Remote backend") + endif () +endif () + +if (UNIX AND NOT APPLE AND LUISA_COMPUTE_ENABLE_WAYLAND) + find_program(LUISA_COMPUTE_WAYLAND_SCANNER wayland-scanner) + find_package(PkgConfig QUIET) + if (PKG_CONFIG_FOUND) + pkg_check_modules(Wayland QUIET wayland-client) + endif () + if (NOT LUISA_COMPUTE_WAYLAND_SCANNER OR NOT Wayland_FOUND) + report_feature_not_available(WAYLAND "Wayland support") + endif () +endif () + +if (SKBUILD OR LUISA_COMPUTE_FORCE_PYTHON_BINDINGS) + find_package(Python3 COMPONENTS Interpreter Development.Module QUIET REQUIRED) +endif () + +if (LUISA_COMPUTE_ENABLE_GUI) + # currently nothing to check +endif () + +if (LUISA_COMPUTE_ENABLE_CLANG_CXX) + find_package(Clang CONFIG QUIET) + if (NOT Clang_FOUND) + report_feature_not_available(CLANG_CXX "Clang C++") + endif () +endif () diff --git a/scripts/xmake_func.lua b/scripts/xmake_func.lua index 8ab05c545..2d3113756 100644 --- a/scripts/xmake_func.lua +++ b/scripts/xmake_func.lua @@ -199,13 +199,16 @@ on_load(function(target) if project_kind then target:set("kind", project_kind) end - if not is_plat("windows") then + if is_plat("linux") then if project_kind == "static" or project_kind == "object" then target:add("cxflags", "-fPIC", { tools = {"clang", "gcc"} }) end end + if is_plat("macosx") then + target:add("cxflags", "-no-pie") + end -- fma support if is_arch("x64", "x86_64") then target:add("cxflags", "-mfma", { diff --git a/src/ast/type.cpp b/src/ast/type.cpp index bcf5c24e3..68b8a3b9f 100644 --- a/src/ast/type.cpp +++ b/src/ast/type.cpp @@ -516,10 +516,14 @@ uint64_t Type::hash() const noexcept { } size_t Type::size() const noexcept { + LUISA_ASSERT(!is_resource() && !is_custom(), + "Trying to take size of backend-specific type."); return static_cast(this)->size; } size_t Type::alignment() const noexcept { + LUISA_ASSERT(!is_resource() && !is_custom(), + "Trying to take alignment of backend-specific type."); return static_cast(this)->alignment; } diff --git a/src/ast/xmake.lua b/src/ast/xmake.lua index b2ca416b6..cbba65277 100644 --- a/src/ast/xmake.lua +++ b/src/ast/xmake.lua @@ -1,11 +1,11 @@ -target("lc-ast") -_config_project({ - project_kind = "shared", - batch_size = 4 -}) -add_deps("lc-core", "lc-vstl") -add_headerfiles("../../include/luisa/ast/**.h") -set_pcxxheader("pch.h") -add_files("**.cpp") -add_defines("LC_AST_EXPORT_DLL") -target_end() +target("lc-ast") +_config_project({ + project_kind = "shared", + batch_size = 4 +}) +add_deps("lc-core", "lc-vstl") +add_headerfiles("../../include/luisa/ast/**.h") +set_pcxxheader("pch.h") +add_files("**.cpp") +add_defines("LC_AST_EXPORT_DLL") +target_end() diff --git a/src/backends/CMakeLists.txt b/src/backends/CMakeLists.txt index 3c8cba3be..80e8e9270 100644 --- a/src/backends/CMakeLists.txt +++ b/src/backends/CMakeLists.txt @@ -1,63 +1,67 @@ -add_library(luisa-compute-backends INTERFACE) - -set(FETCHCONTENT_QUIET OFF) -function(luisa_compute_add_backend name) - cmake_parse_arguments(BACKEND "" "SUPPORT_DIR;BUILTIN_DIR" "SOURCES" ${ARGN}) - # DLL target - add_library(luisa-compute-backend-${name} MODULE ${BACKEND_SOURCES}) - target_link_libraries(luisa-compute-backend-${name} PRIVATE - luisa-compute-ast - luisa-compute-vstl - luisa-compute-runtime - luisa-compute-gui) - if (LUISA_COMPUTE_ENABLE_DSL) - target_link_libraries(luisa-compute-backend-${name} PRIVATE luisa-compute-dsl) - endif () - add_dependencies(luisa-compute-backends luisa-compute-backend-${name}) - set_target_properties(luisa-compute-backend-${name} PROPERTIES - UNITY_BUILD ${LUISA_COMPUTE_ENABLE_UNITY_BUILD} - DEBUG_POSTFIX "" - OUTPUT_NAME lc-backend-${name}) - install(TARGETS luisa-compute-backend-${name} - LIBRARY DESTINATION ${CMAKE_INSTALL_BINDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - # support directory - if (BACKEND_SUPPORT_DIR) - add_custom_target(luisa-compute-backend-${name}-copy-support ALL - COMMAND ${CMAKE_COMMAND} -E copy_directory - "${BACKEND_SUPPORT_DIR}" - "$/") - add_dependencies(luisa-compute-backend-${name} luisa-compute-backend-${name}-copy-support) - install(DIRECTORY ${BACKEND_SUPPORT_DIR}/ - DESTINATION ${CMAKE_INSTALL_BINDIR}/) - endif () -endfunction() - -add_subdirectory(common) -add_subdirectory(validation) - -if (LUISA_COMPUTE_ENABLE_DX) - add_subdirectory(dx) -endif () - -if (LUISA_COMPUTE_ENABLE_METAL) - add_subdirectory(metal) -endif () - -if (LUISA_COMPUTE_ENABLE_CUDA) - add_subdirectory(cuda) -endif () - -if (LUISA_COMPUTE_ENABLE_RUST) - if (LUISA_COMPUTE_ENABLE_CPU) - add_subdirectory(cpu) - endif () - - if (LUISA_COMPUTE_ENABLE_REMOTE) - add_subdirectory(remote) - endif () -endif () - -install(TARGETS luisa-compute-backends - EXPORT LuisaComputeTargets) +add_library(luisa-compute-backends INTERFACE) + +set(FETCHCONTENT_QUIET OFF) +function(luisa_compute_add_backend name) + cmake_parse_arguments(BACKEND "" "SUPPORT_DIR;BUILTIN_DIR" "SOURCES" ${ARGN}) + # DLL target + add_library(luisa-compute-backend-${name} MODULE ${BACKEND_SOURCES}) + target_link_libraries(luisa-compute-backend-${name} PRIVATE + luisa-compute-ast + luisa-compute-vstl + luisa-compute-runtime + luisa-compute-gui) + if (LUISA_COMPUTE_ENABLE_DSL) + target_link_libraries(luisa-compute-backend-${name} PRIVATE luisa-compute-dsl) + endif () + add_dependencies(luisa-compute-backends luisa-compute-backend-${name}) + set_target_properties(luisa-compute-backend-${name} PROPERTIES + UNITY_BUILD ${LUISA_COMPUTE_ENABLE_UNITY_BUILD} + DEBUG_POSTFIX "" + OUTPUT_NAME lc-backend-${name}) + install(TARGETS luisa-compute-backend-${name} + LIBRARY DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + # support directory + if (BACKEND_SUPPORT_DIR) + add_custom_target(luisa-compute-backend-${name}-copy-support ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${BACKEND_SUPPORT_DIR}" + "$/") + add_dependencies(luisa-compute-backend-${name} luisa-compute-backend-${name}-copy-support) + install(DIRECTORY ${BACKEND_SUPPORT_DIR}/ + DESTINATION ${CMAKE_INSTALL_BINDIR}/) + endif () +endfunction() + +add_subdirectory(common) +add_subdirectory(validation) + +if (LUISA_COMPUTE_ENABLE_DX) + add_subdirectory(dx) +endif () + +if (LUISA_COMPUTE_ENABLE_METAL) + add_subdirectory(metal) +endif () + +if (LUISA_COMPUTE_ENABLE_CUDA) + add_subdirectory(cuda) +endif () + +if (LUISA_COMPUTE_ENABLE_RUST) + if (LUISA_COMPUTE_ENABLE_CPU) + add_subdirectory(cpu) + endif () + + if (LUISA_COMPUTE_ENABLE_REMOTE) + add_subdirectory(remote) + endif () +endif () + +if (LUISA_COMPUTE_ENABLE_FALLBACK) + add_subdirectory(fallback) +endif () + +install(TARGETS luisa-compute-backends + EXPORT LuisaComputeTargets) diff --git a/src/backends/common/hlsl/hlsl_codegen_util.cpp b/src/backends/common/hlsl/hlsl_codegen_util.cpp index f174023ad..159a7a959 100644 --- a/src/backends/common/hlsl/hlsl_codegen_util.cpp +++ b/src/backends/common/hlsl/hlsl_codegen_util.cpp @@ -9,7 +9,11 @@ #include #include #include "builtin/hlsl_builtin.hpp" +#if __has_include() +#include +#else #include +#endif static bool shown_buffer_warning = false; namespace lc::hlsl { static std::atomic_bool rootsig_exceed_warned = false; diff --git a/src/backends/cuda/cuda_builtin/cuda_device_math.h b/src/backends/cuda/cuda_builtin/cuda_device_math.h index 390f1fff2..8ebaeb5fc 100644 --- a/src/backends/cuda/cuda_builtin/cuda_device_math.h +++ b/src/backends/cuda/cuda_builtin/cuda_device_math.h @@ -1,3930 +1,3930 @@ -using lc_byte = char; -using lc_ubyte = unsigned char; -using lc_short = short; -using lc_ushort = unsigned short; -using lc_int = int; -using lc_uint = unsigned int; -using lc_half = half; -using lc_float = float; -using lc_bool = bool; -using lc_long = long long; -using lc_ulong = unsigned long long; - -[[nodiscard]] __device__ inline bool isinf_impl(lc_float x) noexcept { - auto u = __float_as_int(x); - return u == 0x7f800000u | u == 0xff800000u; -} -[[nodiscard]] __device__ inline bool isnan_impl(lc_float x) noexcept { - auto u = __float_as_int(x); - return ((u & 0x7F800000u) == 0x7F800000u) & ((u & 0x7FFFFFu) != 0u); -} -[[nodiscard]] __device__ inline lc_float powi_impl(lc_float x, lc_int y) noexcept { - lc_float r = 1.0f; - auto is_y_neg = y < 0; - auto y_abs = is_y_neg ? -y : y; - - while (y_abs) { - if (y_abs & 1) r *= x; - x *= x; - y_abs >>= 1; - } - return is_y_neg ? 1.0f / r : r; -} -[[nodiscard]] __device__ inline lc_float powf_impl(lc_float x, lc_float y) noexcept { - auto y_int = static_cast(y); - return y_int == y ? powi_impl(x, y_int) : powf(x, y); -} - -struct alignas(2) lc_byte2 { - lc_byte x, y; - __device__ inline constexpr lc_byte2() noexcept - : x{}, y{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_byte2{}; } - __device__ inline constexpr static auto one() noexcept { return lc_byte2{1, 1}; } - __device__ inline explicit constexpr lc_byte2(lc_byte s) noexcept - : x{s}, y{s} {} - __device__ inline constexpr lc_byte2(lc_byte x, lc_byte y) noexcept - : x{x}, y{y} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(4) lc_byte3 { - lc_byte x, y, z; - __device__ inline constexpr lc_byte3() noexcept - : x{}, y{}, z{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_byte3{}; } - __device__ inline constexpr static auto one() noexcept { return lc_byte3{1, 1, 1}; } - __device__ inline explicit constexpr lc_byte3(lc_byte s) noexcept - : x{s}, y{s}, z{s} {} - __device__ inline constexpr lc_byte3(lc_byte x, lc_byte y, lc_byte z) noexcept - : x{x}, y{y}, z{z} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(4) lc_byte4 { - lc_byte x, y, z, w; - __device__ inline constexpr lc_byte4() noexcept - : x{}, y{}, z{}, w{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_byte4{}; } - __device__ inline constexpr static auto one() noexcept { return lc_byte4{1, 1, 1, 1}; } - __device__ inline explicit constexpr lc_byte4(lc_byte s) noexcept - : x{s}, y{s}, z{s}, w{s} {} - __device__ inline constexpr lc_byte4(lc_byte x, lc_byte y, lc_byte z, lc_byte w) noexcept - : x{x}, y{y}, z{z}, w{w} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(2) lc_ubyte2 { - lc_ubyte x, y; - __device__ inline constexpr lc_ubyte2() noexcept - : x{}, y{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_ubyte2{}; } - __device__ inline constexpr static auto one() noexcept { return lc_ubyte2{1, 1}; } - __device__ inline explicit constexpr lc_ubyte2(lc_ubyte s) noexcept - : x{s}, y{s} {} - __device__ inline constexpr lc_ubyte2(lc_ubyte x, lc_ubyte y) noexcept - : x{x}, y{y} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(4) lc_ubyte3 { - lc_ubyte x, y, z; - __device__ inline constexpr lc_ubyte3() noexcept - : x{}, y{}, z{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_ubyte3{}; } - __device__ inline constexpr static auto one() noexcept { return lc_ubyte3{1, 1, 1}; } - __device__ inline explicit constexpr lc_ubyte3(lc_ubyte s) noexcept - : x{s}, y{s}, z{s} {} - __device__ inline constexpr lc_ubyte3(lc_ubyte x, lc_ubyte y, lc_ubyte z) noexcept - : x{x}, y{y}, z{z} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(4) lc_ubyte4 { - lc_ubyte x, y, z, w; - __device__ inline constexpr lc_ubyte4() noexcept - : x{}, y{}, z{}, w{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_ubyte4{}; } - __device__ inline constexpr static auto one() noexcept { return lc_ubyte4{1, 1, 1, 1}; } - __device__ inline explicit constexpr lc_ubyte4(lc_ubyte s) noexcept - : x{s}, y{s}, z{s}, w{s} {} - __device__ inline constexpr lc_ubyte4(lc_ubyte x, lc_ubyte y, lc_ubyte z, lc_ubyte w) noexcept - : x{x}, y{y}, z{z}, w{w} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(4) lc_short2 { - lc_short x, y; - __device__ inline constexpr lc_short2() noexcept - : x{}, y{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_short2{}; } - __device__ inline constexpr static auto one() noexcept { return lc_short2{1, 1}; } - __device__ inline explicit constexpr lc_short2(lc_short s) noexcept - : x{s}, y{s} {} - __device__ inline constexpr lc_short2(lc_short x, lc_short y) noexcept - : x{x}, y{y} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(8) lc_short3 { - lc_short x, y, z; - __device__ inline constexpr lc_short3() noexcept - : x{}, y{}, z{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_short3{}; } - __device__ inline constexpr static auto one() noexcept { return lc_short3{1, 1, 1}; } - __device__ inline explicit constexpr lc_short3(lc_short s) noexcept - : x{s}, y{s}, z{s} {} - __device__ inline constexpr lc_short3(lc_short x, lc_short y, lc_short z) noexcept - : x{x}, y{y}, z{z} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(8) lc_short4 { - lc_short x, y, z, w; - __device__ inline constexpr lc_short4() noexcept - : x{}, y{}, z{}, w{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_short4{}; } - __device__ inline constexpr static auto one() noexcept { return lc_short4{1, 1, 1, 1}; } - __device__ inline explicit constexpr lc_short4(lc_short s) noexcept - : x{s}, y{s}, z{s}, w{s} {} - __device__ inline constexpr lc_short4(lc_short x, lc_short y, lc_short z, lc_short w) noexcept - : x{x}, y{y}, z{z}, w{w} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(4) lc_ushort2 { - lc_ushort x, y; - __device__ inline constexpr lc_ushort2() noexcept - : x{}, y{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_ushort2{}; } - __device__ inline constexpr static auto one() noexcept { return lc_ushort2{1, 1}; } - __device__ inline explicit constexpr lc_ushort2(lc_ushort s) noexcept - : x{s}, y{s} {} - __device__ inline constexpr lc_ushort2(lc_ushort x, lc_ushort y) noexcept - : x{x}, y{y} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(8) lc_ushort3 { - lc_ushort x, y, z; - __device__ inline constexpr lc_ushort3() noexcept - : x{}, y{}, z{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_ushort3{}; } - __device__ inline constexpr static auto one() noexcept { return lc_ushort3{1, 1, 1}; } - __device__ inline explicit constexpr lc_ushort3(lc_ushort s) noexcept - : x{s}, y{s}, z{s} {} - __device__ inline constexpr lc_ushort3(lc_ushort x, lc_ushort y, lc_ushort z) noexcept - : x{x}, y{y}, z{z} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(8) lc_ushort4 { - lc_ushort x, y, z, w; - __device__ inline constexpr lc_ushort4() noexcept - : x{}, y{}, z{}, w{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_ushort4{}; } - __device__ inline constexpr static auto one() noexcept { return lc_ushort4{1, 1, 1, 1}; } - __device__ inline explicit constexpr lc_ushort4(lc_ushort s) noexcept - : x{s}, y{s}, z{s}, w{s} {} - __device__ inline constexpr lc_ushort4(lc_ushort x, lc_ushort y, lc_ushort z, lc_ushort w) noexcept - : x{x}, y{y}, z{z}, w{w} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(8) lc_int2 { - lc_int x, y; - __device__ inline constexpr lc_int2() noexcept - : x{}, y{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_int2{}; } - __device__ inline constexpr static auto one() noexcept { return lc_int2{1, 1}; } - __device__ inline explicit constexpr lc_int2(lc_int s) noexcept - : x{s}, y{s} {} - __device__ inline constexpr lc_int2(lc_int x, lc_int y) noexcept - : x{x}, y{y} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(16) lc_int3 { - lc_int x, y, z; - __device__ inline constexpr lc_int3() noexcept - : x{}, y{}, z{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_int3{}; } - __device__ inline constexpr static auto one() noexcept { return lc_int3{1, 1, 1}; } - __device__ inline explicit constexpr lc_int3(lc_int s) noexcept - : x{s}, y{s}, z{s} {} - __device__ inline constexpr lc_int3(lc_int x, lc_int y, lc_int z) noexcept - : x{x}, y{y}, z{z} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(16) lc_int4 { - lc_int x, y, z, w; - __device__ inline constexpr lc_int4() noexcept - : x{}, y{}, z{}, w{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_int4{}; } - __device__ inline constexpr static auto one() noexcept { return lc_int4{1, 1, 1, 1}; } - __device__ inline explicit constexpr lc_int4(lc_int s) noexcept - : x{s}, y{s}, z{s}, w{s} {} - __device__ inline constexpr lc_int4(lc_int x, lc_int y, lc_int z, lc_int w) noexcept - : x{x}, y{y}, z{z}, w{w} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(8) lc_uint2 { - lc_uint x, y; - __device__ inline constexpr lc_uint2() noexcept - : x{}, y{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_uint2{}; } - __device__ inline constexpr static auto one() noexcept { return lc_uint2{1, 1}; } - __device__ inline explicit constexpr lc_uint2(lc_uint s) noexcept - : x{s}, y{s} {} - __device__ inline constexpr lc_uint2(lc_uint x, lc_uint y) noexcept - : x{x}, y{y} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(16) lc_uint3 { - lc_uint x, y, z; - __device__ inline constexpr lc_uint3() noexcept - : x{}, y{}, z{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_uint3{}; } - __device__ inline constexpr static auto one() noexcept { return lc_uint3{1, 1, 1}; } - __device__ inline explicit constexpr lc_uint3(lc_uint s) noexcept - : x{s}, y{s}, z{s} {} - __device__ inline constexpr lc_uint3(lc_uint x, lc_uint y, lc_uint z) noexcept - : x{x}, y{y}, z{z} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(16) lc_uint4 { - lc_uint x, y, z, w; - __device__ inline constexpr lc_uint4() noexcept - : x{}, y{}, z{}, w{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_uint4{}; } - __device__ inline constexpr static auto one() noexcept { return lc_uint4{1, 1, 1, 1}; } - __device__ inline explicit constexpr lc_uint4(lc_uint s) noexcept - : x{s}, y{s}, z{s}, w{s} {} - __device__ inline constexpr lc_uint4(lc_uint x, lc_uint y, lc_uint z, lc_uint w) noexcept - : x{x}, y{y}, z{z}, w{w} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(4) lc_half2 { - lc_half x, y; - __device__ inline constexpr lc_half2() noexcept - : x{}, y{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_half2{}; } - __device__ inline constexpr static auto one() noexcept { return lc_half2{1, 1}; } - __device__ inline explicit constexpr lc_half2(lc_half s) noexcept - : x{s}, y{s} {} - __device__ inline constexpr lc_half2(lc_half x, lc_half y) noexcept - : x{x}, y{y} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(8) lc_half3 { - lc_half x, y, z; - __device__ inline constexpr lc_half3() noexcept - : x{}, y{}, z{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_half3{}; } - __device__ inline constexpr static auto one() noexcept { return lc_half3{1, 1, 1}; } - __device__ inline explicit constexpr lc_half3(lc_half s) noexcept - : x{s}, y{s}, z{s} {} - __device__ inline constexpr lc_half3(lc_half x, lc_half y, lc_half z) noexcept - : x{x}, y{y}, z{z} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(8) lc_half4 { - lc_half x, y, z, w; - __device__ inline constexpr lc_half4() noexcept - : x{}, y{}, z{}, w{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_half4{}; } - __device__ inline constexpr static auto one() noexcept { return lc_half4{1, 1, 1, 1}; } - __device__ inline explicit constexpr lc_half4(lc_half s) noexcept - : x{s}, y{s}, z{s}, w{s} {} - __device__ inline constexpr lc_half4(lc_half x, lc_half y, lc_half z, lc_half w) noexcept - : x{x}, y{y}, z{z}, w{w} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(8) lc_float2 { - lc_float x, y; - __device__ inline constexpr lc_float2() noexcept - : x{}, y{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_float2{}; } - __device__ inline constexpr static auto one() noexcept { return lc_float2{1, 1}; } - __device__ inline explicit constexpr lc_float2(lc_float s) noexcept - : x{s}, y{s} {} - __device__ inline constexpr lc_float2(lc_float x, lc_float y) noexcept - : x{x}, y{y} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(16) lc_float3 { - lc_float x, y, z; - __device__ inline constexpr lc_float3() noexcept - : x{}, y{}, z{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_float3{}; } - __device__ inline constexpr static auto one() noexcept { return lc_float3{1, 1, 1}; } - __device__ inline explicit constexpr lc_float3(lc_float s) noexcept - : x{s}, y{s}, z{s} {} - __device__ inline constexpr lc_float3(lc_float x, lc_float y, lc_float z) noexcept - : x{x}, y{y}, z{z} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(16) lc_float4 { - lc_float x, y, z, w; - __device__ inline constexpr lc_float4() noexcept - : x{}, y{}, z{}, w{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_float4{}; } - __device__ inline constexpr static auto one() noexcept { return lc_float4{1, 1, 1, 1}; } - __device__ inline explicit constexpr lc_float4(lc_float s) noexcept - : x{s}, y{s}, z{s}, w{s} {} - __device__ inline constexpr lc_float4(lc_float x, lc_float y, lc_float z, lc_float w) noexcept - : x{x}, y{y}, z{z}, w{w} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(2) lc_bool2 { - lc_bool x, y; - __device__ inline constexpr lc_bool2() noexcept - : x{}, y{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_bool2{}; } - __device__ inline constexpr static auto one() noexcept { return lc_bool2{1, 1}; } - __device__ inline explicit constexpr lc_bool2(lc_bool s) noexcept - : x{s}, y{s} {} - __device__ inline constexpr lc_bool2(lc_bool x, lc_bool y) noexcept - : x{x}, y{y} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(4) lc_bool3 { - lc_bool x, y, z; - __device__ inline constexpr lc_bool3() noexcept - : x{}, y{}, z{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_bool3{}; } - __device__ inline constexpr static auto one() noexcept { return lc_bool3{1, 1, 1}; } - __device__ inline explicit constexpr lc_bool3(lc_bool s) noexcept - : x{s}, y{s}, z{s} {} - __device__ inline constexpr lc_bool3(lc_bool x, lc_bool y, lc_bool z) noexcept - : x{x}, y{y}, z{z} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(4) lc_bool4 { - lc_bool x, y, z, w; - __device__ inline constexpr lc_bool4() noexcept - : x{}, y{}, z{}, w{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_bool4{}; } - __device__ inline constexpr static auto one() noexcept { return lc_bool4{1, 1, 1, 1}; } - __device__ inline explicit constexpr lc_bool4(lc_bool s) noexcept - : x{s}, y{s}, z{s}, w{s} {} - __device__ inline constexpr lc_bool4(lc_bool x, lc_bool y, lc_bool z, lc_bool w) noexcept - : x{x}, y{y}, z{z}, w{w} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(16) lc_long2 { - lc_long x, y; - __device__ inline constexpr lc_long2() noexcept - : x{}, y{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_long2{}; } - __device__ inline constexpr static auto one() noexcept { return lc_long2{1, 1}; } - __device__ inline explicit constexpr lc_long2(lc_long s) noexcept - : x{s}, y{s} {} - __device__ inline constexpr lc_long2(lc_long x, lc_long y) noexcept - : x{x}, y{y} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(16) lc_long3 { - lc_long x, y, z; - __device__ inline constexpr lc_long3() noexcept - : x{}, y{}, z{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_long3{}; } - __device__ inline constexpr static auto one() noexcept { return lc_long3{1, 1, 1}; } - __device__ inline explicit constexpr lc_long3(lc_long s) noexcept - : x{s}, y{s}, z{s} {} - __device__ inline constexpr lc_long3(lc_long x, lc_long y, lc_long z) noexcept - : x{x}, y{y}, z{z} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(16) lc_long4 { - lc_long x, y, z, w; - __device__ inline constexpr lc_long4() noexcept - : x{}, y{}, z{}, w{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_long4{}; } - __device__ inline constexpr static auto one() noexcept { return lc_long4{1, 1, 1, 1}; } - __device__ inline explicit constexpr lc_long4(lc_long s) noexcept - : x{s}, y{s}, z{s}, w{s} {} - __device__ inline constexpr lc_long4(lc_long x, lc_long y, lc_long z, lc_long w) noexcept - : x{x}, y{y}, z{z}, w{w} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(16) lc_ulong2 { - lc_ulong x, y; - __device__ inline constexpr lc_ulong2() noexcept - : x{}, y{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_ulong2{}; } - __device__ inline constexpr static auto one() noexcept { return lc_ulong2{1, 1}; } - __device__ inline explicit constexpr lc_ulong2(lc_ulong s) noexcept - : x{s}, y{s} {} - __device__ inline constexpr lc_ulong2(lc_ulong x, lc_ulong y) noexcept - : x{x}, y{y} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(16) lc_ulong3 { - lc_ulong x, y, z; - __device__ inline constexpr lc_ulong3() noexcept - : x{}, y{}, z{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_ulong3{}; } - __device__ inline constexpr static auto one() noexcept { return lc_ulong3{1, 1, 1}; } - __device__ inline explicit constexpr lc_ulong3(lc_ulong s) noexcept - : x{s}, y{s}, z{s} {} - __device__ inline constexpr lc_ulong3(lc_ulong x, lc_ulong y, lc_ulong z) noexcept - : x{x}, y{y}, z{z} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -struct alignas(16) lc_ulong4 { - lc_ulong x, y, z, w; - __device__ inline constexpr lc_ulong4() noexcept - : x{}, y{}, z{}, w{} {} - __device__ inline constexpr static auto zero() noexcept { return lc_ulong4{}; } - __device__ inline constexpr static auto one() noexcept { return lc_ulong4{1, 1, 1, 1}; } - __device__ inline explicit constexpr lc_ulong4(lc_ulong s) noexcept - : x{s}, y{s}, z{s}, w{s} {} - __device__ inline constexpr lc_ulong4(lc_ulong x, lc_ulong y, lc_ulong z, lc_ulong w) noexcept - : x{x}, y{y}, z{z}, w{w} {} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } - __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } -}; - -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_byte s = 0) noexcept { return lc_byte2{s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_byte x, lc_byte y) noexcept { return lc_byte2{x, y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_byte2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_byte3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_byte4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ubyte2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ubyte3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ubyte4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_short2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_short3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_short4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ushort2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ushort3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ushort4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_int2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_int3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_int4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_uint2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_uint3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_uint4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_half2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_half3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_half4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_float2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_float3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_float4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_bool2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_bool3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_bool4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_long2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_long3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_long4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ulong2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ulong3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ulong4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_byte3(lc_byte s = 0) noexcept { return lc_byte3{s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte3(lc_byte x, lc_byte y, lc_byte z) noexcept { return lc_byte3{x, y, z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte3(lc_byte x, lc_byte2 yz) noexcept { return lc_byte3{x, yz.x, yz.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte3(lc_byte2 xy, lc_byte z) noexcept { return lc_byte3{xy.x, xy.y, z}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_byte3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_byte4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_ubyte3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_ubyte4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_short3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_short4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_ushort3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_ushort4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_int3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_int4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_uint3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_uint4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_half3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_half4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_float3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_float4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_bool3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_bool4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_long3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_long4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_ulong3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_ulong4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_byte s = 0) noexcept { return lc_byte4{s, s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte4(lc_byte x, lc_byte y, lc_byte z, lc_byte w) noexcept { return lc_byte4{x, y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte4(lc_byte x, lc_byte y, lc_byte2 zw) noexcept { return lc_byte4{x, y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte4(lc_byte x, lc_byte2 yz, lc_byte w) noexcept { return lc_byte4{x, yz.x, yz.y, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte4(lc_byte2 xy, lc_byte z, lc_byte w) noexcept { return lc_byte4{xy.x, xy.y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte4(lc_byte2 xy, lc_byte2 zw) noexcept { return lc_byte4{xy.x, xy.y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte4(lc_byte x, lc_byte3 yzw) noexcept { return lc_byte4{x, yzw.x, yzw.y, yzw.z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_byte4(lc_byte3 xyz, lc_byte w) noexcept { return lc_byte4{xyz.x, xyz.y, xyz.z, w}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_byte4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_ubyte4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_short4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_ushort4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_int4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_uint4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_half4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_float4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_bool4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_long4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_ulong4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } - -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ubyte s = 0) noexcept { return lc_ubyte2{s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ubyte x, lc_ubyte y) noexcept { return lc_ubyte2{x, y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_byte2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_byte3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_byte4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ubyte2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ubyte3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ubyte4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_short2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_short3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_short4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ushort2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ushort3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ushort4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_int2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_int3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_int4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_uint2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_uint3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_uint4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_half2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_half3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_half4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_float2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_float3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_float4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_bool2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_bool3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_bool4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_long2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_long3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_long4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ulong2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ulong3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ulong4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte3(lc_ubyte s = 0) noexcept { return lc_ubyte3{s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte3(lc_ubyte x, lc_ubyte y, lc_ubyte z) noexcept { return lc_ubyte3{x, y, z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte3(lc_ubyte x, lc_ubyte2 yz) noexcept { return lc_ubyte3{x, yz.x, yz.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte3(lc_ubyte2 xy, lc_ubyte z) noexcept { return lc_ubyte3{xy.x, xy.y, z}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_byte3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_byte4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_ubyte3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_ubyte4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_short3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_short4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_ushort3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_ushort4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_int3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_int4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_uint3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_uint4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_half3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_half4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_float3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_float4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_bool3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_bool4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_long3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_long4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_ulong3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_ulong4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_ubyte s = 0) noexcept { return lc_ubyte4{s, s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte4(lc_ubyte x, lc_ubyte y, lc_ubyte z, lc_ubyte w) noexcept { return lc_ubyte4{x, y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte4(lc_ubyte x, lc_ubyte y, lc_ubyte2 zw) noexcept { return lc_ubyte4{x, y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte4(lc_ubyte x, lc_ubyte2 yz, lc_ubyte w) noexcept { return lc_ubyte4{x, yz.x, yz.y, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte4(lc_ubyte2 xy, lc_ubyte z, lc_ubyte w) noexcept { return lc_ubyte4{xy.x, xy.y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte4(lc_ubyte2 xy, lc_ubyte2 zw) noexcept { return lc_ubyte4{xy.x, xy.y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte4(lc_ubyte x, lc_ubyte3 yzw) noexcept { return lc_ubyte4{x, yzw.x, yzw.y, yzw.z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte4(lc_ubyte3 xyz, lc_ubyte w) noexcept { return lc_ubyte4{xyz.x, xyz.y, xyz.z, w}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_byte4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_ubyte4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_short4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_ushort4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_int4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_uint4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_half4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_float4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_bool4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_long4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_ulong4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } - -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_short s = 0) noexcept { return lc_short2{s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_short x, lc_short y) noexcept { return lc_short2{x, y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_byte2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_byte3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_byte4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ubyte2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ubyte3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ubyte4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_short2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_short3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_short4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ushort2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ushort3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ushort4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_int2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_int3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_int4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_uint2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_uint3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_uint4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_half2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_half3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_half4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_float2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_float3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_float4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_bool2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_bool3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_bool4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_long2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_long3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_long4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ulong2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ulong3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ulong4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_short3(lc_short s = 0) noexcept { return lc_short3{s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short3(lc_short x, lc_short y, lc_short z) noexcept { return lc_short3{x, y, z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short3(lc_short x, lc_short2 yz) noexcept { return lc_short3{x, yz.x, yz.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short3(lc_short2 xy, lc_short z) noexcept { return lc_short3{xy.x, xy.y, z}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_byte3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_byte4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_ubyte3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_ubyte4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_short3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_short4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_ushort3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_ushort4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_int3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_int4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_uint3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_uint4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_half3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_half4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_float3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_float4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_bool3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_bool4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_long3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_long4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_ulong3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_ulong4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_short s = 0) noexcept { return lc_short4{s, s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short4(lc_short x, lc_short y, lc_short z, lc_short w) noexcept { return lc_short4{x, y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short4(lc_short x, lc_short y, lc_short2 zw) noexcept { return lc_short4{x, y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short4(lc_short x, lc_short2 yz, lc_short w) noexcept { return lc_short4{x, yz.x, yz.y, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short4(lc_short2 xy, lc_short z, lc_short w) noexcept { return lc_short4{xy.x, xy.y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short4(lc_short2 xy, lc_short2 zw) noexcept { return lc_short4{xy.x, xy.y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short4(lc_short x, lc_short3 yzw) noexcept { return lc_short4{x, yzw.x, yzw.y, yzw.z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_short4(lc_short3 xyz, lc_short w) noexcept { return lc_short4{xyz.x, xyz.y, xyz.z, w}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_byte4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_ubyte4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_short4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_ushort4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_int4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_uint4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_half4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_float4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_bool4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_long4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_ulong4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } - -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ushort s = 0) noexcept { return lc_ushort2{s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ushort x, lc_ushort y) noexcept { return lc_ushort2{x, y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_byte2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_byte3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_byte4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ubyte2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ubyte3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ubyte4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_short2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_short3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_short4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ushort2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ushort3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ushort4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_int2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_int3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_int4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_uint2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_uint3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_uint4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_half2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_half3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_half4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_float2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_float3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_float4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_bool2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_bool3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_bool4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_long2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_long3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_long4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ulong2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ulong3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ulong4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ushort3(lc_ushort s = 0) noexcept { return lc_ushort3{s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort3(lc_ushort x, lc_ushort y, lc_ushort z) noexcept { return lc_ushort3{x, y, z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort3(lc_ushort x, lc_ushort2 yz) noexcept { return lc_ushort3{x, yz.x, yz.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort3(lc_ushort2 xy, lc_ushort z) noexcept { return lc_ushort3{xy.x, xy.y, z}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_byte3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_byte4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_ubyte3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_ubyte4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_short3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_short4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_ushort3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_ushort4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_int3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_int4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_uint3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_uint4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_half3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_half4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_float3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_float4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_bool3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_bool4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_long3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_long4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_ulong3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_ulong4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_ushort s = 0) noexcept { return lc_ushort4{s, s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort4(lc_ushort x, lc_ushort y, lc_ushort z, lc_ushort w) noexcept { return lc_ushort4{x, y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort4(lc_ushort x, lc_ushort y, lc_ushort2 zw) noexcept { return lc_ushort4{x, y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort4(lc_ushort x, lc_ushort2 yz, lc_ushort w) noexcept { return lc_ushort4{x, yz.x, yz.y, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort4(lc_ushort2 xy, lc_ushort z, lc_ushort w) noexcept { return lc_ushort4{xy.x, xy.y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort4(lc_ushort2 xy, lc_ushort2 zw) noexcept { return lc_ushort4{xy.x, xy.y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort4(lc_ushort x, lc_ushort3 yzw) noexcept { return lc_ushort4{x, yzw.x, yzw.y, yzw.z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ushort4(lc_ushort3 xyz, lc_ushort w) noexcept { return lc_ushort4{xyz.x, xyz.y, xyz.z, w}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_byte4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_ubyte4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_short4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_ushort4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_int4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_uint4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_half4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_float4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_bool4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_long4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_ulong4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } - -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_int s = 0) noexcept { return lc_int2{s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_int x, lc_int y) noexcept { return lc_int2{x, y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_byte2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_byte3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_byte4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ubyte2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ubyte3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ubyte4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_short2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_short3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_short4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ushort2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ushort3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ushort4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_int2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_int3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_int4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_uint2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_uint3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_uint4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_half2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_half3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_half4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_float2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_float3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_float4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_bool2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_bool3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_bool4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_long2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_long3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_long4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ulong2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ulong3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ulong4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_int3(lc_int s = 0) noexcept { return lc_int3{s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int3(lc_int x, lc_int y, lc_int z) noexcept { return lc_int3{x, y, z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int3(lc_int x, lc_int2 yz) noexcept { return lc_int3{x, yz.x, yz.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int3(lc_int2 xy, lc_int z) noexcept { return lc_int3{xy.x, xy.y, z}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_byte3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_byte4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_ubyte3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_ubyte4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_short3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_short4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_ushort3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_ushort4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_int3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_int4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_uint3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_uint4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_half3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_half4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_float3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_float4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_bool3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_bool4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_long3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_long4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_ulong3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_ulong4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_int s = 0) noexcept { return lc_int4{s, s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int4(lc_int x, lc_int y, lc_int z, lc_int w) noexcept { return lc_int4{x, y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int4(lc_int x, lc_int y, lc_int2 zw) noexcept { return lc_int4{x, y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int4(lc_int x, lc_int2 yz, lc_int w) noexcept { return lc_int4{x, yz.x, yz.y, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int4(lc_int2 xy, lc_int z, lc_int w) noexcept { return lc_int4{xy.x, xy.y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int4(lc_int2 xy, lc_int2 zw) noexcept { return lc_int4{xy.x, xy.y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int4(lc_int x, lc_int3 yzw) noexcept { return lc_int4{x, yzw.x, yzw.y, yzw.z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_int4(lc_int3 xyz, lc_int w) noexcept { return lc_int4{xyz.x, xyz.y, xyz.z, w}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_byte4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_ubyte4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_short4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_ushort4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_int4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_uint4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_half4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_float4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_bool4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_long4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_ulong4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } - -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_uint s = 0) noexcept { return lc_uint2{s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_uint x, lc_uint y) noexcept { return lc_uint2{x, y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_byte2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_byte3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_byte4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ubyte2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ubyte3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ubyte4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_short2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_short3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_short4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ushort2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ushort3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ushort4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_int2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_int3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_int4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_uint2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_uint3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_uint4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_half2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_half3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_half4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_float2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_float3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_float4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_bool2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_bool3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_bool4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_long2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_long3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_long4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ulong2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ulong3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ulong4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_uint3(lc_uint s = 0) noexcept { return lc_uint3{s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint3(lc_uint x, lc_uint y, lc_uint z) noexcept { return lc_uint3{x, y, z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint3(lc_uint x, lc_uint2 yz) noexcept { return lc_uint3{x, yz.x, yz.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint3(lc_uint2 xy, lc_uint z) noexcept { return lc_uint3{xy.x, xy.y, z}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_byte3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_byte4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_ubyte3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_ubyte4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_short3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_short4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_ushort3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_ushort4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_int3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_int4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_uint3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_uint4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_half3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_half4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_float3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_float4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_bool3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_bool4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_long3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_long4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_ulong3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_ulong4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_uint s = 0) noexcept { return lc_uint4{s, s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint4(lc_uint x, lc_uint y, lc_uint z, lc_uint w) noexcept { return lc_uint4{x, y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint4(lc_uint x, lc_uint y, lc_uint2 zw) noexcept { return lc_uint4{x, y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint4(lc_uint x, lc_uint2 yz, lc_uint w) noexcept { return lc_uint4{x, yz.x, yz.y, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint4(lc_uint2 xy, lc_uint z, lc_uint w) noexcept { return lc_uint4{xy.x, xy.y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint4(lc_uint2 xy, lc_uint2 zw) noexcept { return lc_uint4{xy.x, xy.y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint4(lc_uint x, lc_uint3 yzw) noexcept { return lc_uint4{x, yzw.x, yzw.y, yzw.z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_uint4(lc_uint3 xyz, lc_uint w) noexcept { return lc_uint4{xyz.x, xyz.y, xyz.z, w}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_byte4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_ubyte4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_short4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_ushort4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_int4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_uint4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_half4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_float4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_bool4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_long4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_ulong4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } - -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_half s = 0) noexcept { return lc_half2{s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_half x, lc_half y) noexcept { return lc_half2{x, y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_byte2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_byte3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_byte4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ubyte2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ubyte3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ubyte4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_short2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_short3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_short4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ushort2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ushort3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ushort4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_int2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_int3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_int4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_uint2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_uint3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_uint4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_half2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_half3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_half4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_float2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_float3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_float4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_bool2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_bool3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_bool4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_long2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_long3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_long4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ulong2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ulong3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ulong4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_half3(lc_half s = 0) noexcept { return lc_half3{s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half3(lc_half x, lc_half y, lc_half z) noexcept { return lc_half3{x, y, z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half3(lc_half x, lc_half2 yz) noexcept { return lc_half3{x, yz.x, yz.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half3(lc_half2 xy, lc_half z) noexcept { return lc_half3{xy.x, xy.y, z}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_byte3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_byte4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_ubyte3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_ubyte4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_short3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_short4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_ushort3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_ushort4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_int3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_int4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_uint3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_uint4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_half3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_half4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_float3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_float4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_bool3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_bool4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_long3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_long4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_ulong3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_ulong4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_half s = 0) noexcept { return lc_half4{s, s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half4(lc_half x, lc_half y, lc_half z, lc_half w) noexcept { return lc_half4{x, y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half4(lc_half x, lc_half y, lc_half2 zw) noexcept { return lc_half4{x, y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half4(lc_half x, lc_half2 yz, lc_half w) noexcept { return lc_half4{x, yz.x, yz.y, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half4(lc_half2 xy, lc_half z, lc_half w) noexcept { return lc_half4{xy.x, xy.y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half4(lc_half2 xy, lc_half2 zw) noexcept { return lc_half4{xy.x, xy.y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half4(lc_half x, lc_half3 yzw) noexcept { return lc_half4{x, yzw.x, yzw.y, yzw.z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_half4(lc_half3 xyz, lc_half w) noexcept { return lc_half4{xyz.x, xyz.y, xyz.z, w}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_byte4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_ubyte4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_short4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_ushort4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_int4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_uint4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_half4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_float4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_bool4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_long4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_ulong4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } - -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_float s = 0) noexcept { return lc_float2{s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_float x, lc_float y) noexcept { return lc_float2{x, y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_byte2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_byte3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_byte4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ubyte2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ubyte3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ubyte4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_short2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_short3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_short4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ushort2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ushort3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ushort4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_int2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_int3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_int4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_uint2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_uint3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_uint4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_half2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_half3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_half4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_float2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_float3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_float4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_bool2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_bool3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_bool4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_long2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_long3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_long4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ulong2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ulong3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ulong4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_float3(lc_float s = 0) noexcept { return lc_float3{s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float3(lc_float x, lc_float y, lc_float z) noexcept { return lc_float3{x, y, z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float3(lc_float x, lc_float2 yz) noexcept { return lc_float3{x, yz.x, yz.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float3(lc_float2 xy, lc_float z) noexcept { return lc_float3{xy.x, xy.y, z}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_byte3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_byte4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_ubyte3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_ubyte4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_short3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_short4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_ushort3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_ushort4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_int3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_int4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_uint3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_uint4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_half3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_half4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_float3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_float4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_bool3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_bool4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_long3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_long4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_ulong3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_ulong4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_float s = 0) noexcept { return lc_float4{s, s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float4(lc_float x, lc_float y, lc_float z, lc_float w) noexcept { return lc_float4{x, y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float4(lc_float x, lc_float y, lc_float2 zw) noexcept { return lc_float4{x, y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float4(lc_float x, lc_float2 yz, lc_float w) noexcept { return lc_float4{x, yz.x, yz.y, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float4(lc_float2 xy, lc_float z, lc_float w) noexcept { return lc_float4{xy.x, xy.y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float4(lc_float2 xy, lc_float2 zw) noexcept { return lc_float4{xy.x, xy.y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float4(lc_float x, lc_float3 yzw) noexcept { return lc_float4{x, yzw.x, yzw.y, yzw.z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float4(lc_float3 xyz, lc_float w) noexcept { return lc_float4{xyz.x, xyz.y, xyz.z, w}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_byte4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_ubyte4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_short4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_ushort4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_int4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_uint4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_half4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_float4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_bool4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_long4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_ulong4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } - -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_bool s = 0) noexcept { return lc_bool2{s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_bool x, lc_bool y) noexcept { return lc_bool2{x, y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_byte2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_byte3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_byte4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ubyte2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ubyte3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ubyte4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_short2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_short3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_short4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ushort2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ushort3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ushort4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_int2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_int3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_int4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_uint2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_uint3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_uint4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_half2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_half3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_half4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_float2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_float3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_float4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_bool2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_bool3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_bool4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_long2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_long3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_long4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ulong2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ulong3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ulong4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_bool3(lc_bool s = 0) noexcept { return lc_bool3{s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool3(lc_bool x, lc_bool y, lc_bool z) noexcept { return lc_bool3{x, y, z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool3(lc_bool x, lc_bool2 yz) noexcept { return lc_bool3{x, yz.x, yz.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool3(lc_bool2 xy, lc_bool z) noexcept { return lc_bool3{xy.x, xy.y, z}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_byte3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_byte4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_ubyte3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_ubyte4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_short3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_short4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_ushort3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_ushort4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_int3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_int4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_uint3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_uint4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_half3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_half4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_float3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_float4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_bool3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_bool4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_long3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_long4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_ulong3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_ulong4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_bool s = 0) noexcept { return lc_bool4{s, s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool4(lc_bool x, lc_bool y, lc_bool z, lc_bool w) noexcept { return lc_bool4{x, y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool4(lc_bool x, lc_bool y, lc_bool2 zw) noexcept { return lc_bool4{x, y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool4(lc_bool x, lc_bool2 yz, lc_bool w) noexcept { return lc_bool4{x, yz.x, yz.y, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool4(lc_bool2 xy, lc_bool z, lc_bool w) noexcept { return lc_bool4{xy.x, xy.y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool4(lc_bool2 xy, lc_bool2 zw) noexcept { return lc_bool4{xy.x, xy.y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool4(lc_bool x, lc_bool3 yzw) noexcept { return lc_bool4{x, yzw.x, yzw.y, yzw.z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_bool4(lc_bool3 xyz, lc_bool w) noexcept { return lc_bool4{xyz.x, xyz.y, xyz.z, w}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_byte4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_ubyte4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_short4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_ushort4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_int4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_uint4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_half4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_float4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_bool4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_long4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_ulong4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } - -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_long s = 0) noexcept { return lc_long2{s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_long x, lc_long y) noexcept { return lc_long2{x, y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_byte2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_byte3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_byte4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ubyte2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ubyte3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ubyte4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_short2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_short3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_short4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ushort2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ushort3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ushort4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_int2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_int3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_int4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_uint2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_uint3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_uint4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_half2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_half3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_half4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_float2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_float3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_float4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_bool2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_bool3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_bool4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_long2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_long3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_long4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ulong2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ulong3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ulong4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_long3(lc_long s = 0) noexcept { return lc_long3{s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long3(lc_long x, lc_long y, lc_long z) noexcept { return lc_long3{x, y, z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long3(lc_long x, lc_long2 yz) noexcept { return lc_long3{x, yz.x, yz.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long3(lc_long2 xy, lc_long z) noexcept { return lc_long3{xy.x, xy.y, z}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_byte3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_byte4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_ubyte3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_ubyte4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_short3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_short4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_ushort3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_ushort4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_int3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_int4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_uint3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_uint4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_half3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_half4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_float3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_float4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_bool3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_bool4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_long3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_long4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_ulong3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_ulong4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_long s = 0) noexcept { return lc_long4{s, s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long4(lc_long x, lc_long y, lc_long z, lc_long w) noexcept { return lc_long4{x, y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long4(lc_long x, lc_long y, lc_long2 zw) noexcept { return lc_long4{x, y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long4(lc_long x, lc_long2 yz, lc_long w) noexcept { return lc_long4{x, yz.x, yz.y, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long4(lc_long2 xy, lc_long z, lc_long w) noexcept { return lc_long4{xy.x, xy.y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long4(lc_long2 xy, lc_long2 zw) noexcept { return lc_long4{xy.x, xy.y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long4(lc_long x, lc_long3 yzw) noexcept { return lc_long4{x, yzw.x, yzw.y, yzw.z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_long4(lc_long3 xyz, lc_long w) noexcept { return lc_long4{xyz.x, xyz.y, xyz.z, w}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_byte4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_ubyte4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_short4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_ushort4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_int4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_uint4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_half4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_float4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_bool4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_long4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_ulong4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } - -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ulong s = 0) noexcept { return lc_ulong2{s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ulong x, lc_ulong y) noexcept { return lc_ulong2{x, y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_byte2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_byte3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_byte4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ubyte2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ubyte3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ubyte4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_short2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_short3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_short4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ushort2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ushort3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ushort4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_int2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_int3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_int4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_uint2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_uint3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_uint4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_half2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_half3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_half4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_float2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_float3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_float4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_bool2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_bool3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_bool4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_long2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_long3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_long4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ulong2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ulong3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ulong4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ulong3(lc_ulong s = 0) noexcept { return lc_ulong3{s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong3(lc_ulong x, lc_ulong y, lc_ulong z) noexcept { return lc_ulong3{x, y, z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong3(lc_ulong x, lc_ulong2 yz) noexcept { return lc_ulong3{x, yz.x, yz.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong3(lc_ulong2 xy, lc_ulong z) noexcept { return lc_ulong3{xy.x, xy.y, z}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_byte3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_byte4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_ubyte3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_ubyte4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_short3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_short4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_ushort3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_ushort4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_int3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_int4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_uint3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_uint4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_half3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_half4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_float3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_float4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_bool3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_bool4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_long3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_long4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_ulong3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_ulong4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_ulong s = 0) noexcept { return lc_ulong4{s, s, s, s}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong4(lc_ulong x, lc_ulong y, lc_ulong z, lc_ulong w) noexcept { return lc_ulong4{x, y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong4(lc_ulong x, lc_ulong y, lc_ulong2 zw) noexcept { return lc_ulong4{x, y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong4(lc_ulong x, lc_ulong2 yz, lc_ulong w) noexcept { return lc_ulong4{x, yz.x, yz.y, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong4(lc_ulong2 xy, lc_ulong z, lc_ulong w) noexcept { return lc_ulong4{xy.x, xy.y, z, w}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong4(lc_ulong2 xy, lc_ulong2 zw) noexcept { return lc_ulong4{xy.x, xy.y, zw.x, zw.y}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong4(lc_ulong x, lc_ulong3 yzw) noexcept { return lc_ulong4{x, yzw.x, yzw.y, yzw.z}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_ulong4(lc_ulong3 xyz, lc_ulong w) noexcept { return lc_ulong4{xyz.x, xyz.y, xyz.z, w}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_byte4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_ubyte4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_short4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_ushort4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_int4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_uint4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_half4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_float4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_bool4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_long4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } -[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_ulong4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } - -[[nodiscard]] inline __device__ constexpr auto operator!(lc_byte2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_byte2 v) noexcept { return lc_make_byte2(+v.x, +v.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_byte2 v) noexcept { return lc_make_byte2(-v.x, -v.y); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_byte2 v) noexcept { return lc_make_byte2(~v.x, ~v.y); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_byte3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_byte3 v) noexcept { return lc_make_byte3(+v.x, +v.y, +v.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_byte3 v) noexcept { return lc_make_byte3(-v.x, -v.y, -v.z); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_byte3 v) noexcept { return lc_make_byte3(~v.x, ~v.y, ~v.z); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_byte4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_byte4 v) noexcept { return lc_make_byte4(+v.x, +v.y, +v.z, +v.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_byte4 v) noexcept { return lc_make_byte4(-v.x, -v.y, -v.z, -v.w); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_byte4 v) noexcept { return lc_make_byte4(~v.x, ~v.y, ~v.z, ~v.w); } - -[[nodiscard]] inline __device__ constexpr auto operator!(lc_ubyte2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ubyte2 v) noexcept { return lc_make_ubyte2(+v.x, +v.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ubyte2 v) noexcept { return lc_make_ubyte2(-v.x, -v.y); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_ubyte2 v) noexcept { return lc_make_ubyte2(~v.x, ~v.y); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_ubyte3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ubyte3 v) noexcept { return lc_make_ubyte3(+v.x, +v.y, +v.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ubyte3 v) noexcept { return lc_make_ubyte3(-v.x, -v.y, -v.z); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_ubyte3 v) noexcept { return lc_make_ubyte3(~v.x, ~v.y, ~v.z); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_ubyte4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ubyte4 v) noexcept { return lc_make_ubyte4(+v.x, +v.y, +v.z, +v.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ubyte4 v) noexcept { return lc_make_ubyte4(-v.x, -v.y, -v.z, -v.w); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_ubyte4 v) noexcept { return lc_make_ubyte4(~v.x, ~v.y, ~v.z, ~v.w); } - -[[nodiscard]] inline __device__ constexpr auto operator!(lc_short2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_short2 v) noexcept { return lc_make_short2(+v.x, +v.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_short2 v) noexcept { return lc_make_short2(-v.x, -v.y); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_short2 v) noexcept { return lc_make_short2(~v.x, ~v.y); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_short3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_short3 v) noexcept { return lc_make_short3(+v.x, +v.y, +v.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_short3 v) noexcept { return lc_make_short3(-v.x, -v.y, -v.z); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_short3 v) noexcept { return lc_make_short3(~v.x, ~v.y, ~v.z); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_short4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_short4 v) noexcept { return lc_make_short4(+v.x, +v.y, +v.z, +v.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_short4 v) noexcept { return lc_make_short4(-v.x, -v.y, -v.z, -v.w); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_short4 v) noexcept { return lc_make_short4(~v.x, ~v.y, ~v.z, ~v.w); } - -[[nodiscard]] inline __device__ constexpr auto operator!(lc_ushort2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort2 v) noexcept { return lc_make_ushort2(+v.x, +v.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort2 v) noexcept { return lc_make_ushort2(-v.x, -v.y); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_ushort2 v) noexcept { return lc_make_ushort2(~v.x, ~v.y); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_ushort3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort3 v) noexcept { return lc_make_ushort3(+v.x, +v.y, +v.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort3 v) noexcept { return lc_make_ushort3(-v.x, -v.y, -v.z); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_ushort3 v) noexcept { return lc_make_ushort3(~v.x, ~v.y, ~v.z); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_ushort4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort4 v) noexcept { return lc_make_ushort4(+v.x, +v.y, +v.z, +v.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort4 v) noexcept { return lc_make_ushort4(-v.x, -v.y, -v.z, -v.w); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_ushort4 v) noexcept { return lc_make_ushort4(~v.x, ~v.y, ~v.z, ~v.w); } - -[[nodiscard]] inline __device__ constexpr auto operator!(lc_int2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_int2 v) noexcept { return lc_make_int2(+v.x, +v.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_int2 v) noexcept { return lc_make_int2(-v.x, -v.y); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_int2 v) noexcept { return lc_make_int2(~v.x, ~v.y); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_int3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_int3 v) noexcept { return lc_make_int3(+v.x, +v.y, +v.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_int3 v) noexcept { return lc_make_int3(-v.x, -v.y, -v.z); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_int3 v) noexcept { return lc_make_int3(~v.x, ~v.y, ~v.z); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_int4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_int4 v) noexcept { return lc_make_int4(+v.x, +v.y, +v.z, +v.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_int4 v) noexcept { return lc_make_int4(-v.x, -v.y, -v.z, -v.w); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_int4 v) noexcept { return lc_make_int4(~v.x, ~v.y, ~v.z, ~v.w); } - -[[nodiscard]] inline __device__ constexpr auto operator!(lc_uint2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint2 v) noexcept { return lc_make_uint2(+v.x, +v.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint2 v) noexcept { return lc_make_uint2(-v.x, -v.y); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_uint2 v) noexcept { return lc_make_uint2(~v.x, ~v.y); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_uint3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint3 v) noexcept { return lc_make_uint3(+v.x, +v.y, +v.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint3 v) noexcept { return lc_make_uint3(-v.x, -v.y, -v.z); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_uint3 v) noexcept { return lc_make_uint3(~v.x, ~v.y, ~v.z); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_uint4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint4 v) noexcept { return lc_make_uint4(+v.x, +v.y, +v.z, +v.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint4 v) noexcept { return lc_make_uint4(-v.x, -v.y, -v.z, -v.w); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_uint4 v) noexcept { return lc_make_uint4(~v.x, ~v.y, ~v.z, ~v.w); } - -[[nodiscard]] inline __device__ constexpr auto operator!(lc_half2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_half2 v) noexcept { return lc_make_half2(+v.x, +v.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_half2 v) noexcept { return lc_make_half2(-v.x, -v.y); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_half3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_half3 v) noexcept { return lc_make_half3(+v.x, +v.y, +v.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_half3 v) noexcept { return lc_make_half3(-v.x, -v.y, -v.z); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_half4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_half4 v) noexcept { return lc_make_half4(+v.x, +v.y, +v.z, +v.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_half4 v) noexcept { return lc_make_half4(-v.x, -v.y, -v.z, -v.w); } - -[[nodiscard]] inline __device__ constexpr auto operator!(lc_float2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_float2 v) noexcept { return lc_make_float2(+v.x, +v.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_float2 v) noexcept { return lc_make_float2(-v.x, -v.y); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_float3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_float3 v) noexcept { return lc_make_float3(+v.x, +v.y, +v.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_float3 v) noexcept { return lc_make_float3(-v.x, -v.y, -v.z); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_float4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_float4 v) noexcept { return lc_make_float4(+v.x, +v.y, +v.z, +v.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_float4 v) noexcept { return lc_make_float4(-v.x, -v.y, -v.z, -v.w); } - -[[nodiscard]] inline __device__ constexpr auto operator!(lc_bool2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_bool3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_bool4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } - -[[nodiscard]] inline __device__ constexpr auto operator!(lc_long2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_long2 v) noexcept { return lc_make_long2(+v.x, +v.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_long2 v) noexcept { return lc_make_long2(-v.x, -v.y); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_long2 v) noexcept { return lc_make_long2(~v.x, ~v.y); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_long3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_long3 v) noexcept { return lc_make_long3(+v.x, +v.y, +v.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_long3 v) noexcept { return lc_make_long3(-v.x, -v.y, -v.z); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_long3 v) noexcept { return lc_make_long3(~v.x, ~v.y, ~v.z); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_long4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_long4 v) noexcept { return lc_make_long4(+v.x, +v.y, +v.z, +v.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_long4 v) noexcept { return lc_make_long4(-v.x, -v.y, -v.z, -v.w); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_long4 v) noexcept { return lc_make_long4(~v.x, ~v.y, ~v.z, ~v.w); } - -[[nodiscard]] inline __device__ constexpr auto operator!(lc_ulong2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong2 v) noexcept { return lc_make_ulong2(+v.x, +v.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong2 v) noexcept { return lc_make_ulong2(-v.x, -v.y); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_ulong2 v) noexcept { return lc_make_ulong2(~v.x, ~v.y); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_ulong3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong3 v) noexcept { return lc_make_ulong3(+v.x, +v.y, +v.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong3 v) noexcept { return lc_make_ulong3(-v.x, -v.y, -v.z); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_ulong3 v) noexcept { return lc_make_ulong3(~v.x, ~v.y, ~v.z); } -[[nodiscard]] inline __device__ constexpr auto operator!(lc_ulong4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong4 v) noexcept { return lc_make_ulong4(+v.x, +v.y, +v.z, +v.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong4 v) noexcept { return lc_make_ulong4(-v.x, -v.y, -v.z, -v.w); } -[[nodiscard]] inline __device__ constexpr auto operator~(lc_ulong4 v) noexcept { return lc_make_ulong4(~v.x, ~v.y, ~v.z, ~v.w); } - -[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte2 lhs, lc_byte2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte2 lhs, lc_byte rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte lhs, lc_byte2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte3 lhs, lc_byte3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte3 lhs, lc_byte rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte lhs, lc_byte3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte4 lhs, lc_byte4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte4 lhs, lc_byte rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte lhs, lc_byte4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte2 lhs, lc_ubyte2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte2 lhs, lc_ubyte rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte lhs, lc_ubyte2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte3 lhs, lc_ubyte3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte3 lhs, lc_ubyte rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte lhs, lc_ubyte3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte4 lhs, lc_ubyte4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte4 lhs, lc_ubyte rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte lhs, lc_ubyte4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool2 lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool2 lhs, lc_bool rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool3 lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool3 lhs, lc_bool rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool4 lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool4 lhs, lc_bool rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } -[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte2 lhs, lc_byte2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte2 lhs, lc_byte rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte lhs, lc_byte2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte3 lhs, lc_byte3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte3 lhs, lc_byte rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte lhs, lc_byte3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte4 lhs, lc_byte4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte4 lhs, lc_byte rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte lhs, lc_byte4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte2 lhs, lc_ubyte2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte2 lhs, lc_ubyte rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte lhs, lc_ubyte2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte3 lhs, lc_ubyte3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte3 lhs, lc_ubyte rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte lhs, lc_ubyte3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte4 lhs, lc_ubyte4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte4 lhs, lc_ubyte rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte lhs, lc_ubyte4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool2 lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool2 lhs, lc_bool rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool3 lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool3 lhs, lc_bool rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool4 lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool4 lhs, lc_bool rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } -[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator<(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator>(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator+(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x + rhs.x, lhs.y + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x + rhs, lhs.y + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs + rhs.x, lhs + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x + rhs.x, lhs.y + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x + rhs, lhs.y + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs + rhs.x, lhs + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x + rhs.x, lhs.y + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x + rhs, lhs.y + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs + rhs.x, lhs + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x + rhs.x, lhs.y + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x + rhs, lhs.y + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs + rhs.x, lhs + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs.x + rhs.x, lhs.y + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_half2(lhs.x + rhs, lhs.y + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs + rhs.x, lhs + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_half3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_half4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs.x + rhs.x, lhs.y + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_float2(lhs.x + rhs, lhs.y + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs + rhs.x, lhs + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_float3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_float4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x + rhs.x, lhs.y + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x + rhs, lhs.y + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs + rhs.x, lhs + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x + rhs.x, lhs.y + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x + rhs, lhs.y + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs + rhs.x, lhs + rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } -[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator-(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x - rhs.x, lhs.y - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x - rhs, lhs.y - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs - rhs.x, lhs - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x - rhs.x, lhs.y - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x - rhs, lhs.y - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs - rhs.x, lhs - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x - rhs.x, lhs.y - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x - rhs, lhs.y - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs - rhs.x, lhs - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x - rhs.x, lhs.y - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x - rhs, lhs.y - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs - rhs.x, lhs - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs.x - rhs.x, lhs.y - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_half2(lhs.x - rhs, lhs.y - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs - rhs.x, lhs - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_half3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_half4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs.x - rhs.x, lhs.y - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_float2(lhs.x - rhs, lhs.y - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs - rhs.x, lhs - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_float3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_float4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x - rhs.x, lhs.y - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x - rhs, lhs.y - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs - rhs.x, lhs - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x - rhs.x, lhs.y - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x - rhs, lhs.y - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs - rhs.x, lhs - rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } -[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator*(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x * rhs.x, lhs.y * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x * rhs, lhs.y * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs * rhs.x, lhs * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x * rhs.x, lhs.y * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x * rhs, lhs.y * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs * rhs.x, lhs * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x * rhs.x, lhs.y * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x * rhs, lhs.y * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs * rhs.x, lhs * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x * rhs.x, lhs.y * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x * rhs, lhs.y * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs * rhs.x, lhs * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs.x * rhs.x, lhs.y * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_half2(lhs.x * rhs, lhs.y * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs * rhs.x, lhs * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_half3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_half4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs.x * rhs.x, lhs.y * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_float2(lhs.x * rhs, lhs.y * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs * rhs.x, lhs * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_float3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_float4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x * rhs.x, lhs.y * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x * rhs, lhs.y * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs * rhs.x, lhs * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x * rhs.x, lhs.y * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x * rhs, lhs.y * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs * rhs.x, lhs * rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } -[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator/(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x / rhs.x, lhs.y / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x / rhs, lhs.y / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs / rhs.x, lhs / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x / rhs.x, lhs.y / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x / rhs, lhs.y / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs / rhs.x, lhs / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x / rhs.x, lhs.y / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x / rhs, lhs.y / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs / rhs.x, lhs / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x / rhs.x, lhs.y / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x / rhs, lhs.y / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs / rhs.x, lhs / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs.x / rhs.x, lhs.y / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_half2(lhs.x / rhs, lhs.y / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs / rhs.x, lhs / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_half3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_half4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs.x / rhs.x, lhs.y / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_float2(lhs.x / rhs, lhs.y / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs / rhs.x, lhs / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_float3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_float4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x / rhs.x, lhs.y / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x / rhs, lhs.y / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs / rhs.x, lhs / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x / rhs.x, lhs.y / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x / rhs, lhs.y / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs / rhs.x, lhs / rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } -[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator%(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x % rhs.x, lhs.y % rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x % rhs, lhs.y % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs % rhs.x, lhs % rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z, lhs.w % rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs, lhs.w % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z, lhs % rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x % rhs.x, lhs.y % rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x % rhs, lhs.y % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs % rhs.x, lhs % rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z, lhs.w % rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs, lhs.w % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z, lhs % rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x % rhs.x, lhs.y % rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x % rhs, lhs.y % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs % rhs.x, lhs % rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z, lhs.w % rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs, lhs.w % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z, lhs % rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x % rhs.x, lhs.y % rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x % rhs, lhs.y % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs % rhs.x, lhs % rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z, lhs.w % rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs, lhs.w % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z, lhs % rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x % rhs.x, lhs.y % rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x % rhs, lhs.y % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs % rhs.x, lhs % rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z, lhs.w % rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs, lhs.w % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z, lhs % rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x % rhs.x, lhs.y % rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x % rhs, lhs.y % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs % rhs.x, lhs % rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z, lhs.w % rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs, lhs.w % rhs); } -[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z, lhs % rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x << rhs.x, lhs.y << rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x << rhs, lhs.y << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs << rhs.x, lhs << rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z, lhs.w << rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs, lhs.w << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z, lhs << rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x << rhs.x, lhs.y << rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x << rhs, lhs.y << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs << rhs.x, lhs << rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z, lhs.w << rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs, lhs.w << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z, lhs << rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x << rhs.x, lhs.y << rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x << rhs, lhs.y << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs << rhs.x, lhs << rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z, lhs.w << rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs, lhs.w << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z, lhs << rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x << rhs.x, lhs.y << rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x << rhs, lhs.y << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs << rhs.x, lhs << rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z, lhs.w << rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs, lhs.w << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z, lhs << rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x << rhs.x, lhs.y << rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x << rhs, lhs.y << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs << rhs.x, lhs << rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z, lhs.w << rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs, lhs.w << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z, lhs << rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x << rhs.x, lhs.y << rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x << rhs, lhs.y << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs << rhs.x, lhs << rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z, lhs.w << rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs, lhs.w << rhs); } -[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z, lhs << rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x >> rhs.x, lhs.y >> rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x >> rhs, lhs.y >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs >> rhs.x, lhs >> rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z, lhs.w >> rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs, lhs.w >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z, lhs >> rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x >> rhs.x, lhs.y >> rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x >> rhs, lhs.y >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs >> rhs.x, lhs >> rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z, lhs.w >> rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs, lhs.w >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z, lhs >> rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x >> rhs.x, lhs.y >> rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x >> rhs, lhs.y >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs >> rhs.x, lhs >> rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z, lhs.w >> rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs, lhs.w >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z, lhs >> rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x >> rhs.x, lhs.y >> rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x >> rhs, lhs.y >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs >> rhs.x, lhs >> rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z, lhs.w >> rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs, lhs.w >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z, lhs >> rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x >> rhs.x, lhs.y >> rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x >> rhs, lhs.y >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs >> rhs.x, lhs >> rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z, lhs.w >> rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs, lhs.w >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z, lhs >> rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x >> rhs.x, lhs.y >> rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x >> rhs, lhs.y >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs >> rhs.x, lhs >> rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z, lhs.w >> rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs, lhs.w >> rhs); } -[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z, lhs >> rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator|(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x | rhs.x, lhs.y | rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x | rhs, lhs.y | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs | rhs.x, lhs | rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z, lhs.w | rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs, lhs.w | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z, lhs | rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x | rhs.x, lhs.y | rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x | rhs, lhs.y | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs | rhs.x, lhs | rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z, lhs.w | rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs, lhs.w | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z, lhs | rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x | rhs.x, lhs.y | rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x | rhs, lhs.y | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs | rhs.x, lhs | rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z, lhs.w | rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs, lhs.w | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z, lhs | rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x | rhs.x, lhs.y | rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x | rhs, lhs.y | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs | rhs.x, lhs | rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z, lhs.w | rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs, lhs.w | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z, lhs | rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool2 lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs.x | rhs.x, lhs.y | rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool2 lhs, lc_bool rhs) noexcept { return lc_make_bool2(lhs.x | rhs, lhs.y | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs | rhs.x, lhs | rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool3 lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool3 lhs, lc_bool rhs) noexcept { return lc_make_bool3(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool4 lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z, lhs.w | rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool4 lhs, lc_bool rhs) noexcept { return lc_make_bool4(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs, lhs.w | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z, lhs | rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x | rhs.x, lhs.y | rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x | rhs, lhs.y | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs | rhs.x, lhs | rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z, lhs.w | rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs, lhs.w | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z, lhs | rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x | rhs.x, lhs.y | rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x | rhs, lhs.y | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs | rhs.x, lhs | rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z, lhs.w | rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs, lhs.w | rhs); } -[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z, lhs | rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator&(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x & rhs.x, lhs.y & rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x & rhs, lhs.y & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs & rhs.x, lhs & rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z, lhs.w & rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs, lhs.w & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z, lhs & rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x & rhs.x, lhs.y & rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x & rhs, lhs.y & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs & rhs.x, lhs & rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z, lhs.w & rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs, lhs.w & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z, lhs & rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x & rhs.x, lhs.y & rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x & rhs, lhs.y & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs & rhs.x, lhs & rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z, lhs.w & rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs, lhs.w & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z, lhs & rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x & rhs.x, lhs.y & rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x & rhs, lhs.y & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs & rhs.x, lhs & rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z, lhs.w & rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs, lhs.w & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z, lhs & rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool2 lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs.x & rhs.x, lhs.y & rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool2 lhs, lc_bool rhs) noexcept { return lc_make_bool2(lhs.x & rhs, lhs.y & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs & rhs.x, lhs & rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool3 lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool3 lhs, lc_bool rhs) noexcept { return lc_make_bool3(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool4 lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z, lhs.w & rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool4 lhs, lc_bool rhs) noexcept { return lc_make_bool4(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs, lhs.w & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z, lhs & rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x & rhs.x, lhs.y & rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x & rhs, lhs.y & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs & rhs.x, lhs & rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z, lhs.w & rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs, lhs.w & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z, lhs & rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x & rhs.x, lhs.y & rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x & rhs, lhs.y & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs & rhs.x, lhs & rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z, lhs.w & rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs, lhs.w & rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z, lhs & rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator^(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x ^ rhs.x, lhs.y ^ rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x ^ rhs, lhs.y ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs ^ rhs.x, lhs ^ rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z, lhs.w ^ rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs, lhs.w ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z, lhs ^ rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x ^ rhs.x, lhs.y ^ rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x ^ rhs, lhs.y ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs ^ rhs.x, lhs ^ rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z, lhs.w ^ rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs, lhs.w ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z, lhs ^ rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x ^ rhs.x, lhs.y ^ rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x ^ rhs, lhs.y ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs ^ rhs.x, lhs ^ rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z, lhs.w ^ rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs, lhs.w ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z, lhs ^ rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x ^ rhs.x, lhs.y ^ rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x ^ rhs, lhs.y ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs ^ rhs.x, lhs ^ rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z, lhs.w ^ rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs, lhs.w ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z, lhs ^ rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool2 lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs.x ^ rhs.x, lhs.y ^ rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool2 lhs, lc_bool rhs) noexcept { return lc_make_bool2(lhs.x ^ rhs, lhs.y ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs ^ rhs.x, lhs ^ rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool3 lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool3 lhs, lc_bool rhs) noexcept { return lc_make_bool3(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool4 lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z, lhs.w ^ rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool4 lhs, lc_bool rhs) noexcept { return lc_make_bool4(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs, lhs.w ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z, lhs ^ rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x ^ rhs.x, lhs.y ^ rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x ^ rhs, lhs.y ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs ^ rhs.x, lhs ^ rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z, lhs.w ^ rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs, lhs.w ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z, lhs ^ rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x ^ rhs.x, lhs.y ^ rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x ^ rhs, lhs.y ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs ^ rhs.x, lhs ^ rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z, lhs.w ^ rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs, lhs.w ^ rhs); } -[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z, lhs ^ rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool2 lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs.x || rhs.x, lhs.y || rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool2 lhs, lc_bool rhs) noexcept { return lc_make_bool2(lhs.x || rhs, lhs.y || rhs); } -[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs || rhs.x, lhs || rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool3 lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs.x || rhs.x, lhs.y || rhs.y, lhs.z || rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool3 lhs, lc_bool rhs) noexcept { return lc_make_bool3(lhs.x || rhs, lhs.y || rhs, lhs.z || rhs); } -[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs || rhs.x, lhs || rhs.y, lhs || rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool4 lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs.x || rhs.x, lhs.y || rhs.y, lhs.z || rhs.z, lhs.w || rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool4 lhs, lc_bool rhs) noexcept { return lc_make_bool4(lhs.x || rhs, lhs.y || rhs, lhs.z || rhs, lhs.w || rhs); } -[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs || rhs.x, lhs || rhs.y, lhs || rhs.z, lhs || rhs.w); } - -[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool2 lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs.x && rhs.x, lhs.y && rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool2 lhs, lc_bool rhs) noexcept { return lc_make_bool2(lhs.x && rhs, lhs.y && rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs && rhs.x, lhs && rhs.y); } -[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool3 lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs.x && rhs.x, lhs.y && rhs.y, lhs.z && rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool3 lhs, lc_bool rhs) noexcept { return lc_make_bool3(lhs.x && rhs, lhs.y && rhs, lhs.z && rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs && rhs.x, lhs && rhs.y, lhs && rhs.z); } -[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool4 lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs.x && rhs.x, lhs.y && rhs.y, lhs.z && rhs.z, lhs.w && rhs.w); } -[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool4 lhs, lc_bool rhs) noexcept { return lc_make_bool4(lhs.x && rhs, lhs.y && rhs, lhs.z && rhs, lhs.w && rhs); } -[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs && rhs.x, lhs && rhs.y, lhs && rhs.z, lhs && rhs.w); } - -[[nodiscard]] __device__ inline constexpr auto lc_any(lc_bool2 v) noexcept { return v.x || v.y; } -[[nodiscard]] __device__ inline constexpr auto lc_any(lc_bool3 v) noexcept { return v.x || v.y || v.z; } -[[nodiscard]] __device__ inline constexpr auto lc_any(lc_bool4 v) noexcept { return v.x || v.y || v.z || v.w; } -[[nodiscard]] __device__ inline constexpr auto lc_all(lc_bool2 v) noexcept { return v.x && v.y; } -[[nodiscard]] __device__ inline constexpr auto lc_all(lc_bool3 v) noexcept { return v.x && v.y && v.z; } -[[nodiscard]] __device__ inline constexpr auto lc_all(lc_bool4 v) noexcept { return v.x && v.y && v.z && v.w; } -[[nodiscard]] __device__ inline constexpr auto lc_none(lc_bool2 v) noexcept { return !v.x && !v.y; } -[[nodiscard]] __device__ inline constexpr auto lc_none(lc_bool3 v) noexcept { return !v.x && !v.y && !v.z; } -[[nodiscard]] __device__ inline constexpr auto lc_none(lc_bool4 v) noexcept { return !v.x && !v.y && !v.z && !v.w; } - -struct lc_float2x2 { - lc_float2 cols[2]; - __device__ inline constexpr lc_float2x2() noexcept : cols{} {} - __device__ inline explicit constexpr lc_float2x2(lc_float s) noexcept - : cols{lc_make_float2(s, 0.0f), lc_make_float2(0.0f, s)} {} - __device__ inline constexpr static auto full(lc_float s) noexcept { return lc_float2x2{lc_float2(s), lc_float2(s)}; } - __device__ inline constexpr static auto zero() noexcept { return lc_float2x2{lc_float2::zero(), lc_float2::zero()}; } - __device__ inline constexpr static auto one() noexcept { return lc_float2x2{lc_float2::one(), lc_float2::one()}; } - __device__ inline constexpr lc_float2x2(lc_float2 c0, lc_float2 c1) noexcept - : cols{c0, c1} {} - [[nodiscard]] __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return cols[i]; } - [[nodiscard]] __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return cols[i]; } - [[nodiscard]] __device__ inline constexpr auto comp_mul(const lc_float2x2 &rhs) const noexcept { return lc_float2x2{cols[0] * rhs[0], cols[1] * rhs[1]}; } -}; - -struct lc_float3x3 { - lc_float3 cols[3]; - __device__ inline constexpr lc_float3x3() noexcept : cols{} {} - __device__ inline explicit constexpr lc_float3x3(lc_float s) noexcept - : cols{lc_make_float3(s, 0.0f, 0.0f), lc_make_float3(0.0f, s, 0.0f), lc_make_float3(0.0f, 0.0f, s)} {} - __device__ inline constexpr static auto full(lc_float s) noexcept { return lc_float3x3{lc_float3(s), lc_float3(s), lc_float3(s)}; } - __device__ inline constexpr static auto zero() noexcept { return lc_float3x3{lc_float3::zero(), lc_float3::zero(), lc_float3::zero()}; } - __device__ inline constexpr static auto one() noexcept { return lc_float3x3{lc_float3::one(), lc_float3::one(), lc_float3::one()}; } - __device__ inline constexpr lc_float3x3(lc_float3 c0, lc_float3 c1, lc_float3 c2) noexcept - : cols{c0, c1, c2} {} - [[nodiscard]] __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return cols[i]; } - [[nodiscard]] __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return cols[i]; } - [[nodiscard]] __device__ inline constexpr auto comp_mul(const lc_float3x3 &rhs) const noexcept { return lc_float3x3{cols[0] * rhs[0], cols[1] * rhs[1], cols[2] * rhs[2]}; } -}; - -struct lc_float4x4 { - lc_float4 cols[4]; - __device__ inline constexpr lc_float4x4() noexcept : cols{} {} - __device__ inline explicit constexpr lc_float4x4(lc_float s) noexcept - : cols{lc_make_float4(s, 0.0f, 0.0f, 0.0f), lc_make_float4(0.0f, s, 0.0f, 0.0f), lc_make_float4(0.0f, 0.0f, s, 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, s)} {} - __device__ inline constexpr static auto full(lc_float s) noexcept { return lc_float4x4{lc_float4(s), lc_float4(s), lc_float4(s), lc_float4(s)}; } - __device__ inline constexpr static auto zero() noexcept { return lc_float4x4{lc_float4::zero(), lc_float4::zero(), lc_float4::zero(), lc_float4::zero()}; } - __device__ inline constexpr static auto one() noexcept { return lc_float4x4{lc_float4::one(), lc_float4::one(), lc_float4::one(), lc_float4::one()}; } - __device__ inline constexpr lc_float4x4(lc_float4 c0, lc_float4 c1, lc_float4 c2, lc_float4 c3) noexcept - : cols{c0, c1, c2, c3} {} - [[nodiscard]] __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return cols[i]; } - [[nodiscard]] __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return cols[i]; } - [[nodiscard]] __device__ inline constexpr auto comp_mul(const lc_float4x4 &rhs) const noexcept { return lc_float4x4{cols[0] * rhs[0], cols[1] * rhs[1], cols[2] * rhs[2], cols[3] * rhs[3]}; } -}; - -[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float2x2 m, lc_float s) noexcept { return lc_float2x2{m[0] * s, m[1] * s}; } -[[nodiscard]] __device__ inline constexpr auto operator*(lc_float s, const lc_float2x2 m) noexcept { return m * s; } -[[nodiscard]] __device__ inline constexpr auto operator/(const lc_float2x2 m, lc_float s) noexcept { return m * (1.0f / s); } -[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float2x2 m, const lc_float2 v) noexcept { return v.x * m[0] + v.y * m[1]; } -[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float2x2 lhs, const lc_float2x2 rhs) noexcept { return lc_float2x2{lhs * rhs[0], lhs * rhs[1]}; } -[[nodiscard]] __device__ inline constexpr auto operator+(const lc_float2x2 lhs, const lc_float2x2 rhs) noexcept { return lc_float2x2{lhs[0] + rhs[0], lhs[1] + rhs[1]}; } -[[nodiscard]] __device__ inline constexpr auto operator-(const lc_float2x2 lhs, const lc_float2x2 rhs) noexcept { return lc_float2x2{lhs[0] - rhs[0], lhs[1] - rhs[1]}; } - -[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float3x3 m, lc_float s) noexcept { return lc_float3x3{m[0] * s, m[1] * s, m[2] * s}; } -[[nodiscard]] __device__ inline constexpr auto operator*(lc_float s, const lc_float3x3 m) noexcept { return m * s; } -[[nodiscard]] __device__ inline constexpr auto operator/(const lc_float3x3 m, lc_float s) noexcept { return m * (1.0f / s); } -[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float3x3 m, const lc_float3 v) noexcept { return v.x * m[0] + v.y * m[1] + v.z * m[2]; } -[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float3x3 lhs, const lc_float3x3 rhs) noexcept { return lc_float3x3{lhs * rhs[0], lhs * rhs[1], lhs * rhs[2]}; } -[[nodiscard]] __device__ inline constexpr auto operator+(const lc_float3x3 lhs, const lc_float3x3 rhs) noexcept { return lc_float3x3{lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2]}; } -[[nodiscard]] __device__ inline constexpr auto operator-(const lc_float3x3 lhs, const lc_float3x3 rhs) noexcept { return lc_float3x3{lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2]}; } - -[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float4x4 m, lc_float s) noexcept { return lc_float4x4{m[0] * s, m[1] * s, m[2] * s, m[3] * s}; } -[[nodiscard]] __device__ inline constexpr auto operator*(lc_float s, const lc_float4x4 m) noexcept { return m * s; } -[[nodiscard]] __device__ inline constexpr auto operator/(const lc_float4x4 m, lc_float s) noexcept { return m * (1.0f / s); } -[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float4x4 m, const lc_float4 v) noexcept { return v.x * m[0] + v.y * m[1] + v.z * m[2] + v.w * m[3]; } -[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float4x4 lhs, const lc_float4x4 rhs) noexcept { return lc_float4x4{lhs * rhs[0], lhs * rhs[1], lhs * rhs[2], lhs * rhs[3]}; } -[[nodiscard]] __device__ inline constexpr auto operator+(const lc_float4x4 lhs, const lc_float4x4 rhs) noexcept { return lc_float4x4{lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2], lhs[3] + rhs[3]}; } -[[nodiscard]] __device__ inline constexpr auto operator-(const lc_float4x4 lhs, const lc_float4x4 rhs) noexcept { return lc_float4x4{lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2], lhs[3] - rhs[3]}; } - -[[nodiscard]] __device__ inline constexpr auto lc_make_float2x2(lc_float s = 1.0f) noexcept { return lc_float2x2{lc_make_float2(s, 0.0f), lc_make_float2(0.0f, s)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2x2(lc_float m00, lc_float m01, lc_float m10, lc_float m11) noexcept { return lc_float2x2{lc_make_float2(m00, m01), lc_make_float2(m10, m11)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2x2(lc_float2 c0, lc_float2 c1) noexcept { return lc_float2x2{c0, c1}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2x2(lc_float2x2 m) noexcept { return m; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2x2(lc_float3x3 m) noexcept { return lc_float2x2{lc_make_float2(m[0]), lc_make_float2(m[1])}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float2x2(lc_float4x4 m) noexcept { return lc_float2x2{lc_make_float2(m[0]), lc_make_float2(m[1])}; } - -[[nodiscard]] __device__ inline constexpr auto lc_make_float3x3(lc_float s = 1.0f) noexcept { return lc_float3x3{lc_make_float3(s, 0.0f, 0.0f), lc_make_float3(0.0f, s, 0.0f), lc_make_float3(0.0f, 0.0f, s)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float3x3(lc_float m00, lc_float m01, lc_float m02, lc_float m10, lc_float m11, lc_float m12, lc_float m20, lc_float m21, lc_float m22) noexcept { return lc_float3x3{lc_make_float3(m00, m01, m02), lc_make_float3(m10, m11, m12), lc_make_float3(m20, m21, m22)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float3x3(lc_float3 c0, lc_float3 c1, lc_float3 c2) noexcept { return lc_float3x3{c0, c1, c2}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float3x3(lc_float2x2 m) noexcept { return lc_float3x3{lc_make_float3(m[0], 0.0f), lc_make_float3(m[1], 0.0f), lc_make_float3(0.0f, 0.0f, 1.0f)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float3x3(lc_float3x3 m) noexcept { return m; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float3x3(lc_float4x4 m) noexcept { return lc_float3x3{lc_make_float3(m[0]), lc_make_float3(m[1]), lc_make_float3(m[2])}; } - -[[nodiscard]] __device__ inline constexpr auto lc_make_float4x4(lc_float s = 1.0f) noexcept { return lc_float4x4{lc_make_float4(s, 0.0f, 0.0f, 0.0f), lc_make_float4(0.0f, s, 0.0f, 0.0f), lc_make_float4(0.0f, 0.0f, s, 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, s)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float4x4(lc_float m00, lc_float m01, lc_float m02, lc_float m03, lc_float m10, lc_float m11, lc_float m12, lc_float m13, lc_float m20, lc_float m21, lc_float m22, lc_float m23, lc_float m30, lc_float m31, lc_float m32, lc_float m33) noexcept { return lc_float4x4{lc_make_float4(m00, m01, m02, m03), lc_make_float4(m10, m11, m12, m13), lc_make_float4(m20, m21, m22, m23), lc_make_float4(m30, m31, m32, m33)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float4x4(lc_float4 c0, lc_float4 c1, lc_float4 c2, lc_float4 c3) noexcept { return lc_float4x4{c0, c1, c2, c3}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float4x4(lc_float2x2 m) noexcept { return lc_float4x4{lc_make_float4(m[0], 0.0f, 0.0f), lc_make_float4(m[1], 0.0f, 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, 1.0f)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float4x4(lc_float3x3 m) noexcept { return lc_float4x4{lc_make_float4(m[0], 0.0f), lc_make_float4(m[1], 0.0f), lc_make_float4(m[2], 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, 1.0f)}; } -[[nodiscard]] __device__ inline constexpr auto lc_make_float4x4(lc_float4x4 m) noexcept { return m; } - -template -[[nodiscard]] __device__ inline auto lc_select(T f, T t, bool p) noexcept { return p ? t : f; } -[[nodiscard]] __device__ inline auto lc_select(lc_short2 f, lc_short2 t, lc_bool2 p) noexcept { return lc_make_short2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } -[[nodiscard]] __device__ inline auto lc_select(lc_short3 f, lc_short3 t, lc_bool3 p) noexcept { return lc_make_short3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } -[[nodiscard]] __device__ inline auto lc_select(lc_short4 f, lc_short4 t, lc_bool4 p) noexcept { return lc_make_short4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } -[[nodiscard]] __device__ inline auto lc_select(lc_ushort2 f, lc_ushort2 t, lc_bool2 p) noexcept { return lc_make_ushort2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } -[[nodiscard]] __device__ inline auto lc_select(lc_ushort3 f, lc_ushort3 t, lc_bool3 p) noexcept { return lc_make_ushort3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } -[[nodiscard]] __device__ inline auto lc_select(lc_ushort4 f, lc_ushort4 t, lc_bool4 p) noexcept { return lc_make_ushort4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } -[[nodiscard]] __device__ inline auto lc_select(lc_int2 f, lc_int2 t, lc_bool2 p) noexcept { return lc_make_int2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } -[[nodiscard]] __device__ inline auto lc_select(lc_int3 f, lc_int3 t, lc_bool3 p) noexcept { return lc_make_int3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } -[[nodiscard]] __device__ inline auto lc_select(lc_int4 f, lc_int4 t, lc_bool4 p) noexcept { return lc_make_int4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } -[[nodiscard]] __device__ inline auto lc_select(lc_uint2 f, lc_uint2 t, lc_bool2 p) noexcept { return lc_make_uint2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } -[[nodiscard]] __device__ inline auto lc_select(lc_uint3 f, lc_uint3 t, lc_bool3 p) noexcept { return lc_make_uint3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } -[[nodiscard]] __device__ inline auto lc_select(lc_uint4 f, lc_uint4 t, lc_bool4 p) noexcept { return lc_make_uint4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } -[[nodiscard]] __device__ inline auto lc_select(lc_half2 f, lc_half2 t, lc_bool2 p) noexcept { return lc_make_half2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } -[[nodiscard]] __device__ inline auto lc_select(lc_half3 f, lc_half3 t, lc_bool3 p) noexcept { return lc_make_half3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } -[[nodiscard]] __device__ inline auto lc_select(lc_half4 f, lc_half4 t, lc_bool4 p) noexcept { return lc_make_half4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } -[[nodiscard]] __device__ inline auto lc_select(lc_float2 f, lc_float2 t, lc_bool2 p) noexcept { return lc_make_float2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } -[[nodiscard]] __device__ inline auto lc_select(lc_float3 f, lc_float3 t, lc_bool3 p) noexcept { return lc_make_float3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } -[[nodiscard]] __device__ inline auto lc_select(lc_float4 f, lc_float4 t, lc_bool4 p) noexcept { return lc_make_float4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } -[[nodiscard]] __device__ inline auto lc_select(lc_bool2 f, lc_bool2 t, lc_bool2 p) noexcept { return lc_make_bool2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } -[[nodiscard]] __device__ inline auto lc_select(lc_bool3 f, lc_bool3 t, lc_bool3 p) noexcept { return lc_make_bool3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } -[[nodiscard]] __device__ inline auto lc_select(lc_bool4 f, lc_bool4 t, lc_bool4 p) noexcept { return lc_make_bool4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } -[[nodiscard]] __device__ inline auto lc_select(lc_long2 f, lc_long2 t, lc_bool2 p) noexcept { return lc_make_long2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } -[[nodiscard]] __device__ inline auto lc_select(lc_long3 f, lc_long3 t, lc_bool3 p) noexcept { return lc_make_long3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } -[[nodiscard]] __device__ inline auto lc_select(lc_long4 f, lc_long4 t, lc_bool4 p) noexcept { return lc_make_long4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } -[[nodiscard]] __device__ inline auto lc_select(lc_ulong2 f, lc_ulong2 t, lc_bool2 p) noexcept { return lc_make_ulong2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } -[[nodiscard]] __device__ inline auto lc_select(lc_ulong3 f, lc_ulong3 t, lc_bool3 p) noexcept { return lc_make_ulong3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } -[[nodiscard]] __device__ inline auto lc_select(lc_ulong4 f, lc_ulong4 t, lc_bool4 p) noexcept { return lc_make_ulong4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } - -[[nodiscard]] __device__ inline auto lc_outer_product(lc_float2 a, lc_float2 b) noexcept { return lc_float2x2(a * b.x, a * b.y); } -[[nodiscard]] __device__ inline auto lc_outer_product(lc_float3 a, lc_float3 b) noexcept { return lc_float3x3(a * b.x, a * b.y, a * b.z); } -[[nodiscard]] __device__ inline auto lc_outer_product(lc_float4 a, lc_float4 b) noexcept { return lc_float4x4(a * b.x, a * b.y, a * b.z, a * b.w); } -[[nodiscard]] __device__ inline lc_float lc_min(lc_float a, lc_float b) noexcept { return fminf(a, b); } -[[nodiscard]] __device__ inline lc_float2 lc_min(lc_float2 a, lc_float2 b) noexcept { return lc_make_float2(fminf(a.x, b.x), fminf(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_min(lc_float3 a, lc_float3 b) noexcept { return lc_make_float3(fminf(a.x, b.x), fminf(a.y, b.y), fminf(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_min(lc_float4 a, lc_float4 b) noexcept { return lc_make_float4(fminf(a.x, b.x), fminf(a.y, b.y), fminf(a.z, b.z), fminf(a.w, b.w)); } - -[[nodiscard]] __device__ inline lc_half lc_min(lc_half a, lc_half b) noexcept { return __hmin(a, b); } -[[nodiscard]] __device__ inline lc_half2 lc_min(lc_half2 a, lc_half2 b) noexcept { return lc_make_half2(__hmin(a.x, b.x), __hmin(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_min(lc_half3 a, lc_half3 b) noexcept { return lc_make_half3(__hmin(a.x, b.x), __hmin(a.y, b.y), __hmin(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_min(lc_half4 a, lc_half4 b) noexcept { return lc_make_half4(__hmin(a.x, b.x), __hmin(a.y, b.y), __hmin(a.z, b.z), __hmin(a.w, b.w)); } - -[[nodiscard]] __device__ inline lc_float lc_max(lc_float a, lc_float b) noexcept { return fmaxf(a, b); } -[[nodiscard]] __device__ inline lc_float2 lc_max(lc_float2 a, lc_float2 b) noexcept { return lc_make_float2(fmaxf(a.x, b.x), fmaxf(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_max(lc_float3 a, lc_float3 b) noexcept { return lc_make_float3(fmaxf(a.x, b.x), fmaxf(a.y, b.y), fmaxf(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_max(lc_float4 a, lc_float4 b) noexcept { return lc_make_float4(fmaxf(a.x, b.x), fmaxf(a.y, b.y), fmaxf(a.z, b.z), fmaxf(a.w, b.w)); } - -[[nodiscard]] __device__ inline lc_half lc_max(lc_half a, lc_half b) noexcept { return __hmax(a, b); } -[[nodiscard]] __device__ inline lc_half2 lc_max(lc_half2 a, lc_half2 b) noexcept { return lc_make_half2(__hmax(a.x, b.x), __hmax(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_max(lc_half3 a, lc_half3 b) noexcept { return lc_make_half3(__hmax(a.x, b.x), __hmax(a.y, b.y), __hmax(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_max(lc_half4 a, lc_half4 b) noexcept { return lc_make_half4(__hmax(a.x, b.x), __hmax(a.y, b.y), __hmax(a.z, b.z), __hmax(a.w, b.w)); } - -[[nodiscard]] __device__ inline lc_float lc_abs(lc_float x) noexcept { return fabsf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_abs(lc_float2 x) noexcept { return lc_make_float2(fabsf(x.x), fabsf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_abs(lc_float3 x) noexcept { return lc_make_float3(fabsf(x.x), fabsf(x.y), fabsf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_abs(lc_float4 x) noexcept { return lc_make_float4(fabsf(x.x), fabsf(x.y), fabsf(x.z), fabsf(x.w)); } - -[[nodiscard]] __device__ inline lc_int lc_abs(lc_int x) noexcept { return abs(x); } -[[nodiscard]] __device__ inline lc_int2 lc_abs(lc_int2 x) noexcept { return lc_make_int2(abs(x.x), abs(x.y)); } -[[nodiscard]] __device__ inline lc_int3 lc_abs(lc_int3 x) noexcept { return lc_make_int3(abs(x.x), abs(x.y), abs(x.z)); } -[[nodiscard]] __device__ inline lc_int4 lc_abs(lc_int4 x) noexcept { return lc_make_int4(abs(x.x), abs(x.y), abs(x.z), abs(x.w)); } - -[[nodiscard]] __device__ inline lc_long lc_abs(lc_long x) noexcept { return llabs(x); } -[[nodiscard]] __device__ inline lc_long2 lc_abs(lc_long2 x) noexcept { return lc_make_long2(llabs(x.x), llabs(x.y)); } -[[nodiscard]] __device__ inline lc_long3 lc_abs(lc_long3 x) noexcept { return lc_make_long3(llabs(x.x), llabs(x.y), llabs(x.z)); } -[[nodiscard]] __device__ inline lc_long4 lc_abs(lc_long4 x) noexcept { return lc_make_long4(llabs(x.x), llabs(x.y), llabs(x.z), llabs(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_abs(lc_half x) noexcept { return __habs(x); } -[[nodiscard]] __device__ inline lc_half2 lc_abs(lc_half2 x) noexcept { return lc_make_half2(__habs(x.x), __habs(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_abs(lc_half3 x) noexcept { return lc_make_half3(__habs(x.x), __habs(x.y), __habs(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_abs(lc_half4 x) noexcept { return lc_make_half4(__habs(x.x), __habs(x.y), __habs(x.z), __habs(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_acos(lc_half x) noexcept { return acosf(x); } -[[nodiscard]] __device__ inline lc_half2 lc_acos(lc_half2 x) noexcept { return lc_make_half2(acosf(x.x), acosf(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_acos(lc_half3 x) noexcept { return lc_make_half3(acosf(x.x), acosf(x.y), acosf(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_acos(lc_half4 x) noexcept { return lc_make_half4(acosf(x.x), acosf(x.y), acosf(x.z), acosf(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_acos(lc_float x) noexcept { return acosf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_acos(lc_float2 x) noexcept { return lc_make_float2(acosf(x.x), acosf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_acos(lc_float3 x) noexcept { return lc_make_float3(acosf(x.x), acosf(x.y), acosf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_acos(lc_float4 x) noexcept { return lc_make_float4(acosf(x.x), acosf(x.y), acosf(x.z), acosf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_asin(lc_half x) noexcept { return asinf(x); } -[[nodiscard]] __device__ inline lc_half2 lc_asin(lc_half2 x) noexcept { return lc_make_half2(asinf(x.x), asinf(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_asin(lc_half3 x) noexcept { return lc_make_half3(asinf(x.x), asinf(x.y), asinf(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_asin(lc_half4 x) noexcept { return lc_make_half4(asinf(x.x), asinf(x.y), asinf(x.z), asinf(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_asin(lc_float x) noexcept { return asinf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_asin(lc_float2 x) noexcept { return lc_make_float2(asinf(x.x), asinf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_asin(lc_float3 x) noexcept { return lc_make_float3(asinf(x.x), asinf(x.y), asinf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_asin(lc_float4 x) noexcept { return lc_make_float4(asinf(x.x), asinf(x.y), asinf(x.z), asinf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_atan(lc_half x) noexcept { return atanf(x); } -[[nodiscard]] __device__ inline lc_half2 lc_atan(lc_half2 x) noexcept { return lc_make_half2(atanf(x.x), atanf(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_atan(lc_half3 x) noexcept { return lc_make_half3(atanf(x.x), atanf(x.y), atanf(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_atan(lc_half4 x) noexcept { return lc_make_half4(atanf(x.x), atanf(x.y), atanf(x.z), atanf(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_atan(lc_float x) noexcept { return atanf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_atan(lc_float2 x) noexcept { return lc_make_float2(atanf(x.x), atanf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_atan(lc_float3 x) noexcept { return lc_make_float3(atanf(x.x), atanf(x.y), atanf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_atan(lc_float4 x) noexcept { return lc_make_float4(atanf(x.x), atanf(x.y), atanf(x.z), atanf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_acosh(lc_half x) noexcept { return acoshf(x); } -[[nodiscard]] __device__ inline lc_half2 lc_acosh(lc_half2 x) noexcept { return lc_make_half2(acoshf(x.x), acoshf(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_acosh(lc_half3 x) noexcept { return lc_make_half3(acoshf(x.x), acoshf(x.y), acoshf(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_acosh(lc_half4 x) noexcept { return lc_make_half4(acoshf(x.x), acoshf(x.y), acoshf(x.z), acoshf(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_acosh(lc_float x) noexcept { return acoshf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_acosh(lc_float2 x) noexcept { return lc_make_float2(acoshf(x.x), acoshf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_acosh(lc_float3 x) noexcept { return lc_make_float3(acoshf(x.x), acoshf(x.y), acoshf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_acosh(lc_float4 x) noexcept { return lc_make_float4(acoshf(x.x), acoshf(x.y), acoshf(x.z), acoshf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_asinh(lc_half x) noexcept { return asinhf(x); } -[[nodiscard]] __device__ inline lc_half2 lc_asinh(lc_half2 x) noexcept { return lc_make_half2(asinhf(x.x), asinhf(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_asinh(lc_half3 x) noexcept { return lc_make_half3(asinhf(x.x), asinhf(x.y), asinhf(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_asinh(lc_half4 x) noexcept { return lc_make_half4(asinhf(x.x), asinhf(x.y), asinhf(x.z), asinhf(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_asinh(lc_float x) noexcept { return asinhf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_asinh(lc_float2 x) noexcept { return lc_make_float2(asinhf(x.x), asinhf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_asinh(lc_float3 x) noexcept { return lc_make_float3(asinhf(x.x), asinhf(x.y), asinhf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_asinh(lc_float4 x) noexcept { return lc_make_float4(asinhf(x.x), asinhf(x.y), asinhf(x.z), asinhf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_atanh(lc_half x) noexcept { return atanhf(x); } -[[nodiscard]] __device__ inline lc_half2 lc_atanh(lc_half2 x) noexcept { return lc_make_half2(atanhf(x.x), atanhf(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_atanh(lc_half3 x) noexcept { return lc_make_half3(atanhf(x.x), atanhf(x.y), atanhf(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_atanh(lc_half4 x) noexcept { return lc_make_half4(atanhf(x.x), atanhf(x.y), atanhf(x.z), atanhf(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_atanh(lc_float x) noexcept { return atanhf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_atanh(lc_float2 x) noexcept { return lc_make_float2(atanhf(x.x), atanhf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_atanh(lc_float3 x) noexcept { return lc_make_float3(atanhf(x.x), atanhf(x.y), atanhf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_atanh(lc_float4 x) noexcept { return lc_make_float4(atanhf(x.x), atanhf(x.y), atanhf(x.z), atanhf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_atan2(lc_half y, lc_half x) noexcept { return atan2f(y, x); } -[[nodiscard]] __device__ inline lc_half2 lc_atan2(lc_half2 y, lc_half2 x) noexcept { return lc_make_half2(atan2f(y.x, x.x), atan2f(y.y, x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_atan2(lc_half3 y, lc_half3 x) noexcept { return lc_make_half3(atan2f(y.x, x.x), atan2f(y.y, x.y), atan2f(y.z, x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_atan2(lc_half4 y, lc_half4 x) noexcept { return lc_make_half4(atan2f(y.x, x.x), atan2f(y.y, x.y), atan2f(y.z, x.z), atan2f(y.w, x.w)); } -[[nodiscard]] __device__ inline lc_float lc_atan2(lc_float y, lc_float x) noexcept { return atan2f(y, x); } -[[nodiscard]] __device__ inline lc_float2 lc_atan2(lc_float2 y, lc_float2 x) noexcept { return lc_make_float2(atan2f(y.x, x.x), atan2f(y.y, x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_atan2(lc_float3 y, lc_float3 x) noexcept { return lc_make_float3(atan2f(y.x, x.x), atan2f(y.y, x.y), atan2f(y.z, x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_atan2(lc_float4 y, lc_float4 x) noexcept { return lc_make_float4(atan2f(y.x, x.x), atan2f(y.y, x.y), atan2f(y.z, x.z), atan2f(y.w, x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_cosh(lc_half x) noexcept { return coshf(x); } -[[nodiscard]] __device__ inline lc_half2 lc_cosh(lc_half2 x) noexcept { return lc_make_half2(coshf(x.x), coshf(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_cosh(lc_half3 x) noexcept { return lc_make_half3(coshf(x.x), coshf(x.y), coshf(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_cosh(lc_half4 x) noexcept { return lc_make_half4(coshf(x.x), coshf(x.y), coshf(x.z), coshf(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_cosh(lc_float x) noexcept { return coshf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_cosh(lc_float2 x) noexcept { return lc_make_float2(coshf(x.x), coshf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_cosh(lc_float3 x) noexcept { return lc_make_float3(coshf(x.x), coshf(x.y), coshf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_cosh(lc_float4 x) noexcept { return lc_make_float4(coshf(x.x), coshf(x.y), coshf(x.z), coshf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_sinh(lc_half x) noexcept { return sinhf(x); } -[[nodiscard]] __device__ inline lc_half2 lc_sinh(lc_half2 x) noexcept { return lc_make_half2(sinhf(x.x), sinhf(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_sinh(lc_half3 x) noexcept { return lc_make_half3(sinhf(x.x), sinhf(x.y), sinhf(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_sinh(lc_half4 x) noexcept { return lc_make_half4(sinhf(x.x), sinhf(x.y), sinhf(x.z), sinhf(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_sinh(lc_float x) noexcept { return sinhf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_sinh(lc_float2 x) noexcept { return lc_make_float2(sinhf(x.x), sinhf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_sinh(lc_float3 x) noexcept { return lc_make_float3(sinhf(x.x), sinhf(x.y), sinhf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_sinh(lc_float4 x) noexcept { return lc_make_float4(sinhf(x.x), sinhf(x.y), sinhf(x.z), sinhf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_tanh(lc_half x) noexcept { return tanhf(x); } -[[nodiscard]] __device__ inline lc_half2 lc_tanh(lc_half2 x) noexcept { return lc_make_half2(tanhf(x.x), tanhf(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_tanh(lc_half3 x) noexcept { return lc_make_half3(tanhf(x.x), tanhf(x.y), tanhf(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_tanh(lc_half4 x) noexcept { return lc_make_half4(tanhf(x.x), tanhf(x.y), tanhf(x.z), tanhf(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_tanh(lc_float x) noexcept { return tanhf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_tanh(lc_float2 x) noexcept { return lc_make_float2(tanhf(x.x), tanhf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_tanh(lc_float3 x) noexcept { return lc_make_float3(tanhf(x.x), tanhf(x.y), tanhf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_tanh(lc_float4 x) noexcept { return lc_make_float4(tanhf(x.x), tanhf(x.y), tanhf(x.z), tanhf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_cos(lc_half x) noexcept { return cosf(x); } -[[nodiscard]] __device__ inline lc_half2 lc_cos(lc_half2 x) noexcept { return lc_make_half2(cosf(x.x), cosf(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_cos(lc_half3 x) noexcept { return lc_make_half3(cosf(x.x), cosf(x.y), cosf(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_cos(lc_half4 x) noexcept { return lc_make_half4(cosf(x.x), cosf(x.y), cosf(x.z), cosf(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_cos(lc_float x) noexcept { return cosf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_cos(lc_float2 x) noexcept { return lc_make_float2(cosf(x.x), cosf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_cos(lc_float3 x) noexcept { return lc_make_float3(cosf(x.x), cosf(x.y), cosf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_cos(lc_float4 x) noexcept { return lc_make_float4(cosf(x.x), cosf(x.y), cosf(x.z), cosf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_sin(lc_half x) noexcept { return sinf(x); } -[[nodiscard]] __device__ inline lc_half2 lc_sin(lc_half2 x) noexcept { return lc_make_half2(sinf(x.x), sinf(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_sin(lc_half3 x) noexcept { return lc_make_half3(sinf(x.x), sinf(x.y), sinf(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_sin(lc_half4 x) noexcept { return lc_make_half4(sinf(x.x), sinf(x.y), sinf(x.z), sinf(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_sin(lc_float x) noexcept { return sinf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_sin(lc_float2 x) noexcept { return lc_make_float2(sinf(x.x), sinf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_sin(lc_float3 x) noexcept { return lc_make_float3(sinf(x.x), sinf(x.y), sinf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_sin(lc_float4 x) noexcept { return lc_make_float4(sinf(x.x), sinf(x.y), sinf(x.z), sinf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_tan(lc_half x) noexcept { return tanf(x); } -[[nodiscard]] __device__ inline lc_half2 lc_tan(lc_half2 x) noexcept { return lc_make_half2(tanf(x.x), tanf(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_tan(lc_half3 x) noexcept { return lc_make_half3(tanf(x.x), tanf(x.y), tanf(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_tan(lc_half4 x) noexcept { return lc_make_half4(tanf(x.x), tanf(x.y), tanf(x.z), tanf(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_tan(lc_float x) noexcept { return tanf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_tan(lc_float2 x) noexcept { return lc_make_float2(tanf(x.x), tanf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_tan(lc_float3 x) noexcept { return lc_make_float3(tanf(x.x), tanf(x.y), tanf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_tan(lc_float4 x) noexcept { return lc_make_float4(tanf(x.x), tanf(x.y), tanf(x.z), tanf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_exp(lc_half x) noexcept { return expf(x); } -[[nodiscard]] __device__ inline lc_half2 lc_exp(lc_half2 x) noexcept { return lc_make_half2(expf(x.x), expf(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_exp(lc_half3 x) noexcept { return lc_make_half3(expf(x.x), expf(x.y), expf(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_exp(lc_half4 x) noexcept { return lc_make_half4(expf(x.x), expf(x.y), expf(x.z), expf(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_exp(lc_float x) noexcept { return expf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_exp(lc_float2 x) noexcept { return lc_make_float2(expf(x.x), expf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_exp(lc_float3 x) noexcept { return lc_make_float3(expf(x.x), expf(x.y), expf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_exp(lc_float4 x) noexcept { return lc_make_float4(expf(x.x), expf(x.y), expf(x.z), expf(x.w)); } - -[[nodiscard]] __device__ inline lc_float lc_exp2(lc_float x) noexcept { return exp2f(x); } -[[nodiscard]] __device__ inline lc_float2 lc_exp2(lc_float2 x) noexcept { return lc_make_float2(exp2f(x.x), exp2f(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_exp2(lc_float3 x) noexcept { return lc_make_float3(exp2f(x.x), exp2f(x.y), exp2f(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_exp2(lc_float4 x) noexcept { return lc_make_float4(exp2f(x.x), exp2f(x.y), exp2f(x.z), exp2f(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_exp2(lc_half x) noexcept { return hexp2(x); } -[[nodiscard]] __device__ inline lc_half2 lc_exp2(lc_half2 x) noexcept { return lc_make_half2(hexp2(x.x), hexp2(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_exp2(lc_half3 x) noexcept { return lc_make_half3(hexp2(x.x), hexp2(x.y), hexp2(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_exp2(lc_half4 x) noexcept { return lc_make_half4(hexp2(x.x), hexp2(x.y), hexp2(x.z), hexp2(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_exp10(lc_half x) noexcept { return exp10f(x); } -[[nodiscard]] __device__ inline lc_half2 lc_exp10(lc_half2 x) noexcept { return lc_make_half2(exp10f(x.x), exp10f(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_exp10(lc_half3 x) noexcept { return lc_make_half3(exp10f(x.x), exp10f(x.y), exp10f(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_exp10(lc_half4 x) noexcept { return lc_make_half4(exp10f(x.x), exp10f(x.y), exp10f(x.z), exp10f(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_exp10(lc_float x) noexcept { return exp10f(x); } -[[nodiscard]] __device__ inline lc_float2 lc_exp10(lc_float2 x) noexcept { return lc_make_float2(exp10f(x.x), exp10f(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_exp10(lc_float3 x) noexcept { return lc_make_float3(exp10f(x.x), exp10f(x.y), exp10f(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_exp10(lc_float4 x) noexcept { return lc_make_float4(exp10f(x.x), exp10f(x.y), exp10f(x.z), exp10f(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_log(lc_half x) noexcept { return logf(x); } -[[nodiscard]] __device__ inline lc_half2 lc_log(lc_half2 x) noexcept { return lc_make_half2(logf(x.x), logf(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_log(lc_half3 x) noexcept { return lc_make_half3(logf(x.x), logf(x.y), logf(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_log(lc_half4 x) noexcept { return lc_make_half4(logf(x.x), logf(x.y), logf(x.z), logf(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_log(lc_float x) noexcept { return logf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_log(lc_float2 x) noexcept { return lc_make_float2(logf(x.x), logf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_log(lc_float3 x) noexcept { return lc_make_float3(logf(x.x), logf(x.y), logf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_log(lc_float4 x) noexcept { return lc_make_float4(logf(x.x), logf(x.y), logf(x.z), logf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_log2(lc_half x) noexcept { return log2f(x); } -[[nodiscard]] __device__ inline lc_half2 lc_log2(lc_half2 x) noexcept { return lc_make_half2(log2f(x.x), log2f(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_log2(lc_half3 x) noexcept { return lc_make_half3(log2f(x.x), log2f(x.y), log2f(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_log2(lc_half4 x) noexcept { return lc_make_half4(log2f(x.x), log2f(x.y), log2f(x.z), log2f(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_log2(lc_float x) noexcept { return log2f(x); } -[[nodiscard]] __device__ inline lc_float2 lc_log2(lc_float2 x) noexcept { return lc_make_float2(log2f(x.x), log2f(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_log2(lc_float3 x) noexcept { return lc_make_float3(log2f(x.x), log2f(x.y), log2f(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_log2(lc_float4 x) noexcept { return lc_make_float4(log2f(x.x), log2f(x.y), log2f(x.z), log2f(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_log10(lc_half x) noexcept { return log10f(x); } -[[nodiscard]] __device__ inline lc_half2 lc_log10(lc_half2 x) noexcept { return lc_make_half2(log10f(x.x), log10f(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_log10(lc_half3 x) noexcept { return lc_make_half3(log10f(x.x), log10f(x.y), log10f(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_log10(lc_half4 x) noexcept { return lc_make_half4(log10f(x.x), log10f(x.y), log10f(x.z), log10f(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_log10(lc_float x) noexcept { return log10f(x); } -[[nodiscard]] __device__ inline lc_float2 lc_log10(lc_float2 x) noexcept { return lc_make_float2(log10f(x.x), log10f(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_log10(lc_float3 x) noexcept { return lc_make_float3(log10f(x.x), log10f(x.y), log10f(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_log10(lc_float4 x) noexcept { return lc_make_float4(log10f(x.x), log10f(x.y), log10f(x.z), log10f(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_pow(lc_half x, lc_half a) noexcept { return powf_impl(x, a); } -[[nodiscard]] __device__ inline lc_half2 lc_pow(lc_half2 x, lc_half2 a) noexcept { return lc_make_half2(powf_impl(x.x, a.x), powf_impl(x.y, a.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_pow(lc_half3 x, lc_half3 a) noexcept { return lc_make_half3(powf_impl(x.x, a.x), powf_impl(x.y, a.y), powf_impl(x.z, a.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_pow(lc_half4 x, lc_half4 a) noexcept { return lc_make_half4(powf_impl(x.x, a.x), powf_impl(x.y, a.y), powf_impl(x.z, a.z), powf_impl(x.w, a.w)); } -[[nodiscard]] __device__ inline lc_float lc_pow(lc_float x, lc_float a) noexcept { return powf_impl(x, a); } -[[nodiscard]] __device__ inline lc_float2 lc_pow(lc_float2 x, lc_float2 a) noexcept { return lc_make_float2(powf_impl(x.x, a.x), powf_impl(x.y, a.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_pow(lc_float3 x, lc_float3 a) noexcept { return lc_make_float3(powf_impl(x.x, a.x), powf_impl(x.y, a.y), powf_impl(x.z, a.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_pow(lc_float4 x, lc_float4 a) noexcept { return lc_make_float4(powf_impl(x.x, a.x), powf_impl(x.y, a.y), powf_impl(x.z, a.z), powf_impl(x.w, a.w)); } - -[[nodiscard]] __device__ inline lc_half lc_powi(lc_half x, lc_half a) noexcept { return powi_impl(x, a); } -[[nodiscard]] __device__ inline lc_half2 lc_powi(lc_half2 x, lc_half2 a) noexcept { return lc_make_half2(powi_impl(x.x, a.x), powi_impl(x.y, a.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_powi(lc_half3 x, lc_half3 a) noexcept { return lc_make_half3(powi_impl(x.x, a.x), powi_impl(x.y, a.y), powi_impl(x.z, a.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_powi(lc_half4 x, lc_half4 a) noexcept { return lc_make_half4(powi_impl(x.x, a.x), powi_impl(x.y, a.y), powi_impl(x.z, a.z), powi_impl(x.w, a.w)); } -[[nodiscard]] __device__ inline lc_float lc_powi(lc_float x, lc_float a) noexcept { return powi_impl(x, a); } -[[nodiscard]] __device__ inline lc_float2 lc_powi(lc_float2 x, lc_float2 a) noexcept { return lc_make_float2(powi_impl(x.x, a.x), powi_impl(x.y, a.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_powi(lc_float3 x, lc_float3 a) noexcept { return lc_make_float3(powi_impl(x.x, a.x), powi_impl(x.y, a.y), powi_impl(x.z, a.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_powi(lc_float4 x, lc_float4 a) noexcept { return lc_make_float4(powi_impl(x.x, a.x), powi_impl(x.y, a.y), powi_impl(x.z, a.z), powi_impl(x.w, a.w)); } - -[[nodiscard]] __device__ inline lc_float lc_sqrt(lc_float x) noexcept { return sqrtf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_sqrt(lc_float2 x) noexcept { return lc_make_float2(sqrtf(x.x), sqrtf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_sqrt(lc_float3 x) noexcept { return lc_make_float3(sqrtf(x.x), sqrtf(x.y), sqrtf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_sqrt(lc_float4 x) noexcept { return lc_make_float4(sqrtf(x.x), sqrtf(x.y), sqrtf(x.z), sqrtf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_sqrt(lc_half x) noexcept { return hsqrt(x); } -[[nodiscard]] __device__ inline lc_half2 lc_sqrt(lc_half2 x) noexcept { return lc_make_half2(hsqrt(x.x), hsqrt(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_sqrt(lc_half3 x) noexcept { return lc_make_half3(hsqrt(x.x), hsqrt(x.y), hsqrt(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_sqrt(lc_half4 x) noexcept { return lc_make_half4(hsqrt(x.x), hsqrt(x.y), hsqrt(x.z), hsqrt(x.w)); } - -[[nodiscard]] __device__ inline lc_float lc_rsqrt(lc_float x) noexcept { return rsqrtf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_rsqrt(lc_float2 x) noexcept { return lc_make_float2(rsqrtf(x.x), rsqrtf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_rsqrt(lc_float3 x) noexcept { return lc_make_float3(rsqrtf(x.x), rsqrtf(x.y), rsqrtf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_rsqrt(lc_float4 x) noexcept { return lc_make_float4(rsqrtf(x.x), rsqrtf(x.y), rsqrtf(x.z), rsqrtf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_rsqrt(lc_half x) noexcept { return hrsqrt(x); } -[[nodiscard]] __device__ inline lc_half2 lc_rsqrt(lc_half2 x) noexcept { return lc_make_half2(hrsqrt(x.x), hrsqrt(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_rsqrt(lc_half3 x) noexcept { return lc_make_half3(hrsqrt(x.x), hrsqrt(x.y), hrsqrt(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_rsqrt(lc_half4 x) noexcept { return lc_make_half4(hrsqrt(x.x), hrsqrt(x.y), hrsqrt(x.z), hrsqrt(x.w)); } - -[[nodiscard]] __device__ inline lc_float lc_ceil(lc_float x) noexcept { return ceilf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_ceil(lc_float2 x) noexcept { return lc_make_float2(ceilf(x.x), ceilf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_ceil(lc_float3 x) noexcept { return lc_make_float3(ceilf(x.x), ceilf(x.y), ceilf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_ceil(lc_float4 x) noexcept { return lc_make_float4(ceilf(x.x), ceilf(x.y), ceilf(x.z), ceilf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_ceil(lc_half x) noexcept { return hceil(x); } -[[nodiscard]] __device__ inline lc_half2 lc_ceil(lc_half2 x) noexcept { return lc_make_half2(hceil(x.x), hceil(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_ceil(lc_half3 x) noexcept { return lc_make_half3(hceil(x.x), hceil(x.y), hceil(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_ceil(lc_half4 x) noexcept { return lc_make_half4(hceil(x.x), hceil(x.y), hceil(x.z), hceil(x.w)); } - -[[nodiscard]] __device__ inline lc_float lc_floor(lc_float x) noexcept { return floorf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_floor(lc_float2 x) noexcept { return lc_make_float2(floorf(x.x), floorf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_floor(lc_float3 x) noexcept { return lc_make_float3(floorf(x.x), floorf(x.y), floorf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_floor(lc_float4 x) noexcept { return lc_make_float4(floorf(x.x), floorf(x.y), floorf(x.z), floorf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_floor(lc_half x) noexcept { return hfloor(x); } -[[nodiscard]] __device__ inline lc_half2 lc_floor(lc_half2 x) noexcept { return lc_make_half2(hfloor(x.x), hfloor(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_floor(lc_half3 x) noexcept { return lc_make_half3(hfloor(x.x), hfloor(x.y), hfloor(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_floor(lc_half4 x) noexcept { return lc_make_half4(hfloor(x.x), hfloor(x.y), hfloor(x.z), hfloor(x.w)); } - -[[nodiscard]] __device__ inline lc_float lc_trunc(lc_float x) noexcept { return truncf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_trunc(lc_float2 x) noexcept { return lc_make_float2(truncf(x.x), truncf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_trunc(lc_float3 x) noexcept { return lc_make_float3(truncf(x.x), truncf(x.y), truncf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_trunc(lc_float4 x) noexcept { return lc_make_float4(truncf(x.x), truncf(x.y), truncf(x.z), truncf(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_trunc(lc_half x) noexcept { return htrunc(x); } -[[nodiscard]] __device__ inline lc_half2 lc_trunc(lc_half2 x) noexcept { return lc_make_half2(htrunc(x.x), htrunc(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_trunc(lc_half3 x) noexcept { return lc_make_half3(htrunc(x.x), htrunc(x.y), htrunc(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_trunc(lc_half4 x) noexcept { return lc_make_half4(htrunc(x.x), htrunc(x.y), htrunc(x.z), htrunc(x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_round(lc_half x) noexcept { return roundf(x); } -[[nodiscard]] __device__ inline lc_half2 lc_round(lc_half2 x) noexcept { return lc_make_half2(roundf(x.x), roundf(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_round(lc_half3 x) noexcept { return lc_make_half3(roundf(x.x), roundf(x.y), roundf(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_round(lc_half4 x) noexcept { return lc_make_half4(roundf(x.x), roundf(x.y), roundf(x.z), roundf(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_round(lc_float x) noexcept { return roundf(x); } -[[nodiscard]] __device__ inline lc_float2 lc_round(lc_float2 x) noexcept { return lc_make_float2(roundf(x.x), roundf(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_round(lc_float3 x) noexcept { return lc_make_float3(roundf(x.x), roundf(x.y), roundf(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_round(lc_float4 x) noexcept { return lc_make_float4(roundf(x.x), roundf(x.y), roundf(x.z), roundf(x.w)); } - -[[nodiscard]] __device__ inline lc_float lc_fma(lc_float x, lc_float y, lc_float z) noexcept { return fmaf(x, y, z); } -[[nodiscard]] __device__ inline lc_float2 lc_fma(lc_float2 x, lc_float2 y, lc_float2 z) noexcept { return lc_make_float2(fmaf(x.x, y.x, z.x), fmaf(x.y, y.y, z.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_fma(lc_float3 x, lc_float3 y, lc_float3 z) noexcept { return lc_make_float3(fmaf(x.x, y.x, z.x), fmaf(x.y, y.y, z.y), fmaf(x.z, y.z, z.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_fma(lc_float4 x, lc_float4 y, lc_float4 z) noexcept { return lc_make_float4(fmaf(x.x, y.x, z.x), fmaf(x.y, y.y, z.y), fmaf(x.z, y.z, z.z), fmaf(x.w, y.w, z.w)); } - -[[nodiscard]] __device__ inline lc_half lc_fma(lc_half x, lc_half y, lc_half z) noexcept { return __hfma(x, y, z); } -[[nodiscard]] __device__ inline lc_half2 lc_fma(lc_half2 x, lc_half2 y, lc_half2 z) noexcept { return lc_make_half2(__hfma(x.x, y.x, z.x), __hfma(x.y, y.y, z.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_fma(lc_half3 x, lc_half3 y, lc_half3 z) noexcept { return lc_make_half3(__hfma(x.x, y.x, z.x), __hfma(x.y, y.y, z.y), __hfma(x.z, y.z, z.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_fma(lc_half4 x, lc_half4 y, lc_half4 z) noexcept { return lc_make_half4(__hfma(x.x, y.x, z.x), __hfma(x.y, y.y, z.y), __hfma(x.z, y.z, z.z), __hfma(x.w, y.w, z.w)); } - - -[[nodiscard]] __device__ inline auto lc_copysign_impl(lc_half x, lc_half y) noexcept { - auto ux = __half_as_short(x); - auto uy = __half_as_short(y); - return __short_as_half((ux & 0x7fffu) | (uy & 0x8000u)); -} -[[nodiscard]] __device__ inline lc_float lc_copysign(lc_float x, lc_float y) noexcept { return copysignf(x, y); } -[[nodiscard]] __device__ inline lc_float2 lc_copysign(lc_float2 x, lc_float2 y) noexcept { return lc_make_float2(copysignf(x.x, y.x), copysignf(x.y, y.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_copysign(lc_float3 x, lc_float3 y) noexcept { return lc_make_float3(copysignf(x.x, y.x), copysignf(x.y, y.y), copysignf(x.z, y.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_copysign(lc_float4 x, lc_float4 y) noexcept { return lc_make_float4(copysignf(x.x, y.x), copysignf(x.y, y.y), copysignf(x.z, y.z), copysignf(x.w, y.w)); } - -[[nodiscard]] __device__ inline lc_half lc_copysign(lc_half x, lc_half y) noexcept { return lc_copysign_impl(x, y); } -[[nodiscard]] __device__ inline lc_half2 lc_copysign(lc_half2 x, lc_half2 y) noexcept { return lc_make_half2(lc_copysign_impl(x.x, y.x), lc_copysign_impl(x.y, y.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_copysign(lc_half3 x, lc_half3 y) noexcept { return lc_make_half3(lc_copysign_impl(x.x, y.x), lc_copysign_impl(x.y, y.y), lc_copysign_impl(x.z, y.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_copysign(lc_half4 x, lc_half4 y) noexcept { return lc_make_half4(lc_copysign_impl(x.x, y.x), lc_copysign_impl(x.y, y.y), lc_copysign_impl(x.z, y.z), lc_copysign_impl(x.w, y.w)); } - -[[nodiscard]] __device__ inline lc_bool lc_isinf(lc_float x) noexcept { return isinf_impl(x); } -[[nodiscard]] __device__ inline lc_bool2 lc_isinf(lc_float2 x) noexcept { return lc_make_bool2(isinf_impl(x.x), isinf_impl(x.y)); } -[[nodiscard]] __device__ inline lc_bool3 lc_isinf(lc_float3 x) noexcept { return lc_make_bool3(isinf_impl(x.x), isinf_impl(x.y), isinf_impl(x.z)); } -[[nodiscard]] __device__ inline lc_bool4 lc_isinf(lc_float4 x) noexcept { return lc_make_bool4(isinf_impl(x.x), isinf_impl(x.y), isinf_impl(x.z), isinf_impl(x.w)); } - -[[nodiscard]] __device__ inline lc_bool lc_isnan(lc_float x) noexcept { return isnan_impl(x); } -[[nodiscard]] __device__ inline lc_bool2 lc_isnan(lc_float2 x) noexcept { return lc_make_bool2(isnan_impl(x.x), isnan_impl(x.y)); } -[[nodiscard]] __device__ inline lc_bool3 lc_isnan(lc_float3 x) noexcept { return lc_make_bool3(isnan_impl(x.x), isnan_impl(x.y), isnan_impl(x.z)); } -[[nodiscard]] __device__ inline lc_bool4 lc_isnan(lc_float4 x) noexcept { return lc_make_bool4(isnan_impl(x.x), isnan_impl(x.y), isnan_impl(x.z), isnan_impl(x.w)); } - -[[nodiscard]] __device__ inline lc_bool lc_isinf(lc_half x) noexcept { return __hisinf(x); } -[[nodiscard]] __device__ inline lc_bool2 lc_isinf(lc_half2 x) noexcept { return lc_make_bool2(__hisinf(x.x), __hisinf(x.y)); } -[[nodiscard]] __device__ inline lc_bool3 lc_isinf(lc_half3 x) noexcept { return lc_make_bool3(__hisinf(x.x), __hisinf(x.y), __hisinf(x.z)); } -[[nodiscard]] __device__ inline lc_bool4 lc_isinf(lc_half4 x) noexcept { return lc_make_bool4(__hisinf(x.x), __hisinf(x.y), __hisinf(x.z), __hisinf(x.w)); } - -[[nodiscard]] __device__ inline lc_bool lc_isnan(lc_half x) noexcept { return __hisnan(x); } -[[nodiscard]] __device__ inline lc_bool2 lc_isnan(lc_half2 x) noexcept { return lc_make_bool2(__hisnan(x.x), __hisnan(x.y)); } -[[nodiscard]] __device__ inline lc_bool3 lc_isnan(lc_half3 x) noexcept { return lc_make_bool3(__hisnan(x.x), __hisnan(x.y), __hisnan(x.z)); } -[[nodiscard]] __device__ inline lc_bool4 lc_isnan(lc_half4 x) noexcept { return lc_make_bool4(__hisnan(x.x), __hisnan(x.y), __hisnan(x.z), __hisnan(x.w)); } - -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_short2 v) noexcept { return lc_short(v.x+v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_short2 v) noexcept { return lc_short(v.x*v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_short2 v) noexcept { return lc_short(lc_min(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_short2 v) noexcept { return lc_short(lc_max(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_short3 v) noexcept { return lc_short(v.x+v.y+v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_short3 v) noexcept { return lc_short(v.x*v.y*v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_short3 v) noexcept { return lc_short(lc_min(v.x, lc_min(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_short3 v) noexcept { return lc_short(lc_max(v.x, lc_max(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_short4 v) noexcept { return lc_short(v.x+v.y+v.z+v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_short4 v) noexcept { return lc_short(v.x*v.y*v.z*v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_short4 v) noexcept { return lc_short(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_short4 v) noexcept { return lc_short(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_ushort2 v) noexcept { return lc_ushort(v.x+v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_ushort2 v) noexcept { return lc_ushort(v.x*v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_ushort2 v) noexcept { return lc_ushort(lc_min(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_ushort2 v) noexcept { return lc_ushort(lc_max(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_ushort3 v) noexcept { return lc_ushort(v.x+v.y+v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_ushort3 v) noexcept { return lc_ushort(v.x*v.y*v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_ushort3 v) noexcept { return lc_ushort(lc_min(v.x, lc_min(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_ushort3 v) noexcept { return lc_ushort(lc_max(v.x, lc_max(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_ushort4 v) noexcept { return lc_ushort(v.x+v.y+v.z+v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_ushort4 v) noexcept { return lc_ushort(v.x*v.y*v.z*v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_ushort4 v) noexcept { return lc_ushort(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_ushort4 v) noexcept { return lc_ushort(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_int2 v) noexcept { return lc_int(v.x+v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_int2 v) noexcept { return lc_int(v.x*v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_int2 v) noexcept { return lc_int(lc_min(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_int2 v) noexcept { return lc_int(lc_max(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_int3 v) noexcept { return lc_int(v.x+v.y+v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_int3 v) noexcept { return lc_int(v.x*v.y*v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_int3 v) noexcept { return lc_int(lc_min(v.x, lc_min(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_int3 v) noexcept { return lc_int(lc_max(v.x, lc_max(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_int4 v) noexcept { return lc_int(v.x+v.y+v.z+v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_int4 v) noexcept { return lc_int(v.x*v.y*v.z*v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_int4 v) noexcept { return lc_int(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_int4 v) noexcept { return lc_int(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_uint2 v) noexcept { return lc_uint(v.x+v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_uint2 v) noexcept { return lc_uint(v.x*v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_uint2 v) noexcept { return lc_uint(lc_min(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_uint2 v) noexcept { return lc_uint(lc_max(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_uint3 v) noexcept { return lc_uint(v.x+v.y+v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_uint3 v) noexcept { return lc_uint(v.x*v.y*v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_uint3 v) noexcept { return lc_uint(lc_min(v.x, lc_min(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_uint3 v) noexcept { return lc_uint(lc_max(v.x, lc_max(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_uint4 v) noexcept { return lc_uint(v.x+v.y+v.z+v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_uint4 v) noexcept { return lc_uint(v.x*v.y*v.z*v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_uint4 v) noexcept { return lc_uint(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_uint4 v) noexcept { return lc_uint(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_half2 v) noexcept { return lc_half(v.x+v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_half2 v) noexcept { return lc_half(v.x*v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_half2 v) noexcept { return lc_half(lc_min(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_half2 v) noexcept { return lc_half(lc_max(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_half3 v) noexcept { return lc_half(v.x+v.y+v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_half3 v) noexcept { return lc_half(v.x*v.y*v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_half3 v) noexcept { return lc_half(lc_min(v.x, lc_min(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_half3 v) noexcept { return lc_half(lc_max(v.x, lc_max(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_half4 v) noexcept { return lc_half(v.x+v.y+v.z+v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_half4 v) noexcept { return lc_half(v.x*v.y*v.z*v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_half4 v) noexcept { return lc_half(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_half4 v) noexcept { return lc_half(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_float2 v) noexcept { return lc_float(v.x+v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_float2 v) noexcept { return lc_float(v.x*v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_float2 v) noexcept { return lc_float(lc_min(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_float2 v) noexcept { return lc_float(lc_max(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_float3 v) noexcept { return lc_float(v.x+v.y+v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_float3 v) noexcept { return lc_float(v.x*v.y*v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_float3 v) noexcept { return lc_float(lc_min(v.x, lc_min(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_float3 v) noexcept { return lc_float(lc_max(v.x, lc_max(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_float4 v) noexcept { return lc_float(v.x+v.y+v.z+v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_float4 v) noexcept { return lc_float(v.x*v.y*v.z*v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_float4 v) noexcept { return lc_float(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_float4 v) noexcept { return lc_float(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_long2 v) noexcept { return lc_long(v.x+v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_long2 v) noexcept { return lc_long(v.x*v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_long2 v) noexcept { return lc_long(lc_min(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_long2 v) noexcept { return lc_long(lc_max(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_long3 v) noexcept { return lc_long(v.x+v.y+v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_long3 v) noexcept { return lc_long(v.x*v.y*v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_long3 v) noexcept { return lc_long(lc_min(v.x, lc_min(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_long3 v) noexcept { return lc_long(lc_max(v.x, lc_max(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_long4 v) noexcept { return lc_long(v.x+v.y+v.z+v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_long4 v) noexcept { return lc_long(v.x*v.y*v.z*v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_long4 v) noexcept { return lc_long(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_long4 v) noexcept { return lc_long(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_ulong2 v) noexcept { return lc_ulong(v.x+v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_ulong2 v) noexcept { return lc_ulong(v.x*v.y); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_ulong2 v) noexcept { return lc_ulong(lc_min(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_ulong2 v) noexcept { return lc_ulong(lc_max(v.x, v.y)); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_ulong3 v) noexcept { return lc_ulong(v.x+v.y+v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_ulong3 v) noexcept { return lc_ulong(v.x*v.y*v.z); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_ulong3 v) noexcept { return lc_ulong(lc_min(v.x, lc_min(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_ulong3 v) noexcept { return lc_ulong(lc_max(v.x, lc_max(v.y, v.z))); } -[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_ulong4 v) noexcept { return lc_ulong(v.x+v.y+v.z+v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_ulong4 v) noexcept { return lc_ulong(v.x*v.y*v.z*v.w); } -[[nodiscard]] __device__ inline auto lc_reduce_min(lc_ulong4 v) noexcept { return lc_ulong(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_reduce_max(lc_ulong4 v) noexcept { return lc_ulong(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } -[[nodiscard]] __device__ inline auto lc_min_impl(lc_short a, lc_short b) noexcept { return a < b ? a : b; } -[[nodiscard]] __device__ inline auto lc_max_impl(lc_short a, lc_short b) noexcept { return a > b ? a : b; } -[[nodiscard]] __device__ inline auto lc_min_impl(lc_ushort a, lc_ushort b) noexcept { return a < b ? a : b; } -[[nodiscard]] __device__ inline auto lc_max_impl(lc_ushort a, lc_ushort b) noexcept { return a > b ? a : b; } -[[nodiscard]] __device__ inline auto lc_min_impl(lc_int a, lc_int b) noexcept { return a < b ? a : b; } -[[nodiscard]] __device__ inline auto lc_max_impl(lc_int a, lc_int b) noexcept { return a > b ? a : b; } -[[nodiscard]] __device__ inline auto lc_min_impl(lc_uint a, lc_uint b) noexcept { return a < b ? a : b; } -[[nodiscard]] __device__ inline auto lc_max_impl(lc_uint a, lc_uint b) noexcept { return a > b ? a : b; } -[[nodiscard]] __device__ inline auto lc_min_impl(lc_long a, lc_long b) noexcept { return a < b ? a : b; } -[[nodiscard]] __device__ inline auto lc_max_impl(lc_long a, lc_long b) noexcept { return a > b ? a : b; } -[[nodiscard]] __device__ inline auto lc_min_impl(lc_ulong a, lc_ulong b) noexcept { return a < b ? a : b; } -[[nodiscard]] __device__ inline auto lc_max_impl(lc_ulong a, lc_ulong b) noexcept { return a > b ? a : b; } -[[nodiscard]] __device__ inline lc_short lc_min(lc_short a, lc_short b) noexcept { return lc_min_impl(a, b); } -[[nodiscard]] __device__ inline lc_short2 lc_min(lc_short2 a, lc_short2 b) noexcept { return lc_make_short2(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_short3 lc_min(lc_short3 a, lc_short3 b) noexcept { return lc_make_short3(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_short4 lc_min(lc_short4 a, lc_short4 b) noexcept { return lc_make_short4(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z), lc_min_impl(a.w, b.w)); } -[[nodiscard]] __device__ inline lc_ushort lc_min(lc_ushort a, lc_ushort b) noexcept { return lc_min_impl(a, b); } -[[nodiscard]] __device__ inline lc_ushort2 lc_min(lc_ushort2 a, lc_ushort2 b) noexcept { return lc_make_ushort2(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_ushort3 lc_min(lc_ushort3 a, lc_ushort3 b) noexcept { return lc_make_ushort3(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_ushort4 lc_min(lc_ushort4 a, lc_ushort4 b) noexcept { return lc_make_ushort4(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z), lc_min_impl(a.w, b.w)); } -[[nodiscard]] __device__ inline lc_int lc_min(lc_int a, lc_int b) noexcept { return lc_min_impl(a, b); } -[[nodiscard]] __device__ inline lc_int2 lc_min(lc_int2 a, lc_int2 b) noexcept { return lc_make_int2(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_int3 lc_min(lc_int3 a, lc_int3 b) noexcept { return lc_make_int3(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_int4 lc_min(lc_int4 a, lc_int4 b) noexcept { return lc_make_int4(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z), lc_min_impl(a.w, b.w)); } -[[nodiscard]] __device__ inline lc_uint lc_min(lc_uint a, lc_uint b) noexcept { return lc_min_impl(a, b); } -[[nodiscard]] __device__ inline lc_uint2 lc_min(lc_uint2 a, lc_uint2 b) noexcept { return lc_make_uint2(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_uint3 lc_min(lc_uint3 a, lc_uint3 b) noexcept { return lc_make_uint3(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_uint4 lc_min(lc_uint4 a, lc_uint4 b) noexcept { return lc_make_uint4(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z), lc_min_impl(a.w, b.w)); } -[[nodiscard]] __device__ inline lc_long lc_min(lc_long a, lc_long b) noexcept { return lc_min_impl(a, b); } -[[nodiscard]] __device__ inline lc_long2 lc_min(lc_long2 a, lc_long2 b) noexcept { return lc_make_long2(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_long3 lc_min(lc_long3 a, lc_long3 b) noexcept { return lc_make_long3(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_long4 lc_min(lc_long4 a, lc_long4 b) noexcept { return lc_make_long4(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z), lc_min_impl(a.w, b.w)); } -[[nodiscard]] __device__ inline lc_ulong lc_min(lc_ulong a, lc_ulong b) noexcept { return lc_min_impl(a, b); } -[[nodiscard]] __device__ inline lc_ulong2 lc_min(lc_ulong2 a, lc_ulong2 b) noexcept { return lc_make_ulong2(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_ulong3 lc_min(lc_ulong3 a, lc_ulong3 b) noexcept { return lc_make_ulong3(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_ulong4 lc_min(lc_ulong4 a, lc_ulong4 b) noexcept { return lc_make_ulong4(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z), lc_min_impl(a.w, b.w)); } - -[[nodiscard]] __device__ inline lc_short lc_max(lc_short a, lc_short b) noexcept { return lc_max_impl(a, b); } -[[nodiscard]] __device__ inline lc_short2 lc_max(lc_short2 a, lc_short2 b) noexcept { return lc_make_short2(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_short3 lc_max(lc_short3 a, lc_short3 b) noexcept { return lc_make_short3(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_short4 lc_max(lc_short4 a, lc_short4 b) noexcept { return lc_make_short4(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z), lc_max_impl(a.w, b.w)); } -[[nodiscard]] __device__ inline lc_ushort lc_max(lc_ushort a, lc_ushort b) noexcept { return lc_max_impl(a, b); } -[[nodiscard]] __device__ inline lc_ushort2 lc_max(lc_ushort2 a, lc_ushort2 b) noexcept { return lc_make_ushort2(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_ushort3 lc_max(lc_ushort3 a, lc_ushort3 b) noexcept { return lc_make_ushort3(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_ushort4 lc_max(lc_ushort4 a, lc_ushort4 b) noexcept { return lc_make_ushort4(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z), lc_max_impl(a.w, b.w)); } -[[nodiscard]] __device__ inline lc_int lc_max(lc_int a, lc_int b) noexcept { return lc_max_impl(a, b); } -[[nodiscard]] __device__ inline lc_int2 lc_max(lc_int2 a, lc_int2 b) noexcept { return lc_make_int2(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_int3 lc_max(lc_int3 a, lc_int3 b) noexcept { return lc_make_int3(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_int4 lc_max(lc_int4 a, lc_int4 b) noexcept { return lc_make_int4(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z), lc_max_impl(a.w, b.w)); } -[[nodiscard]] __device__ inline lc_uint lc_max(lc_uint a, lc_uint b) noexcept { return lc_max_impl(a, b); } -[[nodiscard]] __device__ inline lc_uint2 lc_max(lc_uint2 a, lc_uint2 b) noexcept { return lc_make_uint2(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_uint3 lc_max(lc_uint3 a, lc_uint3 b) noexcept { return lc_make_uint3(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_uint4 lc_max(lc_uint4 a, lc_uint4 b) noexcept { return lc_make_uint4(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z), lc_max_impl(a.w, b.w)); } -[[nodiscard]] __device__ inline lc_long lc_max(lc_long a, lc_long b) noexcept { return lc_max_impl(a, b); } -[[nodiscard]] __device__ inline lc_long2 lc_max(lc_long2 a, lc_long2 b) noexcept { return lc_make_long2(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_long3 lc_max(lc_long3 a, lc_long3 b) noexcept { return lc_make_long3(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_long4 lc_max(lc_long4 a, lc_long4 b) noexcept { return lc_make_long4(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z), lc_max_impl(a.w, b.w)); } -[[nodiscard]] __device__ inline lc_ulong lc_max(lc_ulong a, lc_ulong b) noexcept { return lc_max_impl(a, b); } -[[nodiscard]] __device__ inline lc_ulong2 lc_max(lc_ulong2 a, lc_ulong2 b) noexcept { return lc_make_ulong2(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y)); } -[[nodiscard]] __device__ inline lc_ulong3 lc_max(lc_ulong3 a, lc_ulong3 b) noexcept { return lc_make_ulong3(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z)); } -[[nodiscard]] __device__ inline lc_ulong4 lc_max(lc_ulong4 a, lc_ulong4 b) noexcept { return lc_make_ulong4(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z), lc_max_impl(a.w, b.w)); } - -[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_short v, lc_short lo, lc_short hi) noexcept { return lc_min(lc_max(v, lo), hi); } -[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_ushort v, lc_ushort lo, lc_ushort hi) noexcept { return lc_min(lc_max(v, lo), hi); } -[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_int v, lc_int lo, lc_int hi) noexcept { return lc_min(lc_max(v, lo), hi); } -[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_uint v, lc_uint lo, lc_uint hi) noexcept { return lc_min(lc_max(v, lo), hi); } -[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_half v, lc_half lo, lc_half hi) noexcept { return lc_min(lc_max(v, lo), hi); } -[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_float v, lc_float lo, lc_float hi) noexcept { return lc_min(lc_max(v, lo), hi); } -[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_long v, lc_long lo, lc_long hi) noexcept { return lc_min(lc_max(v, lo), hi); } -[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_ulong v, lc_ulong lo, lc_ulong hi) noexcept { return lc_min(lc_max(v, lo), hi); } -[[nodiscard]] __device__ inline lc_short lc_clamp(lc_short v, lc_short lo, lc_short hi) noexcept { return lc_clamp_impl(v, lo, hi); } -[[nodiscard]] __device__ inline lc_short2 lc_clamp(lc_short2 v, lc_short2 lo, lc_short2 hi) noexcept { return lc_make_short2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } -[[nodiscard]] __device__ inline lc_short3 lc_clamp(lc_short3 v, lc_short3 lo, lc_short3 hi) noexcept { return lc_make_short3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } -[[nodiscard]] __device__ inline lc_short4 lc_clamp(lc_short4 v, lc_short4 lo, lc_short4 hi) noexcept { return lc_make_short4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } -[[nodiscard]] __device__ inline lc_ushort lc_clamp(lc_ushort v, lc_ushort lo, lc_ushort hi) noexcept { return lc_clamp_impl(v, lo, hi); } -[[nodiscard]] __device__ inline lc_ushort2 lc_clamp(lc_ushort2 v, lc_ushort2 lo, lc_ushort2 hi) noexcept { return lc_make_ushort2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } -[[nodiscard]] __device__ inline lc_ushort3 lc_clamp(lc_ushort3 v, lc_ushort3 lo, lc_ushort3 hi) noexcept { return lc_make_ushort3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } -[[nodiscard]] __device__ inline lc_ushort4 lc_clamp(lc_ushort4 v, lc_ushort4 lo, lc_ushort4 hi) noexcept { return lc_make_ushort4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } -[[nodiscard]] __device__ inline lc_int lc_clamp(lc_int v, lc_int lo, lc_int hi) noexcept { return lc_clamp_impl(v, lo, hi); } -[[nodiscard]] __device__ inline lc_int2 lc_clamp(lc_int2 v, lc_int2 lo, lc_int2 hi) noexcept { return lc_make_int2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } -[[nodiscard]] __device__ inline lc_int3 lc_clamp(lc_int3 v, lc_int3 lo, lc_int3 hi) noexcept { return lc_make_int3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } -[[nodiscard]] __device__ inline lc_int4 lc_clamp(lc_int4 v, lc_int4 lo, lc_int4 hi) noexcept { return lc_make_int4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } -[[nodiscard]] __device__ inline lc_uint lc_clamp(lc_uint v, lc_uint lo, lc_uint hi) noexcept { return lc_clamp_impl(v, lo, hi); } -[[nodiscard]] __device__ inline lc_uint2 lc_clamp(lc_uint2 v, lc_uint2 lo, lc_uint2 hi) noexcept { return lc_make_uint2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } -[[nodiscard]] __device__ inline lc_uint3 lc_clamp(lc_uint3 v, lc_uint3 lo, lc_uint3 hi) noexcept { return lc_make_uint3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } -[[nodiscard]] __device__ inline lc_uint4 lc_clamp(lc_uint4 v, lc_uint4 lo, lc_uint4 hi) noexcept { return lc_make_uint4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } -[[nodiscard]] __device__ inline lc_long lc_clamp(lc_long v, lc_long lo, lc_long hi) noexcept { return lc_clamp_impl(v, lo, hi); } -[[nodiscard]] __device__ inline lc_long2 lc_clamp(lc_long2 v, lc_long2 lo, lc_long2 hi) noexcept { return lc_make_long2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } -[[nodiscard]] __device__ inline lc_long3 lc_clamp(lc_long3 v, lc_long3 lo, lc_long3 hi) noexcept { return lc_make_long3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } -[[nodiscard]] __device__ inline lc_long4 lc_clamp(lc_long4 v, lc_long4 lo, lc_long4 hi) noexcept { return lc_make_long4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } -[[nodiscard]] __device__ inline lc_ulong lc_clamp(lc_ulong v, lc_ulong lo, lc_ulong hi) noexcept { return lc_clamp_impl(v, lo, hi); } -[[nodiscard]] __device__ inline lc_ulong2 lc_clamp(lc_ulong2 v, lc_ulong2 lo, lc_ulong2 hi) noexcept { return lc_make_ulong2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } -[[nodiscard]] __device__ inline lc_ulong3 lc_clamp(lc_ulong3 v, lc_ulong3 lo, lc_ulong3 hi) noexcept { return lc_make_ulong3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } -[[nodiscard]] __device__ inline lc_ulong4 lc_clamp(lc_ulong4 v, lc_ulong4 lo, lc_ulong4 hi) noexcept { return lc_make_ulong4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } -[[nodiscard]] __device__ inline lc_half lc_clamp(lc_half v, lc_half lo, lc_half hi) noexcept { return lc_clamp_impl(v, lo, hi); } -[[nodiscard]] __device__ inline lc_half2 lc_clamp(lc_half2 v, lc_half2 lo, lc_half2 hi) noexcept { return lc_make_half2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_clamp(lc_half3 v, lc_half3 lo, lc_half3 hi) noexcept { return lc_make_half3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_clamp(lc_half4 v, lc_half4 lo, lc_half4 hi) noexcept { return lc_make_half4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } -[[nodiscard]] __device__ inline lc_float lc_clamp(lc_float v, lc_float lo, lc_float hi) noexcept { return lc_clamp_impl(v, lo, hi); } -[[nodiscard]] __device__ inline lc_float2 lc_clamp(lc_float2 v, lc_float2 lo, lc_float2 hi) noexcept { return lc_make_float2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_clamp(lc_float3 v, lc_float3 lo, lc_float3 hi) noexcept { return lc_make_float3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_clamp(lc_float4 v, lc_float4 lo, lc_float4 hi) noexcept { return lc_make_float4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } - -[[nodiscard]] __device__ inline auto lc_lerp_impl(lc_half a, lc_half b, lc_half t) noexcept { return t * (b - a) + a; } -[[nodiscard]] __device__ inline auto lc_saturate(lc_half x) noexcept { return lc_clamp(x, lc_half(0.0f), lc_half(1.0f)); } -[[nodiscard]] __device__ inline auto lc_saturate(lc_half2 x) noexcept { return lc_clamp(x, lc_make_half2(0.0f), lc_make_half2(1.0f)); } -[[nodiscard]] __device__ inline auto lc_saturate(lc_half3 x) noexcept { return lc_clamp(x, lc_make_half3(0.0f), lc_make_half3(1.0f)); } -[[nodiscard]] __device__ inline auto lc_saturate(lc_half4 x) noexcept { return lc_clamp(x, lc_make_half4(0.0f), lc_make_half4(1.0f)); } - -[[nodiscard]] __device__ inline auto lc_degrees_impl(lc_half rad) noexcept { return rad * (lc_half)(180.0f * 0.318309886183790671537767526745028724f); } -[[nodiscard]] __device__ inline auto lc_radians_impl(lc_half deg) noexcept { return deg * (lc_half)(3.14159265358979323846264338327950288f / 180.0f); } -[[nodiscard]] __device__ inline auto lc_step_impl(lc_half edge, lc_half x) noexcept { return lc_select(lc_half(1.f), lc_half(0.f), x < edge); } -[[nodiscard]] __device__ inline auto lc_smoothstep_impl(lc_half edge0, lc_half edge1, lc_half x) noexcept { - auto t = lc_clamp((x - edge0) / (edge1 - edge0), lc_half(0.0f), lc_half(1.0f)); - return t * t * (lc_half(3.f) - lc_half(2.f) * t); -} -[[nodiscard]] __device__ inline auto lc_mod_impl(lc_half x, lc_half y) noexcept { return x - y * lc_floor(x / y); } -[[nodiscard]] __device__ inline auto lc_fmod_impl(lc_half x, lc_half y) noexcept { return x - y * lc_trunc(x / y); } -[[nodiscard]] __device__ inline auto lc_fract_impl(lc_half x) noexcept { return x - lc_floor(x); } -[[nodiscard]] __device__ inline auto lc_lerp_impl(lc_float a, lc_float b, lc_float t) noexcept { return t * (b - a) + a; } -[[nodiscard]] __device__ inline auto lc_saturate(lc_float x) noexcept { return lc_clamp(x, lc_float(0.0f), lc_float(1.0f)); } -[[nodiscard]] __device__ inline auto lc_saturate(lc_float2 x) noexcept { return lc_clamp(x, lc_make_float2(0.0f), lc_make_float2(1.0f)); } -[[nodiscard]] __device__ inline auto lc_saturate(lc_float3 x) noexcept { return lc_clamp(x, lc_make_float3(0.0f), lc_make_float3(1.0f)); } -[[nodiscard]] __device__ inline auto lc_saturate(lc_float4 x) noexcept { return lc_clamp(x, lc_make_float4(0.0f), lc_make_float4(1.0f)); } - -[[nodiscard]] __device__ inline auto lc_degrees_impl(lc_float rad) noexcept { return rad * (lc_float)(180.0f * 0.318309886183790671537767526745028724f); } -[[nodiscard]] __device__ inline auto lc_radians_impl(lc_float deg) noexcept { return deg * (lc_float)(3.14159265358979323846264338327950288f / 180.0f); } -[[nodiscard]] __device__ inline auto lc_step_impl(lc_float edge, lc_float x) noexcept { return lc_select(lc_float(1.f), lc_float(0.f), x < edge); } -[[nodiscard]] __device__ inline auto lc_smoothstep_impl(lc_float edge0, lc_float edge1, lc_float x) noexcept { - auto t = lc_clamp((x - edge0) / (edge1 - edge0), lc_float(0.0f), lc_float(1.0f)); - return t * t * (lc_float(3.f) - lc_float(2.f) * t); -} -[[nodiscard]] __device__ inline auto lc_mod_impl(lc_float x, lc_float y) noexcept { return x - y * lc_floor(x / y); } -[[nodiscard]] __device__ inline auto lc_fmod_impl(lc_float x, lc_float y) noexcept { return fmodf(x, y); } -[[nodiscard]] __device__ inline auto lc_fract_impl(lc_float x) noexcept { return x - lc_floor(x); } -[[nodiscard]] __device__ inline lc_half lc_lerp(lc_half a, lc_half b, lc_half t) noexcept { return lc_lerp_impl(a, b, t); } -[[nodiscard]] __device__ inline lc_half2 lc_lerp(lc_half2 a, lc_half2 b, lc_half2 t) noexcept { return lc_make_half2(lc_lerp_impl(a.x, b.x, t.x), lc_lerp_impl(a.y, b.y, t.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_lerp(lc_half3 a, lc_half3 b, lc_half3 t) noexcept { return lc_make_half3(lc_lerp_impl(a.x, b.x, t.x), lc_lerp_impl(a.y, b.y, t.y), lc_lerp_impl(a.z, b.z, t.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_lerp(lc_half4 a, lc_half4 b, lc_half4 t) noexcept { return lc_make_half4(lc_lerp_impl(a.x, b.x, t.x), lc_lerp_impl(a.y, b.y, t.y), lc_lerp_impl(a.z, b.z, t.z), lc_lerp_impl(a.w, b.w, t.w)); } -[[nodiscard]] __device__ inline lc_float lc_lerp(lc_float a, lc_float b, lc_float t) noexcept { return lc_lerp_impl(a, b, t); } -[[nodiscard]] __device__ inline lc_float2 lc_lerp(lc_float2 a, lc_float2 b, lc_float2 t) noexcept { return lc_make_float2(lc_lerp_impl(a.x, b.x, t.x), lc_lerp_impl(a.y, b.y, t.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_lerp(lc_float3 a, lc_float3 b, lc_float3 t) noexcept { return lc_make_float3(lc_lerp_impl(a.x, b.x, t.x), lc_lerp_impl(a.y, b.y, t.y), lc_lerp_impl(a.z, b.z, t.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_lerp(lc_float4 a, lc_float4 b, lc_float4 t) noexcept { return lc_make_float4(lc_lerp_impl(a.x, b.x, t.x), lc_lerp_impl(a.y, b.y, t.y), lc_lerp_impl(a.z, b.z, t.z), lc_lerp_impl(a.w, b.w, t.w)); } - -[[nodiscard]] __device__ inline lc_half lc_degrees(lc_half rad) noexcept { return lc_degrees_impl(rad); } -[[nodiscard]] __device__ inline lc_half2 lc_degrees(lc_half2 rad) noexcept { return lc_make_half2(lc_degrees_impl(rad.x), lc_degrees_impl(rad.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_degrees(lc_half3 rad) noexcept { return lc_make_half3(lc_degrees_impl(rad.x), lc_degrees_impl(rad.y), lc_degrees_impl(rad.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_degrees(lc_half4 rad) noexcept { return lc_make_half4(lc_degrees_impl(rad.x), lc_degrees_impl(rad.y), lc_degrees_impl(rad.z), lc_degrees_impl(rad.w)); } -[[nodiscard]] __device__ inline lc_float lc_degrees(lc_float rad) noexcept { return lc_degrees_impl(rad); } -[[nodiscard]] __device__ inline lc_float2 lc_degrees(lc_float2 rad) noexcept { return lc_make_float2(lc_degrees_impl(rad.x), lc_degrees_impl(rad.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_degrees(lc_float3 rad) noexcept { return lc_make_float3(lc_degrees_impl(rad.x), lc_degrees_impl(rad.y), lc_degrees_impl(rad.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_degrees(lc_float4 rad) noexcept { return lc_make_float4(lc_degrees_impl(rad.x), lc_degrees_impl(rad.y), lc_degrees_impl(rad.z), lc_degrees_impl(rad.w)); } - -[[nodiscard]] __device__ inline lc_half lc_radians(lc_half deg) noexcept { return lc_radians_impl(deg); } -[[nodiscard]] __device__ inline lc_half2 lc_radians(lc_half2 deg) noexcept { return lc_make_half2(lc_radians_impl(deg.x), lc_radians_impl(deg.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_radians(lc_half3 deg) noexcept { return lc_make_half3(lc_radians_impl(deg.x), lc_radians_impl(deg.y), lc_radians_impl(deg.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_radians(lc_half4 deg) noexcept { return lc_make_half4(lc_radians_impl(deg.x), lc_radians_impl(deg.y), lc_radians_impl(deg.z), lc_radians_impl(deg.w)); } -[[nodiscard]] __device__ inline lc_float lc_radians(lc_float deg) noexcept { return lc_radians_impl(deg); } -[[nodiscard]] __device__ inline lc_float2 lc_radians(lc_float2 deg) noexcept { return lc_make_float2(lc_radians_impl(deg.x), lc_radians_impl(deg.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_radians(lc_float3 deg) noexcept { return lc_make_float3(lc_radians_impl(deg.x), lc_radians_impl(deg.y), lc_radians_impl(deg.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_radians(lc_float4 deg) noexcept { return lc_make_float4(lc_radians_impl(deg.x), lc_radians_impl(deg.y), lc_radians_impl(deg.z), lc_radians_impl(deg.w)); } - -[[nodiscard]] __device__ inline lc_half lc_step(lc_half edge, lc_half x) noexcept { return lc_step_impl(edge, x); } -[[nodiscard]] __device__ inline lc_half2 lc_step(lc_half2 edge, lc_half2 x) noexcept { return lc_make_half2(lc_step_impl(edge.x, x.x), lc_step_impl(edge.y, x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_step(lc_half3 edge, lc_half3 x) noexcept { return lc_make_half3(lc_step_impl(edge.x, x.x), lc_step_impl(edge.y, x.y), lc_step_impl(edge.z, x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_step(lc_half4 edge, lc_half4 x) noexcept { return lc_make_half4(lc_step_impl(edge.x, x.x), lc_step_impl(edge.y, x.y), lc_step_impl(edge.z, x.z), lc_step_impl(edge.w, x.w)); } -[[nodiscard]] __device__ inline lc_float lc_step(lc_float edge, lc_float x) noexcept { return lc_step_impl(edge, x); } -[[nodiscard]] __device__ inline lc_float2 lc_step(lc_float2 edge, lc_float2 x) noexcept { return lc_make_float2(lc_step_impl(edge.x, x.x), lc_step_impl(edge.y, x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_step(lc_float3 edge, lc_float3 x) noexcept { return lc_make_float3(lc_step_impl(edge.x, x.x), lc_step_impl(edge.y, x.y), lc_step_impl(edge.z, x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_step(lc_float4 edge, lc_float4 x) noexcept { return lc_make_float4(lc_step_impl(edge.x, x.x), lc_step_impl(edge.y, x.y), lc_step_impl(edge.z, x.z), lc_step_impl(edge.w, x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_smoothstep(lc_half e0, lc_half e1, lc_half x) noexcept { return lc_smoothstep_impl(e0, e1, x); } -[[nodiscard]] __device__ inline lc_half2 lc_smoothstep(lc_half2 e0, lc_half2 e1, lc_half2 x) noexcept { return lc_make_half2(lc_smoothstep_impl(e0.x, e1.x, x.x), lc_smoothstep_impl(e0.y, e1.y, x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_smoothstep(lc_half3 e0, lc_half3 e1, lc_half3 x) noexcept { return lc_make_half3(lc_smoothstep_impl(e0.x, e1.x, x.x), lc_smoothstep_impl(e0.y, e1.y, x.y), lc_smoothstep_impl(e0.z, e1.z, x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_smoothstep(lc_half4 e0, lc_half4 e1, lc_half4 x) noexcept { return lc_make_half4(lc_smoothstep_impl(e0.x, e1.x, x.x), lc_smoothstep_impl(e0.y, e1.y, x.y), lc_smoothstep_impl(e0.z, e1.z, x.z), lc_smoothstep_impl(e0.w, e1.w, x.w)); } -[[nodiscard]] __device__ inline lc_float lc_smoothstep(lc_float e0, lc_float e1, lc_float x) noexcept { return lc_smoothstep_impl(e0, e1, x); } -[[nodiscard]] __device__ inline lc_float2 lc_smoothstep(lc_float2 e0, lc_float2 e1, lc_float2 x) noexcept { return lc_make_float2(lc_smoothstep_impl(e0.x, e1.x, x.x), lc_smoothstep_impl(e0.y, e1.y, x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_smoothstep(lc_float3 e0, lc_float3 e1, lc_float3 x) noexcept { return lc_make_float3(lc_smoothstep_impl(e0.x, e1.x, x.x), lc_smoothstep_impl(e0.y, e1.y, x.y), lc_smoothstep_impl(e0.z, e1.z, x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_smoothstep(lc_float4 e0, lc_float4 e1, lc_float4 x) noexcept { return lc_make_float4(lc_smoothstep_impl(e0.x, e1.x, x.x), lc_smoothstep_impl(e0.y, e1.y, x.y), lc_smoothstep_impl(e0.z, e1.z, x.z), lc_smoothstep_impl(e0.w, e1.w, x.w)); } - -[[nodiscard]] __device__ inline lc_half lc_mod(lc_half x, lc_half y) noexcept { return lc_mod_impl(x, y); } -[[nodiscard]] __device__ inline lc_half2 lc_mod(lc_half2 x, lc_half2 y) noexcept { return lc_make_half2(lc_mod_impl(x.x, y.x), lc_mod_impl(x.y, y.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_mod(lc_half3 x, lc_half3 y) noexcept { return lc_make_half3(lc_mod_impl(x.x, y.x), lc_mod_impl(x.y, y.y), lc_mod_impl(x.z, y.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_mod(lc_half4 x, lc_half4 y) noexcept { return lc_make_half4(lc_mod_impl(x.x, y.x), lc_mod_impl(x.y, y.y), lc_mod_impl(x.z, y.z), lc_mod_impl(x.w, y.w)); } -[[nodiscard]] __device__ inline lc_float lc_mod(lc_float x, lc_float y) noexcept { return lc_mod_impl(x, y); } -[[nodiscard]] __device__ inline lc_float2 lc_mod(lc_float2 x, lc_float2 y) noexcept { return lc_make_float2(lc_mod_impl(x.x, y.x), lc_mod_impl(x.y, y.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_mod(lc_float3 x, lc_float3 y) noexcept { return lc_make_float3(lc_mod_impl(x.x, y.x), lc_mod_impl(x.y, y.y), lc_mod_impl(x.z, y.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_mod(lc_float4 x, lc_float4 y) noexcept { return lc_make_float4(lc_mod_impl(x.x, y.x), lc_mod_impl(x.y, y.y), lc_mod_impl(x.z, y.z), lc_mod_impl(x.w, y.w)); } - -[[nodiscard]] __device__ inline lc_half lc_fmod(lc_half x, lc_half y) noexcept { return lc_fmod_impl(x, y); } -[[nodiscard]] __device__ inline lc_half2 lc_fmod(lc_half2 x, lc_half2 y) noexcept { return lc_make_half2(lc_fmod_impl(x.x, y.x), lc_fmod_impl(x.y, y.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_fmod(lc_half3 x, lc_half3 y) noexcept { return lc_make_half3(lc_fmod_impl(x.x, y.x), lc_fmod_impl(x.y, y.y), lc_fmod_impl(x.z, y.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_fmod(lc_half4 x, lc_half4 y) noexcept { return lc_make_half4(lc_fmod_impl(x.x, y.x), lc_fmod_impl(x.y, y.y), lc_fmod_impl(x.z, y.z), lc_fmod_impl(x.w, y.w)); } -[[nodiscard]] __device__ inline lc_float lc_fmod(lc_float x, lc_float y) noexcept { return lc_fmod_impl(x, y); } -[[nodiscard]] __device__ inline lc_float2 lc_fmod(lc_float2 x, lc_float2 y) noexcept { return lc_make_float2(lc_fmod_impl(x.x, y.x), lc_fmod_impl(x.y, y.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_fmod(lc_float3 x, lc_float3 y) noexcept { return lc_make_float3(lc_fmod_impl(x.x, y.x), lc_fmod_impl(x.y, y.y), lc_fmod_impl(x.z, y.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_fmod(lc_float4 x, lc_float4 y) noexcept { return lc_make_float4(lc_fmod_impl(x.x, y.x), lc_fmod_impl(x.y, y.y), lc_fmod_impl(x.z, y.z), lc_fmod_impl(x.w, y.w)); } - -[[nodiscard]] __device__ inline lc_half lc_fract(lc_half x) noexcept { return lc_fract_impl(x); } -[[nodiscard]] __device__ inline lc_half2 lc_fract(lc_half2 x) noexcept { return lc_make_half2(lc_fract_impl(x.x), lc_fract_impl(x.y)); } -[[nodiscard]] __device__ inline lc_half3 lc_fract(lc_half3 x) noexcept { return lc_make_half3(lc_fract_impl(x.x), lc_fract_impl(x.y), lc_fract_impl(x.z)); } -[[nodiscard]] __device__ inline lc_half4 lc_fract(lc_half4 x) noexcept { return lc_make_half4(lc_fract_impl(x.x), lc_fract_impl(x.y), lc_fract_impl(x.z), lc_fract_impl(x.w)); } -[[nodiscard]] __device__ inline lc_float lc_fract(lc_float x) noexcept { return lc_fract_impl(x); } -[[nodiscard]] __device__ inline lc_float2 lc_fract(lc_float2 x) noexcept { return lc_make_float2(lc_fract_impl(x.x), lc_fract_impl(x.y)); } -[[nodiscard]] __device__ inline lc_float3 lc_fract(lc_float3 x) noexcept { return lc_make_float3(lc_fract_impl(x.x), lc_fract_impl(x.y), lc_fract_impl(x.z)); } -[[nodiscard]] __device__ inline lc_float4 lc_fract(lc_float4 x) noexcept { return lc_make_float4(lc_fract_impl(x.x), lc_fract_impl(x.y), lc_fract_impl(x.z), lc_fract_impl(x.w)); } - -[[nodiscard]] __device__ inline lc_uint lc_clz(lc_uint x) noexcept { return __clz(x); } -[[nodiscard]] __device__ inline lc_uint2 lc_clz(lc_uint2 x) noexcept { return lc_make_uint2(__clz(x.x), __clz(x.y)); } -[[nodiscard]] __device__ inline lc_uint3 lc_clz(lc_uint3 x) noexcept { return lc_make_uint3(__clz(x.x), __clz(x.y), __clz(x.z)); } -[[nodiscard]] __device__ inline lc_uint4 lc_clz(lc_uint4 x) noexcept { return lc_make_uint4(__clz(x.x), __clz(x.y), __clz(x.z), __clz(x.w)); } - -[[nodiscard]] __device__ inline lc_ulong lc_clz(lc_ulong x) noexcept { return __clzll(x); } -[[nodiscard]] __device__ inline lc_ulong2 lc_clz(lc_ulong2 x) noexcept { return lc_make_ulong2(__clzll(x.x), __clzll(x.y)); } -[[nodiscard]] __device__ inline lc_ulong3 lc_clz(lc_ulong3 x) noexcept { return lc_make_ulong3(__clzll(x.x), __clzll(x.y), __clzll(x.z)); } -[[nodiscard]] __device__ inline lc_ulong4 lc_clz(lc_ulong4 x) noexcept { return lc_make_ulong4(__clzll(x.x), __clzll(x.y), __clzll(x.z), __clzll(x.w)); } - -[[nodiscard]] __device__ inline lc_uint lc_popcount(lc_uint x) noexcept { return __popc(x); } -[[nodiscard]] __device__ inline lc_uint2 lc_popcount(lc_uint2 x) noexcept { return lc_make_uint2(__popc(x.x), __popc(x.y)); } -[[nodiscard]] __device__ inline lc_uint3 lc_popcount(lc_uint3 x) noexcept { return lc_make_uint3(__popc(x.x), __popc(x.y), __popc(x.z)); } -[[nodiscard]] __device__ inline lc_uint4 lc_popcount(lc_uint4 x) noexcept { return lc_make_uint4(__popc(x.x), __popc(x.y), __popc(x.z), __popc(x.w)); } - -[[nodiscard]] __device__ inline lc_ulong lc_popcount(lc_ulong x) noexcept { return __popcll(x); } -[[nodiscard]] __device__ inline lc_ulong2 lc_popcount(lc_ulong2 x) noexcept { return lc_make_ulong2(__popcll(x.x), __popcll(x.y)); } -[[nodiscard]] __device__ inline lc_ulong3 lc_popcount(lc_ulong3 x) noexcept { return lc_make_ulong3(__popcll(x.x), __popcll(x.y), __popcll(x.z)); } -[[nodiscard]] __device__ inline lc_ulong4 lc_popcount(lc_ulong4 x) noexcept { return lc_make_ulong4(__popcll(x.x), __popcll(x.y), __popcll(x.z), __popcll(x.w)); } - -[[nodiscard]] __device__ inline lc_uint lc_reverse(lc_uint x) noexcept { return __brev(x); } -[[nodiscard]] __device__ inline lc_uint2 lc_reverse(lc_uint2 x) noexcept { return lc_make_uint2(__brev(x.x), __brev(x.y)); } -[[nodiscard]] __device__ inline lc_uint3 lc_reverse(lc_uint3 x) noexcept { return lc_make_uint3(__brev(x.x), __brev(x.y), __brev(x.z)); } -[[nodiscard]] __device__ inline lc_uint4 lc_reverse(lc_uint4 x) noexcept { return lc_make_uint4(__brev(x.x), __brev(x.y), __brev(x.z), __brev(x.w)); } - -[[nodiscard]] __device__ inline lc_ulong lc_reverse(lc_ulong x) noexcept { return __brevll(x); } -[[nodiscard]] __device__ inline lc_ulong2 lc_reverse(lc_ulong2 x) noexcept { return lc_make_ulong2(__brevll(x.x), __brevll(x.y)); } -[[nodiscard]] __device__ inline lc_ulong3 lc_reverse(lc_ulong3 x) noexcept { return lc_make_ulong3(__brevll(x.x), __brevll(x.y), __brevll(x.z)); } -[[nodiscard]] __device__ inline lc_ulong4 lc_reverse(lc_ulong4 x) noexcept { return lc_make_ulong4(__brevll(x.x), __brevll(x.y), __brevll(x.z), __brevll(x.w)); } - -[[nodiscard]] __device__ inline auto lc_ctz_impl(lc_uint x) noexcept { return (__ffs(x) - 1u) % 32u; } -[[nodiscard]] __device__ inline auto lc_ctz_impl(lc_ulong x) noexcept { return (__ffsll(x) - 1u) % 64u; } -[[nodiscard]] __device__ inline lc_uint lc_ctz(lc_uint x) noexcept { return lc_ctz_impl(x); } -[[nodiscard]] __device__ inline lc_uint2 lc_ctz(lc_uint2 x) noexcept { return lc_make_uint2(lc_ctz_impl(x.x), lc_ctz_impl(x.y)); } -[[nodiscard]] __device__ inline lc_uint3 lc_ctz(lc_uint3 x) noexcept { return lc_make_uint3(lc_ctz_impl(x.x), lc_ctz_impl(x.y), lc_ctz_impl(x.z)); } -[[nodiscard]] __device__ inline lc_uint4 lc_ctz(lc_uint4 x) noexcept { return lc_make_uint4(lc_ctz_impl(x.x), lc_ctz_impl(x.y), lc_ctz_impl(x.z), lc_ctz_impl(x.w)); } -[[nodiscard]] __device__ inline lc_ulong lc_ctz(lc_ulong x) noexcept { return lc_ctz_impl(x); } -[[nodiscard]] __device__ inline lc_ulong2 lc_ctz(lc_ulong2 x) noexcept { return lc_make_ulong2(lc_ctz_impl(x.x), lc_ctz_impl(x.y)); } -[[nodiscard]] __device__ inline lc_ulong3 lc_ctz(lc_ulong3 x) noexcept { return lc_make_ulong3(lc_ctz_impl(x.x), lc_ctz_impl(x.y), lc_ctz_impl(x.z)); } -[[nodiscard]] __device__ inline lc_ulong4 lc_ctz(lc_ulong4 x) noexcept { return lc_make_ulong4(lc_ctz_impl(x.x), lc_ctz_impl(x.y), lc_ctz_impl(x.z), lc_ctz_impl(x.w)); } - -[[nodiscard]] __device__ inline constexpr auto lc_cross(lc_float3 u, lc_float3 v) noexcept { - return lc_make_float3(u.y * v.z - v.y * u.z, - u.z * v.x - v.z * u.x, - u.x * v.y - v.x * u.y); -} - -[[nodiscard]] __device__ inline auto lc_dot(lc_float2 a, lc_float2 b) noexcept { - return a.x * b.x + a.y * b.y; -} -[[nodiscard]] __device__ inline auto lc_dot(lc_float3 a, lc_float3 b) noexcept { - return a.x * b.x + a.y * b.y + a.z * b.z; -} -[[nodiscard]] __device__ inline auto lc_dot(lc_float4 a, lc_float4 b) noexcept { - return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; -} - -[[nodiscard]] __device__ inline auto lc_length(lc_float2 v) noexcept { return lc_sqrt(lc_dot(v, v)); } -[[nodiscard]] __device__ inline auto lc_length(lc_float3 v) noexcept { return lc_sqrt(lc_dot(v, v)); } -[[nodiscard]] __device__ inline auto lc_length(lc_float4 v) noexcept { return lc_sqrt(lc_dot(v, v)); } - -[[nodiscard]] __device__ inline auto lc_length_squared(lc_float2 v) noexcept { return lc_dot(v, v); } -[[nodiscard]] __device__ inline auto lc_length_squared(lc_float3 v) noexcept { return lc_dot(v, v); } -[[nodiscard]] __device__ inline auto lc_length_squared(lc_float4 v) noexcept { return lc_dot(v, v); } - -[[nodiscard]] __device__ inline auto lc_distance(lc_float2 a, lc_float2 b) noexcept { return lc_length(a - b); } -[[nodiscard]] __device__ inline auto lc_distance(lc_float3 a, lc_float3 b) noexcept { return lc_length(a - b); } -[[nodiscard]] __device__ inline auto lc_distance(lc_float4 a, lc_float4 b) noexcept { return lc_length(a - b); } - -[[nodiscard]] __device__ inline auto lc_distance_squared(lc_float2 a, lc_float2 b) noexcept { return lc_length_squared(a - b); } -[[nodiscard]] __device__ inline auto lc_distance_squared(lc_float3 a, lc_float3 b) noexcept { return lc_length_squared(a - b); } -[[nodiscard]] __device__ inline auto lc_distance_squared(lc_float4 a, lc_float4 b) noexcept { return lc_length_squared(a - b); } - -[[nodiscard]] __device__ inline auto lc_faceforward(lc_float3 n, lc_float3 i, lc_float3 n_ref) noexcept { return lc_select(-n, n, lc_dot(n_ref, i) < lc_float(0.f)); } - -[[nodiscard]] __device__ inline auto lc_normalize(lc_float2 v) noexcept { return v * lc_rsqrt(lc_dot(v, v)); } -[[nodiscard]] __device__ inline auto lc_normalize(lc_float3 v) noexcept { return v * lc_rsqrt(lc_dot(v, v)); } -[[nodiscard]] __device__ inline auto lc_normalize(lc_float4 v) noexcept { return v * lc_rsqrt(lc_dot(v, v)); } - -[[nodiscard]] __device__ inline constexpr auto lc_cross(lc_half3 u, lc_half3 v) noexcept { - return lc_make_half3(u.y * v.z - v.y * u.z, - u.z * v.x - v.z * u.x, - u.x * v.y - v.x * u.y); -} - -[[nodiscard]] __device__ inline auto lc_dot(lc_half2 a, lc_half2 b) noexcept { - return a.x * b.x + a.y * b.y; -} -[[nodiscard]] __device__ inline auto lc_dot(lc_half3 a, lc_half3 b) noexcept { - return a.x * b.x + a.y * b.y + a.z * b.z; -} -[[nodiscard]] __device__ inline auto lc_dot(lc_half4 a, lc_half4 b) noexcept { - return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; -} - -[[nodiscard]] __device__ inline auto lc_length(lc_half2 v) noexcept { return lc_sqrt(lc_dot(v, v)); } -[[nodiscard]] __device__ inline auto lc_length(lc_half3 v) noexcept { return lc_sqrt(lc_dot(v, v)); } -[[nodiscard]] __device__ inline auto lc_length(lc_half4 v) noexcept { return lc_sqrt(lc_dot(v, v)); } - -[[nodiscard]] __device__ inline auto lc_length_squared(lc_half2 v) noexcept { return lc_dot(v, v); } -[[nodiscard]] __device__ inline auto lc_length_squared(lc_half3 v) noexcept { return lc_dot(v, v); } -[[nodiscard]] __device__ inline auto lc_length_squared(lc_half4 v) noexcept { return lc_dot(v, v); } - -[[nodiscard]] __device__ inline auto lc_distance(lc_half2 a, lc_half2 b) noexcept { return lc_length(a - b); } -[[nodiscard]] __device__ inline auto lc_distance(lc_half3 a, lc_half3 b) noexcept { return lc_length(a - b); } -[[nodiscard]] __device__ inline auto lc_distance(lc_half4 a, lc_half4 b) noexcept { return lc_length(a - b); } - -[[nodiscard]] __device__ inline auto lc_distance_squared(lc_half2 a, lc_half2 b) noexcept { return lc_length_squared(a - b); } -[[nodiscard]] __device__ inline auto lc_distance_squared(lc_half3 a, lc_half3 b) noexcept { return lc_length_squared(a - b); } -[[nodiscard]] __device__ inline auto lc_distance_squared(lc_half4 a, lc_half4 b) noexcept { return lc_length_squared(a - b); } - -[[nodiscard]] __device__ inline auto lc_faceforward(lc_half3 n, lc_half3 i, lc_half3 n_ref) noexcept { return lc_select(-n, n, lc_dot(n_ref, i) < lc_half(0.f)); } - -[[nodiscard]] __device__ inline auto lc_normalize(lc_half2 v) noexcept { return v * lc_rsqrt(lc_dot(v, v)); } -[[nodiscard]] __device__ inline auto lc_normalize(lc_half3 v) noexcept { return v * lc_rsqrt(lc_dot(v, v)); } -[[nodiscard]] __device__ inline auto lc_normalize(lc_half4 v) noexcept { return v * lc_rsqrt(lc_dot(v, v)); } - -[[nodiscard]] __device__ inline constexpr auto lc_transpose(const lc_float2x2 m) noexcept { return lc_make_float2x2(m[0].x, m[1].x, m[0].y, m[1].y); } -[[nodiscard]] __device__ inline constexpr auto lc_transpose(const lc_float3x3 m) noexcept { return lc_make_float3x3(m[0].x, m[1].x, m[2].x, m[0].y, m[1].y, m[2].y, m[0].z, m[1].z, m[2].z); } -[[nodiscard]] __device__ inline constexpr auto lc_transpose(const lc_float4x4 m) noexcept { return lc_make_float4x4(m[0].x, m[1].x, m[2].x, m[3].x, m[0].y, m[1].y, m[2].y, m[3].y, m[0].z, m[1].z, m[2].z, m[3].z, m[0].w, m[1].w, m[2].w, m[3].w); } - -[[nodiscard]] __device__ inline constexpr auto lc_determinant(const lc_float2x2 m) noexcept { - return m[0][0] * m[1][1] - m[1][0] * m[0][1]; -} - -[[nodiscard]] __device__ constexpr auto lc_determinant(const lc_float3x3 m) noexcept {// from GLM - return m[0].x * (m[1].y * m[2].z - m[2].y * m[1].z) - - m[1].x * (m[0].y * m[2].z - m[2].y * m[0].z) - + m[2].x * (m[0].y * m[1].z - m[1].y * m[0].z); -} - -[[nodiscard]] __device__ inline constexpr auto lc_determinant(const lc_float4x4 m) noexcept {// from GLM - const auto coef00 = m[2].z * m[3].w - m[3].z * m[2].w; - const auto coef02 = m[1].z * m[3].w - m[3].z * m[1].w; - const auto coef03 = m[1].z * m[2].w - m[2].z * m[1].w; - const auto coef04 = m[2].y * m[3].w - m[3].y * m[2].w; - const auto coef06 = m[1].y * m[3].w - m[3].y * m[1].w; - const auto coef07 = m[1].y * m[2].w - m[2].y * m[1].w; - const auto coef08 = m[2].y * m[3].z - m[3].y * m[2].z; - const auto coef10 = m[1].y * m[3].z - m[3].y * m[1].z; - const auto coef11 = m[1].y * m[2].z - m[2].y * m[1].z; - const auto coef12 = m[2].x * m[3].w - m[3].x * m[2].w; - const auto coef14 = m[1].x * m[3].w - m[3].x * m[1].w; - const auto coef15 = m[1].x * m[2].w - m[2].x * m[1].w; - const auto coef16 = m[2].x * m[3].z - m[3].x * m[2].z; - const auto coef18 = m[1].x * m[3].z - m[3].x * m[1].z; - const auto coef19 = m[1].x * m[2].z - m[2].x * m[1].z; - const auto coef20 = m[2].x * m[3].y - m[3].x * m[2].y; - const auto coef22 = m[1].x * m[3].y - m[3].x * m[1].y; - const auto coef23 = m[1].x * m[2].y - m[2].x * m[1].y; - const auto fac0 = lc_make_float4(coef00, coef00, coef02, coef03); - const auto fac1 = lc_make_float4(coef04, coef04, coef06, coef07); - const auto fac2 = lc_make_float4(coef08, coef08, coef10, coef11); - const auto fac3 = lc_make_float4(coef12, coef12, coef14, coef15); - const auto fac4 = lc_make_float4(coef16, coef16, coef18, coef19); - const auto fac5 = lc_make_float4(coef20, coef20, coef22, coef23); - const auto Vec0 = lc_make_float4(m[1].x, m[0].x, m[0].x, m[0].x); - const auto Vec1 = lc_make_float4(m[1].y, m[0].y, m[0].y, m[0].y); - const auto Vec2 = lc_make_float4(m[1].z, m[0].z, m[0].z, m[0].z); - const auto Vec3 = lc_make_float4(m[1].w, m[0].w, m[0].w, m[0].w); - const auto inv0 = Vec1 * fac0 - Vec2 * fac1 + Vec3 * fac2; - const auto inv1 = Vec0 * fac0 - Vec2 * fac3 + Vec3 * fac4; - const auto inv2 = Vec0 * fac1 - Vec1 * fac3 + Vec3 * fac5; - const auto inv3 = Vec0 * fac2 - Vec1 * fac4 + Vec2 * fac5; - constexpr auto sign_a = lc_make_float4(+1.0f, -1.0f, +1.0f, -1.0f); - constexpr auto sign_b = lc_make_float4(-1.0f, +1.0f, -1.0f, +1.0f); - const auto inv_0 = inv0 * sign_a; - const auto inv_1 = inv1 * sign_b; - const auto inv_2 = inv2 * sign_a; - const auto inv_3 = inv3 * sign_b; - const auto dot0 = m[0] * lc_make_float4(inv_0.x, inv_1.x, inv_2.x, inv_3.x); - return dot0.x + dot0.y + dot0.z + dot0.w; -} - -[[nodiscard]] __device__ inline constexpr auto lc_inverse(const lc_float2x2 m) noexcept { - const auto one_over_determinant = 1.0f / (m[0][0] * m[1][1] - m[1][0] * m[0][1]); - return lc_make_float2x2(m[1][1] * one_over_determinant, - - m[0][1] * one_over_determinant, - - m[1][0] * one_over_determinant, - + m[0][0] * one_over_determinant); -} - -[[nodiscard]] __device__ inline constexpr auto lc_inverse(const lc_float3x3 m) noexcept {// from GLM - const auto one_over_determinant = 1.0f - / (m[0].x * (m[1].y * m[2].z - m[2].y * m[1].z) - - m[1].x * (m[0].y * m[2].z - m[2].y * m[0].z) - + m[2].x * (m[0].y * m[1].z - m[1].y * m[0].z)); - return lc_make_float3x3( - (m[1].y * m[2].z - m[2].y * m[1].z) * one_over_determinant, - (m[2].y * m[0].z - m[0].y * m[2].z) * one_over_determinant, - (m[0].y * m[1].z - m[1].y * m[0].z) * one_over_determinant, - (m[2].x * m[1].z - m[1].x * m[2].z) * one_over_determinant, - (m[0].x * m[2].z - m[2].x * m[0].z) * one_over_determinant, - (m[1].x * m[0].z - m[0].x * m[1].z) * one_over_determinant, - (m[1].x * m[2].y - m[2].x * m[1].y) * one_over_determinant, - (m[2].x * m[0].y - m[0].x * m[2].y) * one_over_determinant, - (m[0].x * m[1].y - m[1].x * m[0].y) * one_over_determinant); -} - -[[nodiscard]] __device__ inline constexpr auto lc_inverse(const lc_float4x4 m) noexcept {// from GLM - const auto coef00 = m[2].z * m[3].w - m[3].z * m[2].w; - const auto coef02 = m[1].z * m[3].w - m[3].z * m[1].w; - const auto coef03 = m[1].z * m[2].w - m[2].z * m[1].w; - const auto coef04 = m[2].y * m[3].w - m[3].y * m[2].w; - const auto coef06 = m[1].y * m[3].w - m[3].y * m[1].w; - const auto coef07 = m[1].y * m[2].w - m[2].y * m[1].w; - const auto coef08 = m[2].y * m[3].z - m[3].y * m[2].z; - const auto coef10 = m[1].y * m[3].z - m[3].y * m[1].z; - const auto coef11 = m[1].y * m[2].z - m[2].y * m[1].z; - const auto coef12 = m[2].x * m[3].w - m[3].x * m[2].w; - const auto coef14 = m[1].x * m[3].w - m[3].x * m[1].w; - const auto coef15 = m[1].x * m[2].w - m[2].x * m[1].w; - const auto coef16 = m[2].x * m[3].z - m[3].x * m[2].z; - const auto coef18 = m[1].x * m[3].z - m[3].x * m[1].z; - const auto coef19 = m[1].x * m[2].z - m[2].x * m[1].z; - const auto coef20 = m[2].x * m[3].y - m[3].x * m[2].y; - const auto coef22 = m[1].x * m[3].y - m[3].x * m[1].y; - const auto coef23 = m[1].x * m[2].y - m[2].x * m[1].y; - const auto fac0 = lc_make_float4(coef00, coef00, coef02, coef03); - const auto fac1 = lc_make_float4(coef04, coef04, coef06, coef07); - const auto fac2 = lc_make_float4(coef08, coef08, coef10, coef11); - const auto fac3 = lc_make_float4(coef12, coef12, coef14, coef15); - const auto fac4 = lc_make_float4(coef16, coef16, coef18, coef19); - const auto fac5 = lc_make_float4(coef20, coef20, coef22, coef23); - const auto Vec0 = lc_make_float4(m[1].x, m[0].x, m[0].x, m[0].x); - const auto Vec1 = lc_make_float4(m[1].y, m[0].y, m[0].y, m[0].y); - const auto Vec2 = lc_make_float4(m[1].z, m[0].z, m[0].z, m[0].z); - const auto Vec3 = lc_make_float4(m[1].w, m[0].w, m[0].w, m[0].w); - const auto inv0 = Vec1 * fac0 - Vec2 * fac1 + Vec3 * fac2; - const auto inv1 = Vec0 * fac0 - Vec2 * fac3 + Vec3 * fac4; - const auto inv2 = Vec0 * fac1 - Vec1 * fac3 + Vec3 * fac5; - const auto inv3 = Vec0 * fac2 - Vec1 * fac4 + Vec2 * fac5; - constexpr auto sign_a = lc_make_float4(+1.0f, -1.0f, +1.0f, -1.0f); - constexpr auto sign_b = lc_make_float4(-1.0f, +1.0f, -1.0f, +1.0f); - const auto inv_0 = inv0 * sign_a; - const auto inv_1 = inv1 * sign_b; - const auto inv_2 = inv2 * sign_a; - const auto inv_3 = inv3 * sign_b; - const auto dot0 = m[0] * lc_make_float4(inv_0.x, inv_1.x, inv_2.x, inv_3.x); - const auto dot1 = dot0.x + dot0.y + dot0.z + dot0.w; - const auto one_over_determinant = 1.0f / dot1; - return lc_make_float4x4(inv_0 * one_over_determinant, - inv_1 * one_over_determinant, - inv_2 * one_over_determinant, - inv_3 * one_over_determinant); -} - -[[nodiscard]] __device__ inline auto lc_reflect(const lc_float3 v, const lc_float3 n) noexcept { - return v - 2.0f * lc_dot(v, n) * n; -} - -template -[[nodiscard]] __device__ inline auto lc_bit_cast(S s) noexcept { - static_assert(sizeof(D) == sizeof(S)); - return reinterpret_cast(s); -} -template -[[nodiscard]] __device__ inline constexpr auto lc_zero() noexcept { - return T{}; -} -template -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return T::one(); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_int(1); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_float(1.0f); -} -template<> -[[nodiscard]] __device__ inline auto lc_one() noexcept { - return lc_half(1.0f); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_uint(1u); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_long(1); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_ulong(1); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_short(1); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_ushort(1); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_byte(1); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_ubyte(1); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return true; -} -template -class lc_array { - -private: - T _data[N]; - -public: - template - __device__ constexpr lc_array(Elem... elem) noexcept : _data{elem...} {} - __device__ constexpr lc_array(lc_array &&) noexcept = default; - __device__ constexpr lc_array(const lc_array &) noexcept = default; - __device__ constexpr lc_array &operator=(lc_array &&) noexcept = default; - __device__ constexpr lc_array &operator=(const lc_array &) noexcept = default; - [[nodiscard]] __device__ T &operator[](size_t i) noexcept { return _data[i]; } - [[nodiscard]] __device__ T operator[](size_t i) const noexcept { return _data[i]; } - -public: - [[nodiscard]] __device__ static auto one() noexcept { - lc_array ret; - #pragma unroll - for (auto i = 0u; i < N; i++) { ret[i] = lc_one(); } - return ret; - } -}; - -[[nodiscard]] __device__ inline auto lc_mat_comp_mul(lc_float2x2 lhs, lc_float2x2 rhs) noexcept { - return lc_make_float2x2(lhs[0] * rhs[0], - lhs[1] * rhs[1]); -} - -[[nodiscard]] __device__ inline auto lc_mat_comp_mul(lc_float3x3 lhs, lc_float3x3 rhs) noexcept { - return lc_make_float3x3(lhs[0] * rhs[0], - lhs[1] * rhs[1], - lhs[2] * rhs[2]); -} - -[[nodiscard]] __device__ inline auto lc_mat_comp_mul(lc_float4x4 lhs, lc_float4x4 rhs) noexcept { - return lc_make_float4x4(lhs[0] * rhs[0], - lhs[1] * rhs[1], - lhs[2] * rhs[2], - lhs[3] * rhs[3]); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float2 v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float3 v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float4 v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half2 v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half3 v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half4 v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float2x2 v) noexcept { - v.cols[0] = lc_remove_nan(v.cols[0]); - v.cols[1] = lc_remove_nan(v.cols[1]); - return v; -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float3x3 v) noexcept { - v.cols[0] = lc_remove_nan(v.cols[0]); - v.cols[1] = lc_remove_nan(v.cols[1]); - v.cols[2] = lc_remove_nan(v.cols[2]); - return v; -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float4x4 v) noexcept { - v.cols[0] = lc_remove_nan(v.cols[0]); - v.cols[1] = lc_remove_nan(v.cols[1]); - v.cols[2] = lc_remove_nan(v.cols[2]); - v.cols[3] = lc_remove_nan(v.cols[3]); - return v; -} - -__device__ inline void lc_accumulate_grad(lc_float *dst, lc_float grad) noexcept { *dst = *dst + lc_remove_nan(grad); } -__device__ inline void lc_accumulate_grad(lc_float2x2 *dst, lc_float2x2 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } -__device__ inline void lc_accumulate_grad(lc_float3x3 *dst, lc_float3x3 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } -__device__ inline void lc_accumulate_grad(lc_float4x4 *dst, lc_float4x4 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } -__device__ inline void lc_accumulate_grad(lc_float2 *dst, lc_float2 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } -__device__ inline void lc_accumulate_grad(lc_float3 *dst, lc_float3 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } -__device__ inline void lc_accumulate_grad(lc_float4 *dst, lc_float4 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } -__device__ inline void lc_accumulate_grad(lc_half *dst, lc_half grad) noexcept { *dst = *dst + lc_remove_nan(grad); } -__device__ inline void lc_accumulate_grad(lc_half2 *dst, lc_half2 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } -__device__ inline void lc_accumulate_grad(lc_half3 *dst, lc_half3 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } -__device__ inline void lc_accumulate_grad(lc_half4 *dst, lc_half4 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } -__device__ inline void lc_accumulate_grad(lc_short *dst, lc_short grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_ushort *dst, lc_ushort grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_int *dst, lc_int grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_uint *dst, lc_uint grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_long *dst, lc_long grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_ulong *dst, lc_ulong grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_bool *dst, lc_bool grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_byte *dst, lc_byte grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_ubyte *dst, lc_ubyte grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_byte2 *dst, lc_byte2 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_byte3 *dst, lc_byte3 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_byte4 *dst, lc_byte4 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_ubyte2 *dst, lc_ubyte2 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_ubyte3 *dst, lc_ubyte3 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_ubyte4 *dst, lc_ubyte4 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_short2 *dst, lc_short2 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_short3 *dst, lc_short3 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_short4 *dst, lc_short4 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_ushort2 *dst, lc_ushort2 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_ushort3 *dst, lc_ushort3 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_ushort4 *dst, lc_ushort4 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_int2 *dst, lc_int2 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_int3 *dst, lc_int3 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_int4 *dst, lc_int4 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_uint2 *dst, lc_uint2 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_uint3 *dst, lc_uint3 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_uint4 *dst, lc_uint4 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_long2 *dst, lc_long2 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_long3 *dst, lc_long3 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_long4 *dst, lc_long4 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_ulong2 *dst, lc_ulong2 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_ulong3 *dst, lc_ulong3 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_ulong4 *dst, lc_ulong4 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_bool2 *dst, lc_bool2 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_bool3 *dst, lc_bool3 grad) noexcept {} -__device__ inline void lc_accumulate_grad(lc_bool4 *dst, lc_bool4 grad) noexcept {} -struct lc_user_data_t{}; constexpr lc_user_data_t _lc_user_data{}; -template struct element_type_{using type = void;}; -template using element_type = typename element_type_::type; - -template<> struct element_type_ { using type = lc_float; }; -template<> struct element_type_ { using type = lc_float; }; -template<> struct element_type_ { using type = lc_float; }; -template<> struct element_type_ { using type = lc_half; }; -template<> struct element_type_ { using type = lc_half; }; -template<> struct element_type_ { using type = lc_half; }; -template<> struct element_type_ { using type = lc_short; }; -template<> struct element_type_ { using type = lc_short; }; -template<> struct element_type_ { using type = lc_short; }; -template<> struct element_type_ { using type = lc_ushort; }; -template<> struct element_type_ { using type = lc_ushort; }; -template<> struct element_type_ { using type = lc_ushort; }; -template<> struct element_type_ { using type = lc_byte; }; -template<> struct element_type_ { using type = lc_byte; }; -template<> struct element_type_ { using type = lc_byte; }; -template<> struct element_type_ { using type = lc_ubyte; }; -template<> struct element_type_ { using type = lc_ubyte; }; -template<> struct element_type_ { using type = lc_ubyte; }; -template<> struct element_type_ { using type = lc_int; }; -template<> struct element_type_ { using type = lc_int; }; -template<> struct element_type_ { using type = lc_int; }; -template<> struct element_type_ { using type = lc_uint; }; -template<> struct element_type_ { using type = lc_uint; }; -template<> struct element_type_ { using type = lc_uint; }; -template<> struct element_type_ { using type = lc_long; }; -template<> struct element_type_ { using type = lc_long; }; -template<> struct element_type_ { using type = lc_long; }; -template<> struct element_type_ { using type = lc_ulong; }; -template<> struct element_type_ { using type = lc_ulong; }; -template<> struct element_type_ { using type = lc_ulong; }; - -template -__device__ inline void lc_accumulate_grad(lc_array *dst, lc_array grad) noexcept { - #pragma unroll - for (auto i = 0u; i < N; i++) { lc_accumulate_grad(&(*dst)[i], grad[i]); } -} +using lc_byte = char; +using lc_ubyte = unsigned char; +using lc_short = short; +using lc_ushort = unsigned short; +using lc_int = int; +using lc_uint = unsigned int; +using lc_half = half; +using lc_float = float; +using lc_bool = bool; +using lc_long = long long; +using lc_ulong = unsigned long long; + +[[nodiscard]] __device__ inline bool isinf_impl(lc_float x) noexcept { + auto u = __float_as_int(x); + return u == 0x7f800000u | u == 0xff800000u; +} +[[nodiscard]] __device__ inline bool isnan_impl(lc_float x) noexcept { + auto u = __float_as_int(x); + return ((u & 0x7F800000u) == 0x7F800000u) & ((u & 0x7FFFFFu) != 0u); +} +[[nodiscard]] __device__ inline lc_float powi_impl(lc_float x, lc_int y) noexcept { + lc_float r = 1.0f; + auto is_y_neg = y < 0; + auto y_abs = is_y_neg ? -y : y; + + while (y_abs) { + if (y_abs & 1) r *= x; + x *= x; + y_abs >>= 1; + } + return is_y_neg ? 1.0f / r : r; +} +[[nodiscard]] __device__ inline lc_float powf_impl(lc_float x, lc_float y) noexcept { + auto y_int = static_cast(y); + return y_int == y ? powi_impl(x, y_int) : powf(x, y); +} + +struct alignas(2) lc_byte2 { + lc_byte x, y; + __device__ inline constexpr lc_byte2() noexcept + : x{}, y{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_byte2{}; } + __device__ inline constexpr static auto one() noexcept { return lc_byte2{1, 1}; } + __device__ inline explicit constexpr lc_byte2(lc_byte s) noexcept + : x{s}, y{s} {} + __device__ inline constexpr lc_byte2(lc_byte x, lc_byte y) noexcept + : x{x}, y{y} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(4) lc_byte3 { + lc_byte x, y, z; + __device__ inline constexpr lc_byte3() noexcept + : x{}, y{}, z{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_byte3{}; } + __device__ inline constexpr static auto one() noexcept { return lc_byte3{1, 1, 1}; } + __device__ inline explicit constexpr lc_byte3(lc_byte s) noexcept + : x{s}, y{s}, z{s} {} + __device__ inline constexpr lc_byte3(lc_byte x, lc_byte y, lc_byte z) noexcept + : x{x}, y{y}, z{z} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(4) lc_byte4 { + lc_byte x, y, z, w; + __device__ inline constexpr lc_byte4() noexcept + : x{}, y{}, z{}, w{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_byte4{}; } + __device__ inline constexpr static auto one() noexcept { return lc_byte4{1, 1, 1, 1}; } + __device__ inline explicit constexpr lc_byte4(lc_byte s) noexcept + : x{s}, y{s}, z{s}, w{s} {} + __device__ inline constexpr lc_byte4(lc_byte x, lc_byte y, lc_byte z, lc_byte w) noexcept + : x{x}, y{y}, z{z}, w{w} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(2) lc_ubyte2 { + lc_ubyte x, y; + __device__ inline constexpr lc_ubyte2() noexcept + : x{}, y{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_ubyte2{}; } + __device__ inline constexpr static auto one() noexcept { return lc_ubyte2{1, 1}; } + __device__ inline explicit constexpr lc_ubyte2(lc_ubyte s) noexcept + : x{s}, y{s} {} + __device__ inline constexpr lc_ubyte2(lc_ubyte x, lc_ubyte y) noexcept + : x{x}, y{y} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(4) lc_ubyte3 { + lc_ubyte x, y, z; + __device__ inline constexpr lc_ubyte3() noexcept + : x{}, y{}, z{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_ubyte3{}; } + __device__ inline constexpr static auto one() noexcept { return lc_ubyte3{1, 1, 1}; } + __device__ inline explicit constexpr lc_ubyte3(lc_ubyte s) noexcept + : x{s}, y{s}, z{s} {} + __device__ inline constexpr lc_ubyte3(lc_ubyte x, lc_ubyte y, lc_ubyte z) noexcept + : x{x}, y{y}, z{z} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(4) lc_ubyte4 { + lc_ubyte x, y, z, w; + __device__ inline constexpr lc_ubyte4() noexcept + : x{}, y{}, z{}, w{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_ubyte4{}; } + __device__ inline constexpr static auto one() noexcept { return lc_ubyte4{1, 1, 1, 1}; } + __device__ inline explicit constexpr lc_ubyte4(lc_ubyte s) noexcept + : x{s}, y{s}, z{s}, w{s} {} + __device__ inline constexpr lc_ubyte4(lc_ubyte x, lc_ubyte y, lc_ubyte z, lc_ubyte w) noexcept + : x{x}, y{y}, z{z}, w{w} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(4) lc_short2 { + lc_short x, y; + __device__ inline constexpr lc_short2() noexcept + : x{}, y{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_short2{}; } + __device__ inline constexpr static auto one() noexcept { return lc_short2{1, 1}; } + __device__ inline explicit constexpr lc_short2(lc_short s) noexcept + : x{s}, y{s} {} + __device__ inline constexpr lc_short2(lc_short x, lc_short y) noexcept + : x{x}, y{y} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(8) lc_short3 { + lc_short x, y, z; + __device__ inline constexpr lc_short3() noexcept + : x{}, y{}, z{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_short3{}; } + __device__ inline constexpr static auto one() noexcept { return lc_short3{1, 1, 1}; } + __device__ inline explicit constexpr lc_short3(lc_short s) noexcept + : x{s}, y{s}, z{s} {} + __device__ inline constexpr lc_short3(lc_short x, lc_short y, lc_short z) noexcept + : x{x}, y{y}, z{z} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(8) lc_short4 { + lc_short x, y, z, w; + __device__ inline constexpr lc_short4() noexcept + : x{}, y{}, z{}, w{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_short4{}; } + __device__ inline constexpr static auto one() noexcept { return lc_short4{1, 1, 1, 1}; } + __device__ inline explicit constexpr lc_short4(lc_short s) noexcept + : x{s}, y{s}, z{s}, w{s} {} + __device__ inline constexpr lc_short4(lc_short x, lc_short y, lc_short z, lc_short w) noexcept + : x{x}, y{y}, z{z}, w{w} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(4) lc_ushort2 { + lc_ushort x, y; + __device__ inline constexpr lc_ushort2() noexcept + : x{}, y{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_ushort2{}; } + __device__ inline constexpr static auto one() noexcept { return lc_ushort2{1, 1}; } + __device__ inline explicit constexpr lc_ushort2(lc_ushort s) noexcept + : x{s}, y{s} {} + __device__ inline constexpr lc_ushort2(lc_ushort x, lc_ushort y) noexcept + : x{x}, y{y} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(8) lc_ushort3 { + lc_ushort x, y, z; + __device__ inline constexpr lc_ushort3() noexcept + : x{}, y{}, z{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_ushort3{}; } + __device__ inline constexpr static auto one() noexcept { return lc_ushort3{1, 1, 1}; } + __device__ inline explicit constexpr lc_ushort3(lc_ushort s) noexcept + : x{s}, y{s}, z{s} {} + __device__ inline constexpr lc_ushort3(lc_ushort x, lc_ushort y, lc_ushort z) noexcept + : x{x}, y{y}, z{z} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(8) lc_ushort4 { + lc_ushort x, y, z, w; + __device__ inline constexpr lc_ushort4() noexcept + : x{}, y{}, z{}, w{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_ushort4{}; } + __device__ inline constexpr static auto one() noexcept { return lc_ushort4{1, 1, 1, 1}; } + __device__ inline explicit constexpr lc_ushort4(lc_ushort s) noexcept + : x{s}, y{s}, z{s}, w{s} {} + __device__ inline constexpr lc_ushort4(lc_ushort x, lc_ushort y, lc_ushort z, lc_ushort w) noexcept + : x{x}, y{y}, z{z}, w{w} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(8) lc_int2 { + lc_int x, y; + __device__ inline constexpr lc_int2() noexcept + : x{}, y{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_int2{}; } + __device__ inline constexpr static auto one() noexcept { return lc_int2{1, 1}; } + __device__ inline explicit constexpr lc_int2(lc_int s) noexcept + : x{s}, y{s} {} + __device__ inline constexpr lc_int2(lc_int x, lc_int y) noexcept + : x{x}, y{y} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(16) lc_int3 { + lc_int x, y, z; + __device__ inline constexpr lc_int3() noexcept + : x{}, y{}, z{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_int3{}; } + __device__ inline constexpr static auto one() noexcept { return lc_int3{1, 1, 1}; } + __device__ inline explicit constexpr lc_int3(lc_int s) noexcept + : x{s}, y{s}, z{s} {} + __device__ inline constexpr lc_int3(lc_int x, lc_int y, lc_int z) noexcept + : x{x}, y{y}, z{z} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(16) lc_int4 { + lc_int x, y, z, w; + __device__ inline constexpr lc_int4() noexcept + : x{}, y{}, z{}, w{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_int4{}; } + __device__ inline constexpr static auto one() noexcept { return lc_int4{1, 1, 1, 1}; } + __device__ inline explicit constexpr lc_int4(lc_int s) noexcept + : x{s}, y{s}, z{s}, w{s} {} + __device__ inline constexpr lc_int4(lc_int x, lc_int y, lc_int z, lc_int w) noexcept + : x{x}, y{y}, z{z}, w{w} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(8) lc_uint2 { + lc_uint x, y; + __device__ inline constexpr lc_uint2() noexcept + : x{}, y{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_uint2{}; } + __device__ inline constexpr static auto one() noexcept { return lc_uint2{1, 1}; } + __device__ inline explicit constexpr lc_uint2(lc_uint s) noexcept + : x{s}, y{s} {} + __device__ inline constexpr lc_uint2(lc_uint x, lc_uint y) noexcept + : x{x}, y{y} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(16) lc_uint3 { + lc_uint x, y, z; + __device__ inline constexpr lc_uint3() noexcept + : x{}, y{}, z{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_uint3{}; } + __device__ inline constexpr static auto one() noexcept { return lc_uint3{1, 1, 1}; } + __device__ inline explicit constexpr lc_uint3(lc_uint s) noexcept + : x{s}, y{s}, z{s} {} + __device__ inline constexpr lc_uint3(lc_uint x, lc_uint y, lc_uint z) noexcept + : x{x}, y{y}, z{z} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(16) lc_uint4 { + lc_uint x, y, z, w; + __device__ inline constexpr lc_uint4() noexcept + : x{}, y{}, z{}, w{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_uint4{}; } + __device__ inline constexpr static auto one() noexcept { return lc_uint4{1, 1, 1, 1}; } + __device__ inline explicit constexpr lc_uint4(lc_uint s) noexcept + : x{s}, y{s}, z{s}, w{s} {} + __device__ inline constexpr lc_uint4(lc_uint x, lc_uint y, lc_uint z, lc_uint w) noexcept + : x{x}, y{y}, z{z}, w{w} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(4) lc_half2 { + lc_half x, y; + __device__ inline constexpr lc_half2() noexcept + : x{}, y{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_half2{}; } + __device__ inline constexpr static auto one() noexcept { return lc_half2{1, 1}; } + __device__ inline explicit constexpr lc_half2(lc_half s) noexcept + : x{s}, y{s} {} + __device__ inline constexpr lc_half2(lc_half x, lc_half y) noexcept + : x{x}, y{y} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(8) lc_half3 { + lc_half x, y, z; + __device__ inline constexpr lc_half3() noexcept + : x{}, y{}, z{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_half3{}; } + __device__ inline constexpr static auto one() noexcept { return lc_half3{1, 1, 1}; } + __device__ inline explicit constexpr lc_half3(lc_half s) noexcept + : x{s}, y{s}, z{s} {} + __device__ inline constexpr lc_half3(lc_half x, lc_half y, lc_half z) noexcept + : x{x}, y{y}, z{z} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(8) lc_half4 { + lc_half x, y, z, w; + __device__ inline constexpr lc_half4() noexcept + : x{}, y{}, z{}, w{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_half4{}; } + __device__ inline constexpr static auto one() noexcept { return lc_half4{1, 1, 1, 1}; } + __device__ inline explicit constexpr lc_half4(lc_half s) noexcept + : x{s}, y{s}, z{s}, w{s} {} + __device__ inline constexpr lc_half4(lc_half x, lc_half y, lc_half z, lc_half w) noexcept + : x{x}, y{y}, z{z}, w{w} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(8) lc_float2 { + lc_float x, y; + __device__ inline constexpr lc_float2() noexcept + : x{}, y{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_float2{}; } + __device__ inline constexpr static auto one() noexcept { return lc_float2{1, 1}; } + __device__ inline explicit constexpr lc_float2(lc_float s) noexcept + : x{s}, y{s} {} + __device__ inline constexpr lc_float2(lc_float x, lc_float y) noexcept + : x{x}, y{y} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(16) lc_float3 { + lc_float x, y, z; + __device__ inline constexpr lc_float3() noexcept + : x{}, y{}, z{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_float3{}; } + __device__ inline constexpr static auto one() noexcept { return lc_float3{1, 1, 1}; } + __device__ inline explicit constexpr lc_float3(lc_float s) noexcept + : x{s}, y{s}, z{s} {} + __device__ inline constexpr lc_float3(lc_float x, lc_float y, lc_float z) noexcept + : x{x}, y{y}, z{z} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(16) lc_float4 { + lc_float x, y, z, w; + __device__ inline constexpr lc_float4() noexcept + : x{}, y{}, z{}, w{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_float4{}; } + __device__ inline constexpr static auto one() noexcept { return lc_float4{1, 1, 1, 1}; } + __device__ inline explicit constexpr lc_float4(lc_float s) noexcept + : x{s}, y{s}, z{s}, w{s} {} + __device__ inline constexpr lc_float4(lc_float x, lc_float y, lc_float z, lc_float w) noexcept + : x{x}, y{y}, z{z}, w{w} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(2) lc_bool2 { + lc_bool x, y; + __device__ inline constexpr lc_bool2() noexcept + : x{}, y{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_bool2{}; } + __device__ inline constexpr static auto one() noexcept { return lc_bool2{1, 1}; } + __device__ inline explicit constexpr lc_bool2(lc_bool s) noexcept + : x{s}, y{s} {} + __device__ inline constexpr lc_bool2(lc_bool x, lc_bool y) noexcept + : x{x}, y{y} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(4) lc_bool3 { + lc_bool x, y, z; + __device__ inline constexpr lc_bool3() noexcept + : x{}, y{}, z{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_bool3{}; } + __device__ inline constexpr static auto one() noexcept { return lc_bool3{1, 1, 1}; } + __device__ inline explicit constexpr lc_bool3(lc_bool s) noexcept + : x{s}, y{s}, z{s} {} + __device__ inline constexpr lc_bool3(lc_bool x, lc_bool y, lc_bool z) noexcept + : x{x}, y{y}, z{z} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(4) lc_bool4 { + lc_bool x, y, z, w; + __device__ inline constexpr lc_bool4() noexcept + : x{}, y{}, z{}, w{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_bool4{}; } + __device__ inline constexpr static auto one() noexcept { return lc_bool4{1, 1, 1, 1}; } + __device__ inline explicit constexpr lc_bool4(lc_bool s) noexcept + : x{s}, y{s}, z{s}, w{s} {} + __device__ inline constexpr lc_bool4(lc_bool x, lc_bool y, lc_bool z, lc_bool w) noexcept + : x{x}, y{y}, z{z}, w{w} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(16) lc_long2 { + lc_long x, y; + __device__ inline constexpr lc_long2() noexcept + : x{}, y{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_long2{}; } + __device__ inline constexpr static auto one() noexcept { return lc_long2{1, 1}; } + __device__ inline explicit constexpr lc_long2(lc_long s) noexcept + : x{s}, y{s} {} + __device__ inline constexpr lc_long2(lc_long x, lc_long y) noexcept + : x{x}, y{y} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(16) lc_long3 { + lc_long x, y, z; + __device__ inline constexpr lc_long3() noexcept + : x{}, y{}, z{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_long3{}; } + __device__ inline constexpr static auto one() noexcept { return lc_long3{1, 1, 1}; } + __device__ inline explicit constexpr lc_long3(lc_long s) noexcept + : x{s}, y{s}, z{s} {} + __device__ inline constexpr lc_long3(lc_long x, lc_long y, lc_long z) noexcept + : x{x}, y{y}, z{z} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(16) lc_long4 { + lc_long x, y, z, w; + __device__ inline constexpr lc_long4() noexcept + : x{}, y{}, z{}, w{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_long4{}; } + __device__ inline constexpr static auto one() noexcept { return lc_long4{1, 1, 1, 1}; } + __device__ inline explicit constexpr lc_long4(lc_long s) noexcept + : x{s}, y{s}, z{s}, w{s} {} + __device__ inline constexpr lc_long4(lc_long x, lc_long y, lc_long z, lc_long w) noexcept + : x{x}, y{y}, z{z}, w{w} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(16) lc_ulong2 { + lc_ulong x, y; + __device__ inline constexpr lc_ulong2() noexcept + : x{}, y{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_ulong2{}; } + __device__ inline constexpr static auto one() noexcept { return lc_ulong2{1, 1}; } + __device__ inline explicit constexpr lc_ulong2(lc_ulong s) noexcept + : x{s}, y{s} {} + __device__ inline constexpr lc_ulong2(lc_ulong x, lc_ulong y) noexcept + : x{x}, y{y} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(16) lc_ulong3 { + lc_ulong x, y, z; + __device__ inline constexpr lc_ulong3() noexcept + : x{}, y{}, z{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_ulong3{}; } + __device__ inline constexpr static auto one() noexcept { return lc_ulong3{1, 1, 1}; } + __device__ inline explicit constexpr lc_ulong3(lc_ulong s) noexcept + : x{s}, y{s}, z{s} {} + __device__ inline constexpr lc_ulong3(lc_ulong x, lc_ulong y, lc_ulong z) noexcept + : x{x}, y{y}, z{z} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +struct alignas(16) lc_ulong4 { + lc_ulong x, y, z, w; + __device__ inline constexpr lc_ulong4() noexcept + : x{}, y{}, z{}, w{} {} + __device__ inline constexpr static auto zero() noexcept { return lc_ulong4{}; } + __device__ inline constexpr static auto one() noexcept { return lc_ulong4{1, 1, 1, 1}; } + __device__ inline explicit constexpr lc_ulong4(lc_ulong s) noexcept + : x{s}, y{s}, z{s}, w{s} {} + __device__ inline constexpr lc_ulong4(lc_ulong x, lc_ulong y, lc_ulong z, lc_ulong w) noexcept + : x{x}, y{y}, z{z}, w{w} {} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return (&x)[i]; } + __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return (&x)[i]; } +}; + +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_byte s = 0) noexcept { return lc_byte2{s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_byte x, lc_byte y) noexcept { return lc_byte2{x, y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_byte2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_byte3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_byte4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ubyte2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ubyte3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ubyte4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_short2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_short3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_short4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ushort2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ushort3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ushort4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_int2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_int3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_int4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_uint2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_uint3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_uint4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_half2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_half3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_half4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_float2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_float3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_float4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_bool2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_bool3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_bool4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_long2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_long3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_long4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ulong2 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ulong3 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte2(lc_ulong4 v) noexcept { return lc_byte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_byte3(lc_byte s = 0) noexcept { return lc_byte3{s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte3(lc_byte x, lc_byte y, lc_byte z) noexcept { return lc_byte3{x, y, z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte3(lc_byte x, lc_byte2 yz) noexcept { return lc_byte3{x, yz.x, yz.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte3(lc_byte2 xy, lc_byte z) noexcept { return lc_byte3{xy.x, xy.y, z}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_byte3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_byte4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_ubyte3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_ubyte4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_short3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_short4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_ushort3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_ushort4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_int3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_int4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_uint3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_uint4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_half3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_half4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_float3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_float4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_bool3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_bool4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_long3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_long4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_ulong3 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_byte3(lc_ulong4 v) noexcept { return lc_byte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_byte s = 0) noexcept { return lc_byte4{s, s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte4(lc_byte x, lc_byte y, lc_byte z, lc_byte w) noexcept { return lc_byte4{x, y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte4(lc_byte x, lc_byte y, lc_byte2 zw) noexcept { return lc_byte4{x, y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte4(lc_byte x, lc_byte2 yz, lc_byte w) noexcept { return lc_byte4{x, yz.x, yz.y, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte4(lc_byte2 xy, lc_byte z, lc_byte w) noexcept { return lc_byte4{xy.x, xy.y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte4(lc_byte2 xy, lc_byte2 zw) noexcept { return lc_byte4{xy.x, xy.y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte4(lc_byte x, lc_byte3 yzw) noexcept { return lc_byte4{x, yzw.x, yzw.y, yzw.z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_byte4(lc_byte3 xyz, lc_byte w) noexcept { return lc_byte4{xyz.x, xyz.y, xyz.z, w}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_byte4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_ubyte4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_short4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_ushort4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_int4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_uint4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_half4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_float4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_bool4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_long4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_byte4(lc_ulong4 v) noexcept { return lc_byte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } + +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ubyte s = 0) noexcept { return lc_ubyte2{s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ubyte x, lc_ubyte y) noexcept { return lc_ubyte2{x, y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_byte2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_byte3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_byte4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ubyte2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ubyte3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ubyte4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_short2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_short3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_short4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ushort2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ushort3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ushort4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_int2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_int3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_int4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_uint2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_uint3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_uint4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_half2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_half3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_half4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_float2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_float3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_float4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_bool2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_bool3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_bool4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_long2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_long3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_long4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ulong2 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ulong3 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte2(lc_ulong4 v) noexcept { return lc_ubyte2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte3(lc_ubyte s = 0) noexcept { return lc_ubyte3{s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte3(lc_ubyte x, lc_ubyte y, lc_ubyte z) noexcept { return lc_ubyte3{x, y, z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte3(lc_ubyte x, lc_ubyte2 yz) noexcept { return lc_ubyte3{x, yz.x, yz.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte3(lc_ubyte2 xy, lc_ubyte z) noexcept { return lc_ubyte3{xy.x, xy.y, z}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_byte3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_byte4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_ubyte3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_ubyte4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_short3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_short4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_ushort3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_ushort4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_int3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_int4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_uint3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_uint4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_half3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_half4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_float3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_float4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_bool3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_bool4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_long3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_long4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_ulong3 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ubyte3(lc_ulong4 v) noexcept { return lc_ubyte3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_ubyte s = 0) noexcept { return lc_ubyte4{s, s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte4(lc_ubyte x, lc_ubyte y, lc_ubyte z, lc_ubyte w) noexcept { return lc_ubyte4{x, y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte4(lc_ubyte x, lc_ubyte y, lc_ubyte2 zw) noexcept { return lc_ubyte4{x, y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte4(lc_ubyte x, lc_ubyte2 yz, lc_ubyte w) noexcept { return lc_ubyte4{x, yz.x, yz.y, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte4(lc_ubyte2 xy, lc_ubyte z, lc_ubyte w) noexcept { return lc_ubyte4{xy.x, xy.y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte4(lc_ubyte2 xy, lc_ubyte2 zw) noexcept { return lc_ubyte4{xy.x, xy.y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte4(lc_ubyte x, lc_ubyte3 yzw) noexcept { return lc_ubyte4{x, yzw.x, yzw.y, yzw.z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ubyte4(lc_ubyte3 xyz, lc_ubyte w) noexcept { return lc_ubyte4{xyz.x, xyz.y, xyz.z, w}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_byte4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_ubyte4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_short4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_ushort4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_int4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_uint4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_half4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_float4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_bool4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_long4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ubyte4(lc_ulong4 v) noexcept { return lc_ubyte4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } + +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_short s = 0) noexcept { return lc_short2{s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_short x, lc_short y) noexcept { return lc_short2{x, y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_byte2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_byte3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_byte4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ubyte2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ubyte3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ubyte4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_short2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_short3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_short4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ushort2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ushort3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ushort4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_int2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_int3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_int4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_uint2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_uint3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_uint4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_half2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_half3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_half4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_float2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_float3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_float4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_bool2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_bool3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_bool4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_long2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_long3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_long4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ulong2 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ulong3 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short2(lc_ulong4 v) noexcept { return lc_short2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_short3(lc_short s = 0) noexcept { return lc_short3{s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short3(lc_short x, lc_short y, lc_short z) noexcept { return lc_short3{x, y, z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short3(lc_short x, lc_short2 yz) noexcept { return lc_short3{x, yz.x, yz.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short3(lc_short2 xy, lc_short z) noexcept { return lc_short3{xy.x, xy.y, z}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_byte3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_byte4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_ubyte3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_ubyte4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_short3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_short4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_ushort3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_ushort4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_int3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_int4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_uint3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_uint4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_half3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_half4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_float3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_float4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_bool3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_bool4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_long3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_long4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_ulong3 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_short3(lc_ulong4 v) noexcept { return lc_short3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_short s = 0) noexcept { return lc_short4{s, s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short4(lc_short x, lc_short y, lc_short z, lc_short w) noexcept { return lc_short4{x, y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short4(lc_short x, lc_short y, lc_short2 zw) noexcept { return lc_short4{x, y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short4(lc_short x, lc_short2 yz, lc_short w) noexcept { return lc_short4{x, yz.x, yz.y, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short4(lc_short2 xy, lc_short z, lc_short w) noexcept { return lc_short4{xy.x, xy.y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short4(lc_short2 xy, lc_short2 zw) noexcept { return lc_short4{xy.x, xy.y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short4(lc_short x, lc_short3 yzw) noexcept { return lc_short4{x, yzw.x, yzw.y, yzw.z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_short4(lc_short3 xyz, lc_short w) noexcept { return lc_short4{xyz.x, xyz.y, xyz.z, w}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_byte4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_ubyte4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_short4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_ushort4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_int4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_uint4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_half4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_float4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_bool4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_long4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_short4(lc_ulong4 v) noexcept { return lc_short4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } + +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ushort s = 0) noexcept { return lc_ushort2{s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ushort x, lc_ushort y) noexcept { return lc_ushort2{x, y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_byte2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_byte3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_byte4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ubyte2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ubyte3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ubyte4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_short2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_short3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_short4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ushort2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ushort3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ushort4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_int2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_int3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_int4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_uint2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_uint3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_uint4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_half2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_half3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_half4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_float2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_float3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_float4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_bool2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_bool3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_bool4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_long2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_long3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_long4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ulong2 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ulong3 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort2(lc_ulong4 v) noexcept { return lc_ushort2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ushort3(lc_ushort s = 0) noexcept { return lc_ushort3{s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort3(lc_ushort x, lc_ushort y, lc_ushort z) noexcept { return lc_ushort3{x, y, z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort3(lc_ushort x, lc_ushort2 yz) noexcept { return lc_ushort3{x, yz.x, yz.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort3(lc_ushort2 xy, lc_ushort z) noexcept { return lc_ushort3{xy.x, xy.y, z}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_byte3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_byte4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_ubyte3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_ubyte4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_short3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_short4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_ushort3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_ushort4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_int3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_int4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_uint3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_uint4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_half3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_half4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_float3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_float4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_bool3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_bool4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_long3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_long4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_ulong3 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ushort3(lc_ulong4 v) noexcept { return lc_ushort3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_ushort s = 0) noexcept { return lc_ushort4{s, s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort4(lc_ushort x, lc_ushort y, lc_ushort z, lc_ushort w) noexcept { return lc_ushort4{x, y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort4(lc_ushort x, lc_ushort y, lc_ushort2 zw) noexcept { return lc_ushort4{x, y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort4(lc_ushort x, lc_ushort2 yz, lc_ushort w) noexcept { return lc_ushort4{x, yz.x, yz.y, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort4(lc_ushort2 xy, lc_ushort z, lc_ushort w) noexcept { return lc_ushort4{xy.x, xy.y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort4(lc_ushort2 xy, lc_ushort2 zw) noexcept { return lc_ushort4{xy.x, xy.y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort4(lc_ushort x, lc_ushort3 yzw) noexcept { return lc_ushort4{x, yzw.x, yzw.y, yzw.z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ushort4(lc_ushort3 xyz, lc_ushort w) noexcept { return lc_ushort4{xyz.x, xyz.y, xyz.z, w}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_byte4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_ubyte4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_short4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_ushort4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_int4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_uint4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_half4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_float4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_bool4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_long4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ushort4(lc_ulong4 v) noexcept { return lc_ushort4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } + +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_int s = 0) noexcept { return lc_int2{s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_int x, lc_int y) noexcept { return lc_int2{x, y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_byte2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_byte3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_byte4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ubyte2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ubyte3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ubyte4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_short2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_short3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_short4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ushort2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ushort3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ushort4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_int2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_int3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_int4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_uint2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_uint3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_uint4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_half2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_half3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_half4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_float2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_float3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_float4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_bool2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_bool3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_bool4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_long2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_long3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_long4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ulong2 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ulong3 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int2(lc_ulong4 v) noexcept { return lc_int2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_int3(lc_int s = 0) noexcept { return lc_int3{s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int3(lc_int x, lc_int y, lc_int z) noexcept { return lc_int3{x, y, z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int3(lc_int x, lc_int2 yz) noexcept { return lc_int3{x, yz.x, yz.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int3(lc_int2 xy, lc_int z) noexcept { return lc_int3{xy.x, xy.y, z}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_byte3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_byte4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_ubyte3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_ubyte4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_short3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_short4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_ushort3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_ushort4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_int3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_int4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_uint3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_uint4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_half3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_half4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_float3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_float4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_bool3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_bool4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_long3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_long4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_ulong3 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_int3(lc_ulong4 v) noexcept { return lc_int3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_int s = 0) noexcept { return lc_int4{s, s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int4(lc_int x, lc_int y, lc_int z, lc_int w) noexcept { return lc_int4{x, y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int4(lc_int x, lc_int y, lc_int2 zw) noexcept { return lc_int4{x, y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int4(lc_int x, lc_int2 yz, lc_int w) noexcept { return lc_int4{x, yz.x, yz.y, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int4(lc_int2 xy, lc_int z, lc_int w) noexcept { return lc_int4{xy.x, xy.y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int4(lc_int2 xy, lc_int2 zw) noexcept { return lc_int4{xy.x, xy.y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int4(lc_int x, lc_int3 yzw) noexcept { return lc_int4{x, yzw.x, yzw.y, yzw.z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_int4(lc_int3 xyz, lc_int w) noexcept { return lc_int4{xyz.x, xyz.y, xyz.z, w}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_byte4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_ubyte4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_short4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_ushort4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_int4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_uint4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_half4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_float4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_bool4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_long4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_int4(lc_ulong4 v) noexcept { return lc_int4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } + +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_uint s = 0) noexcept { return lc_uint2{s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_uint x, lc_uint y) noexcept { return lc_uint2{x, y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_byte2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_byte3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_byte4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ubyte2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ubyte3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ubyte4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_short2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_short3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_short4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ushort2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ushort3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ushort4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_int2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_int3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_int4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_uint2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_uint3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_uint4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_half2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_half3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_half4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_float2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_float3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_float4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_bool2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_bool3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_bool4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_long2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_long3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_long4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ulong2 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ulong3 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint2(lc_ulong4 v) noexcept { return lc_uint2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_uint3(lc_uint s = 0) noexcept { return lc_uint3{s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint3(lc_uint x, lc_uint y, lc_uint z) noexcept { return lc_uint3{x, y, z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint3(lc_uint x, lc_uint2 yz) noexcept { return lc_uint3{x, yz.x, yz.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint3(lc_uint2 xy, lc_uint z) noexcept { return lc_uint3{xy.x, xy.y, z}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_byte3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_byte4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_ubyte3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_ubyte4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_short3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_short4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_ushort3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_ushort4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_int3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_int4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_uint3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_uint4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_half3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_half4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_float3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_float4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_bool3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_bool4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_long3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_long4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_ulong3 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_uint3(lc_ulong4 v) noexcept { return lc_uint3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_uint s = 0) noexcept { return lc_uint4{s, s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint4(lc_uint x, lc_uint y, lc_uint z, lc_uint w) noexcept { return lc_uint4{x, y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint4(lc_uint x, lc_uint y, lc_uint2 zw) noexcept { return lc_uint4{x, y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint4(lc_uint x, lc_uint2 yz, lc_uint w) noexcept { return lc_uint4{x, yz.x, yz.y, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint4(lc_uint2 xy, lc_uint z, lc_uint w) noexcept { return lc_uint4{xy.x, xy.y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint4(lc_uint2 xy, lc_uint2 zw) noexcept { return lc_uint4{xy.x, xy.y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint4(lc_uint x, lc_uint3 yzw) noexcept { return lc_uint4{x, yzw.x, yzw.y, yzw.z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_uint4(lc_uint3 xyz, lc_uint w) noexcept { return lc_uint4{xyz.x, xyz.y, xyz.z, w}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_byte4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_ubyte4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_short4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_ushort4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_int4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_uint4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_half4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_float4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_bool4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_long4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_uint4(lc_ulong4 v) noexcept { return lc_uint4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } + +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_half s = 0) noexcept { return lc_half2{s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_half x, lc_half y) noexcept { return lc_half2{x, y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_byte2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_byte3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_byte4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ubyte2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ubyte3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ubyte4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_short2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_short3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_short4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ushort2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ushort3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ushort4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_int2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_int3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_int4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_uint2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_uint3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_uint4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_half2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_half3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_half4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_float2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_float3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_float4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_bool2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_bool3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_bool4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_long2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_long3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_long4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ulong2 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ulong3 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half2(lc_ulong4 v) noexcept { return lc_half2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_half3(lc_half s = 0) noexcept { return lc_half3{s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half3(lc_half x, lc_half y, lc_half z) noexcept { return lc_half3{x, y, z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half3(lc_half x, lc_half2 yz) noexcept { return lc_half3{x, yz.x, yz.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half3(lc_half2 xy, lc_half z) noexcept { return lc_half3{xy.x, xy.y, z}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_byte3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_byte4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_ubyte3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_ubyte4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_short3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_short4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_ushort3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_ushort4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_int3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_int4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_uint3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_uint4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_half3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_half4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_float3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_float4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_bool3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_bool4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_long3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_long4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_ulong3 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_half3(lc_ulong4 v) noexcept { return lc_half3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_half s = 0) noexcept { return lc_half4{s, s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half4(lc_half x, lc_half y, lc_half z, lc_half w) noexcept { return lc_half4{x, y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half4(lc_half x, lc_half y, lc_half2 zw) noexcept { return lc_half4{x, y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half4(lc_half x, lc_half2 yz, lc_half w) noexcept { return lc_half4{x, yz.x, yz.y, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half4(lc_half2 xy, lc_half z, lc_half w) noexcept { return lc_half4{xy.x, xy.y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half4(lc_half2 xy, lc_half2 zw) noexcept { return lc_half4{xy.x, xy.y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half4(lc_half x, lc_half3 yzw) noexcept { return lc_half4{x, yzw.x, yzw.y, yzw.z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_half4(lc_half3 xyz, lc_half w) noexcept { return lc_half4{xyz.x, xyz.y, xyz.z, w}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_byte4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_ubyte4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_short4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_ushort4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_int4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_uint4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_half4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_float4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_bool4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_long4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_half4(lc_ulong4 v) noexcept { return lc_half4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } + +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_float s = 0) noexcept { return lc_float2{s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_float x, lc_float y) noexcept { return lc_float2{x, y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_byte2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_byte3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_byte4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ubyte2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ubyte3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ubyte4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_short2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_short3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_short4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ushort2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ushort3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ushort4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_int2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_int3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_int4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_uint2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_uint3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_uint4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_half2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_half3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_half4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_float2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_float3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_float4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_bool2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_bool3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_bool4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_long2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_long3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_long4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ulong2 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ulong3 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2(lc_ulong4 v) noexcept { return lc_float2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_float3(lc_float s = 0) noexcept { return lc_float3{s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float3(lc_float x, lc_float y, lc_float z) noexcept { return lc_float3{x, y, z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float3(lc_float x, lc_float2 yz) noexcept { return lc_float3{x, yz.x, yz.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float3(lc_float2 xy, lc_float z) noexcept { return lc_float3{xy.x, xy.y, z}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_byte3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_byte4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_ubyte3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_ubyte4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_short3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_short4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_ushort3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_ushort4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_int3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_int4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_uint3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_uint4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_half3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_half4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_float3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_float4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_bool3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_bool4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_long3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_long4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_ulong3 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_float3(lc_ulong4 v) noexcept { return lc_float3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_float s = 0) noexcept { return lc_float4{s, s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float4(lc_float x, lc_float y, lc_float z, lc_float w) noexcept { return lc_float4{x, y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float4(lc_float x, lc_float y, lc_float2 zw) noexcept { return lc_float4{x, y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float4(lc_float x, lc_float2 yz, lc_float w) noexcept { return lc_float4{x, yz.x, yz.y, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float4(lc_float2 xy, lc_float z, lc_float w) noexcept { return lc_float4{xy.x, xy.y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float4(lc_float2 xy, lc_float2 zw) noexcept { return lc_float4{xy.x, xy.y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float4(lc_float x, lc_float3 yzw) noexcept { return lc_float4{x, yzw.x, yzw.y, yzw.z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float4(lc_float3 xyz, lc_float w) noexcept { return lc_float4{xyz.x, xyz.y, xyz.z, w}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_byte4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_ubyte4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_short4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_ushort4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_int4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_uint4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_half4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_float4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_bool4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_long4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_float4(lc_ulong4 v) noexcept { return lc_float4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } + +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_bool s = 0) noexcept { return lc_bool2{s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_bool x, lc_bool y) noexcept { return lc_bool2{x, y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_byte2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_byte3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_byte4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ubyte2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ubyte3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ubyte4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_short2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_short3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_short4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ushort2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ushort3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ushort4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_int2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_int3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_int4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_uint2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_uint3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_uint4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_half2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_half3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_half4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_float2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_float3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_float4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_bool2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_bool3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_bool4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_long2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_long3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_long4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ulong2 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ulong3 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool2(lc_ulong4 v) noexcept { return lc_bool2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_bool3(lc_bool s = 0) noexcept { return lc_bool3{s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool3(lc_bool x, lc_bool y, lc_bool z) noexcept { return lc_bool3{x, y, z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool3(lc_bool x, lc_bool2 yz) noexcept { return lc_bool3{x, yz.x, yz.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool3(lc_bool2 xy, lc_bool z) noexcept { return lc_bool3{xy.x, xy.y, z}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_byte3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_byte4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_ubyte3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_ubyte4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_short3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_short4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_ushort3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_ushort4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_int3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_int4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_uint3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_uint4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_half3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_half4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_float3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_float4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_bool3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_bool4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_long3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_long4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_ulong3 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_bool3(lc_ulong4 v) noexcept { return lc_bool3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_bool s = 0) noexcept { return lc_bool4{s, s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool4(lc_bool x, lc_bool y, lc_bool z, lc_bool w) noexcept { return lc_bool4{x, y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool4(lc_bool x, lc_bool y, lc_bool2 zw) noexcept { return lc_bool4{x, y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool4(lc_bool x, lc_bool2 yz, lc_bool w) noexcept { return lc_bool4{x, yz.x, yz.y, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool4(lc_bool2 xy, lc_bool z, lc_bool w) noexcept { return lc_bool4{xy.x, xy.y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool4(lc_bool2 xy, lc_bool2 zw) noexcept { return lc_bool4{xy.x, xy.y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool4(lc_bool x, lc_bool3 yzw) noexcept { return lc_bool4{x, yzw.x, yzw.y, yzw.z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_bool4(lc_bool3 xyz, lc_bool w) noexcept { return lc_bool4{xyz.x, xyz.y, xyz.z, w}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_byte4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_ubyte4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_short4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_ushort4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_int4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_uint4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_half4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_float4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_bool4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_long4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_bool4(lc_ulong4 v) noexcept { return lc_bool4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } + +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_long s = 0) noexcept { return lc_long2{s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_long x, lc_long y) noexcept { return lc_long2{x, y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_byte2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_byte3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_byte4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ubyte2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ubyte3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ubyte4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_short2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_short3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_short4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ushort2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ushort3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ushort4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_int2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_int3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_int4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_uint2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_uint3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_uint4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_half2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_half3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_half4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_float2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_float3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_float4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_bool2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_bool3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_bool4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_long2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_long3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_long4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ulong2 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ulong3 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long2(lc_ulong4 v) noexcept { return lc_long2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_long3(lc_long s = 0) noexcept { return lc_long3{s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long3(lc_long x, lc_long y, lc_long z) noexcept { return lc_long3{x, y, z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long3(lc_long x, lc_long2 yz) noexcept { return lc_long3{x, yz.x, yz.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long3(lc_long2 xy, lc_long z) noexcept { return lc_long3{xy.x, xy.y, z}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_byte3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_byte4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_ubyte3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_ubyte4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_short3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_short4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_ushort3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_ushort4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_int3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_int4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_uint3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_uint4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_half3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_half4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_float3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_float4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_bool3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_bool4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_long3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_long4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_ulong3 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_long3(lc_ulong4 v) noexcept { return lc_long3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_long s = 0) noexcept { return lc_long4{s, s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long4(lc_long x, lc_long y, lc_long z, lc_long w) noexcept { return lc_long4{x, y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long4(lc_long x, lc_long y, lc_long2 zw) noexcept { return lc_long4{x, y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long4(lc_long x, lc_long2 yz, lc_long w) noexcept { return lc_long4{x, yz.x, yz.y, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long4(lc_long2 xy, lc_long z, lc_long w) noexcept { return lc_long4{xy.x, xy.y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long4(lc_long2 xy, lc_long2 zw) noexcept { return lc_long4{xy.x, xy.y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long4(lc_long x, lc_long3 yzw) noexcept { return lc_long4{x, yzw.x, yzw.y, yzw.z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_long4(lc_long3 xyz, lc_long w) noexcept { return lc_long4{xyz.x, xyz.y, xyz.z, w}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_byte4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_ubyte4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_short4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_ushort4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_int4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_uint4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_half4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_float4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_bool4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_long4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_long4(lc_ulong4 v) noexcept { return lc_long4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } + +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ulong s = 0) noexcept { return lc_ulong2{s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ulong x, lc_ulong y) noexcept { return lc_ulong2{x, y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_byte2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_byte3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_byte4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ubyte2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ubyte3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ubyte4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_short2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_short3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_short4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ushort2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ushort3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ushort4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_int2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_int3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_int4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_uint2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_uint3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_uint4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_half2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_half3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_half4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_float2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_float3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_float4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_bool2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_bool3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_bool4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_long2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_long3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_long4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ulong2 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ulong3 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong2(lc_ulong4 v) noexcept { return lc_ulong2{static_cast(v.x), static_cast(v.y)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ulong3(lc_ulong s = 0) noexcept { return lc_ulong3{s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong3(lc_ulong x, lc_ulong y, lc_ulong z) noexcept { return lc_ulong3{x, y, z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong3(lc_ulong x, lc_ulong2 yz) noexcept { return lc_ulong3{x, yz.x, yz.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong3(lc_ulong2 xy, lc_ulong z) noexcept { return lc_ulong3{xy.x, xy.y, z}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_byte3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_byte4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_ubyte3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_ubyte4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_short3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_short4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_ushort3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_ushort4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_int3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_int4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_uint3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_uint4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_half3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_half4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_float3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_float4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_bool3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_bool4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_long3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_long4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_ulong3 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] __device__ constexpr auto lc_make_ulong3(lc_ulong4 v) noexcept { return lc_ulong3{static_cast(v.x), static_cast(v.y), static_cast(v.z)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_ulong s = 0) noexcept { return lc_ulong4{s, s, s, s}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong4(lc_ulong x, lc_ulong y, lc_ulong z, lc_ulong w) noexcept { return lc_ulong4{x, y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong4(lc_ulong x, lc_ulong y, lc_ulong2 zw) noexcept { return lc_ulong4{x, y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong4(lc_ulong x, lc_ulong2 yz, lc_ulong w) noexcept { return lc_ulong4{x, yz.x, yz.y, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong4(lc_ulong2 xy, lc_ulong z, lc_ulong w) noexcept { return lc_ulong4{xy.x, xy.y, z, w}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong4(lc_ulong2 xy, lc_ulong2 zw) noexcept { return lc_ulong4{xy.x, xy.y, zw.x, zw.y}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong4(lc_ulong x, lc_ulong3 yzw) noexcept { return lc_ulong4{x, yzw.x, yzw.y, yzw.z}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_ulong4(lc_ulong3 xyz, lc_ulong w) noexcept { return lc_ulong4{xyz.x, xyz.y, xyz.z, w}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_byte4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_ubyte4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_short4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_ushort4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_int4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_uint4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_half4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_float4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_bool4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_long4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } +[[nodiscard]] inline __device__ constexpr auto lc_make_ulong4(lc_ulong4 v) noexcept { return lc_ulong4{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}; } + +[[nodiscard]] inline __device__ constexpr auto operator!(lc_byte2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_byte2 v) noexcept { return lc_make_byte2(+v.x, +v.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_byte2 v) noexcept { return lc_make_byte2(-v.x, -v.y); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_byte2 v) noexcept { return lc_make_byte2(~v.x, ~v.y); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_byte3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_byte3 v) noexcept { return lc_make_byte3(+v.x, +v.y, +v.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_byte3 v) noexcept { return lc_make_byte3(-v.x, -v.y, -v.z); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_byte3 v) noexcept { return lc_make_byte3(~v.x, ~v.y, ~v.z); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_byte4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_byte4 v) noexcept { return lc_make_byte4(+v.x, +v.y, +v.z, +v.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_byte4 v) noexcept { return lc_make_byte4(-v.x, -v.y, -v.z, -v.w); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_byte4 v) noexcept { return lc_make_byte4(~v.x, ~v.y, ~v.z, ~v.w); } + +[[nodiscard]] inline __device__ constexpr auto operator!(lc_ubyte2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ubyte2 v) noexcept { return lc_make_ubyte2(+v.x, +v.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ubyte2 v) noexcept { return lc_make_ubyte2(-v.x, -v.y); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_ubyte2 v) noexcept { return lc_make_ubyte2(~v.x, ~v.y); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_ubyte3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ubyte3 v) noexcept { return lc_make_ubyte3(+v.x, +v.y, +v.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ubyte3 v) noexcept { return lc_make_ubyte3(-v.x, -v.y, -v.z); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_ubyte3 v) noexcept { return lc_make_ubyte3(~v.x, ~v.y, ~v.z); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_ubyte4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ubyte4 v) noexcept { return lc_make_ubyte4(+v.x, +v.y, +v.z, +v.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ubyte4 v) noexcept { return lc_make_ubyte4(-v.x, -v.y, -v.z, -v.w); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_ubyte4 v) noexcept { return lc_make_ubyte4(~v.x, ~v.y, ~v.z, ~v.w); } + +[[nodiscard]] inline __device__ constexpr auto operator!(lc_short2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_short2 v) noexcept { return lc_make_short2(+v.x, +v.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_short2 v) noexcept { return lc_make_short2(-v.x, -v.y); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_short2 v) noexcept { return lc_make_short2(~v.x, ~v.y); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_short3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_short3 v) noexcept { return lc_make_short3(+v.x, +v.y, +v.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_short3 v) noexcept { return lc_make_short3(-v.x, -v.y, -v.z); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_short3 v) noexcept { return lc_make_short3(~v.x, ~v.y, ~v.z); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_short4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_short4 v) noexcept { return lc_make_short4(+v.x, +v.y, +v.z, +v.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_short4 v) noexcept { return lc_make_short4(-v.x, -v.y, -v.z, -v.w); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_short4 v) noexcept { return lc_make_short4(~v.x, ~v.y, ~v.z, ~v.w); } + +[[nodiscard]] inline __device__ constexpr auto operator!(lc_ushort2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort2 v) noexcept { return lc_make_ushort2(+v.x, +v.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort2 v) noexcept { return lc_make_ushort2(-v.x, -v.y); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_ushort2 v) noexcept { return lc_make_ushort2(~v.x, ~v.y); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_ushort3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort3 v) noexcept { return lc_make_ushort3(+v.x, +v.y, +v.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort3 v) noexcept { return lc_make_ushort3(-v.x, -v.y, -v.z); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_ushort3 v) noexcept { return lc_make_ushort3(~v.x, ~v.y, ~v.z); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_ushort4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort4 v) noexcept { return lc_make_ushort4(+v.x, +v.y, +v.z, +v.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort4 v) noexcept { return lc_make_ushort4(-v.x, -v.y, -v.z, -v.w); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_ushort4 v) noexcept { return lc_make_ushort4(~v.x, ~v.y, ~v.z, ~v.w); } + +[[nodiscard]] inline __device__ constexpr auto operator!(lc_int2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_int2 v) noexcept { return lc_make_int2(+v.x, +v.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_int2 v) noexcept { return lc_make_int2(-v.x, -v.y); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_int2 v) noexcept { return lc_make_int2(~v.x, ~v.y); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_int3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_int3 v) noexcept { return lc_make_int3(+v.x, +v.y, +v.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_int3 v) noexcept { return lc_make_int3(-v.x, -v.y, -v.z); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_int3 v) noexcept { return lc_make_int3(~v.x, ~v.y, ~v.z); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_int4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_int4 v) noexcept { return lc_make_int4(+v.x, +v.y, +v.z, +v.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_int4 v) noexcept { return lc_make_int4(-v.x, -v.y, -v.z, -v.w); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_int4 v) noexcept { return lc_make_int4(~v.x, ~v.y, ~v.z, ~v.w); } + +[[nodiscard]] inline __device__ constexpr auto operator!(lc_uint2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint2 v) noexcept { return lc_make_uint2(+v.x, +v.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint2 v) noexcept { return lc_make_uint2(-v.x, -v.y); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_uint2 v) noexcept { return lc_make_uint2(~v.x, ~v.y); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_uint3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint3 v) noexcept { return lc_make_uint3(+v.x, +v.y, +v.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint3 v) noexcept { return lc_make_uint3(-v.x, -v.y, -v.z); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_uint3 v) noexcept { return lc_make_uint3(~v.x, ~v.y, ~v.z); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_uint4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint4 v) noexcept { return lc_make_uint4(+v.x, +v.y, +v.z, +v.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint4 v) noexcept { return lc_make_uint4(-v.x, -v.y, -v.z, -v.w); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_uint4 v) noexcept { return lc_make_uint4(~v.x, ~v.y, ~v.z, ~v.w); } + +[[nodiscard]] inline __device__ constexpr auto operator!(lc_half2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_half2 v) noexcept { return lc_make_half2(+v.x, +v.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_half2 v) noexcept { return lc_make_half2(-v.x, -v.y); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_half3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_half3 v) noexcept { return lc_make_half3(+v.x, +v.y, +v.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_half3 v) noexcept { return lc_make_half3(-v.x, -v.y, -v.z); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_half4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_half4 v) noexcept { return lc_make_half4(+v.x, +v.y, +v.z, +v.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_half4 v) noexcept { return lc_make_half4(-v.x, -v.y, -v.z, -v.w); } + +[[nodiscard]] inline __device__ constexpr auto operator!(lc_float2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_float2 v) noexcept { return lc_make_float2(+v.x, +v.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_float2 v) noexcept { return lc_make_float2(-v.x, -v.y); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_float3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_float3 v) noexcept { return lc_make_float3(+v.x, +v.y, +v.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_float3 v) noexcept { return lc_make_float3(-v.x, -v.y, -v.z); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_float4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_float4 v) noexcept { return lc_make_float4(+v.x, +v.y, +v.z, +v.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_float4 v) noexcept { return lc_make_float4(-v.x, -v.y, -v.z, -v.w); } + +[[nodiscard]] inline __device__ constexpr auto operator!(lc_bool2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_bool3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_bool4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } + +[[nodiscard]] inline __device__ constexpr auto operator!(lc_long2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_long2 v) noexcept { return lc_make_long2(+v.x, +v.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_long2 v) noexcept { return lc_make_long2(-v.x, -v.y); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_long2 v) noexcept { return lc_make_long2(~v.x, ~v.y); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_long3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_long3 v) noexcept { return lc_make_long3(+v.x, +v.y, +v.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_long3 v) noexcept { return lc_make_long3(-v.x, -v.y, -v.z); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_long3 v) noexcept { return lc_make_long3(~v.x, ~v.y, ~v.z); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_long4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_long4 v) noexcept { return lc_make_long4(+v.x, +v.y, +v.z, +v.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_long4 v) noexcept { return lc_make_long4(-v.x, -v.y, -v.z, -v.w); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_long4 v) noexcept { return lc_make_long4(~v.x, ~v.y, ~v.z, ~v.w); } + +[[nodiscard]] inline __device__ constexpr auto operator!(lc_ulong2 v) noexcept { return lc_make_bool2(!v.x, !v.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong2 v) noexcept { return lc_make_ulong2(+v.x, +v.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong2 v) noexcept { return lc_make_ulong2(-v.x, -v.y); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_ulong2 v) noexcept { return lc_make_ulong2(~v.x, ~v.y); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_ulong3 v) noexcept { return lc_make_bool3(!v.x, !v.y, !v.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong3 v) noexcept { return lc_make_ulong3(+v.x, +v.y, +v.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong3 v) noexcept { return lc_make_ulong3(-v.x, -v.y, -v.z); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_ulong3 v) noexcept { return lc_make_ulong3(~v.x, ~v.y, ~v.z); } +[[nodiscard]] inline __device__ constexpr auto operator!(lc_ulong4 v) noexcept { return lc_make_bool4(!v.x, !v.y, !v.z, !v.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong4 v) noexcept { return lc_make_ulong4(+v.x, +v.y, +v.z, +v.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong4 v) noexcept { return lc_make_ulong4(-v.x, -v.y, -v.z, -v.w); } +[[nodiscard]] inline __device__ constexpr auto operator~(lc_ulong4 v) noexcept { return lc_make_ulong4(~v.x, ~v.y, ~v.z, ~v.w); } + +[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte2 lhs, lc_byte2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte2 lhs, lc_byte rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte lhs, lc_byte2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte3 lhs, lc_byte3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte3 lhs, lc_byte rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte lhs, lc_byte3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte4 lhs, lc_byte4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte4 lhs, lc_byte rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_byte lhs, lc_byte4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte2 lhs, lc_ubyte2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte2 lhs, lc_ubyte rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte lhs, lc_ubyte2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte3 lhs, lc_ubyte3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte3 lhs, lc_ubyte rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte lhs, lc_ubyte3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte4 lhs, lc_ubyte4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte4 lhs, lc_ubyte rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ubyte lhs, lc_ubyte4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool2 lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool2 lhs, lc_bool rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool3 lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool3 lhs, lc_bool rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool4 lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool4 lhs, lc_bool rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_bool lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs.x == rhs.x, lhs.y == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_bool2(lhs.x == rhs, lhs.y == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs == rhs.x, lhs == rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_bool3(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs); } +[[nodiscard]] inline __device__ constexpr auto operator==(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs == rhs.x, lhs == rhs.y, lhs == rhs.z, lhs == rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte2 lhs, lc_byte2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte2 lhs, lc_byte rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte lhs, lc_byte2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte3 lhs, lc_byte3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte3 lhs, lc_byte rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte lhs, lc_byte3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte4 lhs, lc_byte4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte4 lhs, lc_byte rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_byte lhs, lc_byte4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte2 lhs, lc_ubyte2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte2 lhs, lc_ubyte rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte lhs, lc_ubyte2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte3 lhs, lc_ubyte3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte3 lhs, lc_ubyte rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte lhs, lc_ubyte3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte4 lhs, lc_ubyte4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte4 lhs, lc_ubyte rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ubyte lhs, lc_ubyte4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool2 lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool2 lhs, lc_bool rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool3 lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool3 lhs, lc_bool rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool4 lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool4 lhs, lc_bool rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_bool lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs.x != rhs.x, lhs.y != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_bool2(lhs.x != rhs, lhs.y != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs != rhs.x, lhs != rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_bool3(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs); } +[[nodiscard]] inline __device__ constexpr auto operator!=(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator<(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs.x < rhs.x, lhs.y < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_bool2(lhs.x < rhs, lhs.y < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs < rhs.x, lhs < rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_bool3(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs < rhs.x, lhs < rhs.y, lhs < rhs.z, lhs < rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator>(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs.x > rhs.x, lhs.y > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_bool2(lhs.x > rhs, lhs.y > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs > rhs.x, lhs > rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_bool3(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs > rhs.x, lhs > rhs.y, lhs > rhs.z, lhs > rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs.x <= rhs.x, lhs.y <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_bool2(lhs.x <= rhs, lhs.y <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs <= rhs.x, lhs <= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_bool3(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<=(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs.x >= rhs.x, lhs.y >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_bool2(lhs.x >= rhs, lhs.y >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_bool2(lhs >= rhs.x, lhs >= rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_bool3(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_bool3(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>=(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator+(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x + rhs.x, lhs.y + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x + rhs, lhs.y + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs + rhs.x, lhs + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x + rhs.x, lhs.y + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x + rhs, lhs.y + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs + rhs.x, lhs + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x + rhs.x, lhs.y + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x + rhs, lhs.y + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs + rhs.x, lhs + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x + rhs.x, lhs.y + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x + rhs, lhs.y + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs + rhs.x, lhs + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs.x + rhs.x, lhs.y + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_half2(lhs.x + rhs, lhs.y + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs + rhs.x, lhs + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_half3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_half4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs.x + rhs.x, lhs.y + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_float2(lhs.x + rhs, lhs.y + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs + rhs.x, lhs + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_float3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_float4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x + rhs.x, lhs.y + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x + rhs, lhs.y + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs + rhs.x, lhs + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x + rhs.x, lhs.y + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x + rhs, lhs.y + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs + rhs.x, lhs + rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs); } +[[nodiscard]] inline __device__ constexpr auto operator+(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator-(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x - rhs.x, lhs.y - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x - rhs, lhs.y - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs - rhs.x, lhs - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x - rhs.x, lhs.y - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x - rhs, lhs.y - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs - rhs.x, lhs - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x - rhs.x, lhs.y - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x - rhs, lhs.y - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs - rhs.x, lhs - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x - rhs.x, lhs.y - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x - rhs, lhs.y - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs - rhs.x, lhs - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs.x - rhs.x, lhs.y - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_half2(lhs.x - rhs, lhs.y - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs - rhs.x, lhs - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_half3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_half4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs.x - rhs.x, lhs.y - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_float2(lhs.x - rhs, lhs.y - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs - rhs.x, lhs - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_float3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_float4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x - rhs.x, lhs.y - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x - rhs, lhs.y - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs - rhs.x, lhs - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x - rhs.x, lhs.y - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x - rhs, lhs.y - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs - rhs.x, lhs - rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs); } +[[nodiscard]] inline __device__ constexpr auto operator-(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator*(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x * rhs.x, lhs.y * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x * rhs, lhs.y * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs * rhs.x, lhs * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x * rhs.x, lhs.y * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x * rhs, lhs.y * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs * rhs.x, lhs * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x * rhs.x, lhs.y * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x * rhs, lhs.y * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs * rhs.x, lhs * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x * rhs.x, lhs.y * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x * rhs, lhs.y * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs * rhs.x, lhs * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs.x * rhs.x, lhs.y * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_half2(lhs.x * rhs, lhs.y * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs * rhs.x, lhs * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_half3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_half4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs.x * rhs.x, lhs.y * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_float2(lhs.x * rhs, lhs.y * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs * rhs.x, lhs * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_float3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_float4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x * rhs.x, lhs.y * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x * rhs, lhs.y * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs * rhs.x, lhs * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x * rhs.x, lhs.y * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x * rhs, lhs.y * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs * rhs.x, lhs * rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } +[[nodiscard]] inline __device__ constexpr auto operator*(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator/(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x / rhs.x, lhs.y / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x / rhs, lhs.y / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs / rhs.x, lhs / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x / rhs.x, lhs.y / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x / rhs, lhs.y / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs / rhs.x, lhs / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x / rhs.x, lhs.y / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x / rhs, lhs.y / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs / rhs.x, lhs / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x / rhs.x, lhs.y / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x / rhs, lhs.y / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs / rhs.x, lhs / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_half2 lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs.x / rhs.x, lhs.y / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_half2 lhs, lc_half rhs) noexcept { return lc_make_half2(lhs.x / rhs, lhs.y / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_half lhs, lc_half2 rhs) noexcept { return lc_make_half2(lhs / rhs.x, lhs / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_half3 lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_half3 lhs, lc_half rhs) noexcept { return lc_make_half3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_half lhs, lc_half3 rhs) noexcept { return lc_make_half3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_half4 lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_half4 lhs, lc_half rhs) noexcept { return lc_make_half4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_half lhs, lc_half4 rhs) noexcept { return lc_make_half4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_float2 lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs.x / rhs.x, lhs.y / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_float2 lhs, lc_float rhs) noexcept { return lc_make_float2(lhs.x / rhs, lhs.y / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_float lhs, lc_float2 rhs) noexcept { return lc_make_float2(lhs / rhs.x, lhs / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_float3 lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_float3 lhs, lc_float rhs) noexcept { return lc_make_float3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_float lhs, lc_float3 rhs) noexcept { return lc_make_float3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_float4 lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_float4 lhs, lc_float rhs) noexcept { return lc_make_float4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_float lhs, lc_float4 rhs) noexcept { return lc_make_float4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x / rhs.x, lhs.y / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x / rhs, lhs.y / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs / rhs.x, lhs / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x / rhs.x, lhs.y / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x / rhs, lhs.y / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs / rhs.x, lhs / rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } +[[nodiscard]] inline __device__ constexpr auto operator/(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator%(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x % rhs.x, lhs.y % rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x % rhs, lhs.y % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs % rhs.x, lhs % rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z, lhs.w % rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs, lhs.w % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z, lhs % rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x % rhs.x, lhs.y % rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x % rhs, lhs.y % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs % rhs.x, lhs % rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z, lhs.w % rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs, lhs.w % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z, lhs % rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x % rhs.x, lhs.y % rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x % rhs, lhs.y % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs % rhs.x, lhs % rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z, lhs.w % rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs, lhs.w % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z, lhs % rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x % rhs.x, lhs.y % rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x % rhs, lhs.y % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs % rhs.x, lhs % rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z, lhs.w % rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs, lhs.w % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z, lhs % rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x % rhs.x, lhs.y % rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x % rhs, lhs.y % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs % rhs.x, lhs % rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z, lhs.w % rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs, lhs.w % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z, lhs % rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x % rhs.x, lhs.y % rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x % rhs, lhs.y % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs % rhs.x, lhs % rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z, lhs.w % rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x % rhs, lhs.y % rhs, lhs.z % rhs, lhs.w % rhs); } +[[nodiscard]] inline __device__ constexpr auto operator%(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs % rhs.x, lhs % rhs.y, lhs % rhs.z, lhs % rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x << rhs.x, lhs.y << rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x << rhs, lhs.y << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs << rhs.x, lhs << rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z, lhs.w << rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs, lhs.w << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z, lhs << rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x << rhs.x, lhs.y << rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x << rhs, lhs.y << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs << rhs.x, lhs << rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z, lhs.w << rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs, lhs.w << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z, lhs << rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x << rhs.x, lhs.y << rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x << rhs, lhs.y << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs << rhs.x, lhs << rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z, lhs.w << rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs, lhs.w << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z, lhs << rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x << rhs.x, lhs.y << rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x << rhs, lhs.y << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs << rhs.x, lhs << rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z, lhs.w << rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs, lhs.w << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z, lhs << rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x << rhs.x, lhs.y << rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x << rhs, lhs.y << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs << rhs.x, lhs << rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z, lhs.w << rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs, lhs.w << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z, lhs << rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x << rhs.x, lhs.y << rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x << rhs, lhs.y << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs << rhs.x, lhs << rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z, lhs.w << rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x << rhs, lhs.y << rhs, lhs.z << rhs, lhs.w << rhs); } +[[nodiscard]] inline __device__ constexpr auto operator<<(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs << rhs.x, lhs << rhs.y, lhs << rhs.z, lhs << rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x >> rhs.x, lhs.y >> rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x >> rhs, lhs.y >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs >> rhs.x, lhs >> rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z, lhs.w >> rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs, lhs.w >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z, lhs >> rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x >> rhs.x, lhs.y >> rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x >> rhs, lhs.y >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs >> rhs.x, lhs >> rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z, lhs.w >> rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs, lhs.w >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z, lhs >> rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x >> rhs.x, lhs.y >> rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x >> rhs, lhs.y >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs >> rhs.x, lhs >> rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z, lhs.w >> rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs, lhs.w >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z, lhs >> rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x >> rhs.x, lhs.y >> rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x >> rhs, lhs.y >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs >> rhs.x, lhs >> rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z, lhs.w >> rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs, lhs.w >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z, lhs >> rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x >> rhs.x, lhs.y >> rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x >> rhs, lhs.y >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs >> rhs.x, lhs >> rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z, lhs.w >> rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs, lhs.w >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z, lhs >> rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x >> rhs.x, lhs.y >> rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x >> rhs, lhs.y >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs >> rhs.x, lhs >> rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z, lhs.w >> rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x >> rhs, lhs.y >> rhs, lhs.z >> rhs, lhs.w >> rhs); } +[[nodiscard]] inline __device__ constexpr auto operator>>(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs >> rhs.x, lhs >> rhs.y, lhs >> rhs.z, lhs >> rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator|(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x | rhs.x, lhs.y | rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x | rhs, lhs.y | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs | rhs.x, lhs | rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z, lhs.w | rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs, lhs.w | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z, lhs | rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x | rhs.x, lhs.y | rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x | rhs, lhs.y | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs | rhs.x, lhs | rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z, lhs.w | rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs, lhs.w | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z, lhs | rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x | rhs.x, lhs.y | rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x | rhs, lhs.y | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs | rhs.x, lhs | rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z, lhs.w | rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs, lhs.w | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z, lhs | rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x | rhs.x, lhs.y | rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x | rhs, lhs.y | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs | rhs.x, lhs | rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z, lhs.w | rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs, lhs.w | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z, lhs | rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool2 lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs.x | rhs.x, lhs.y | rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool2 lhs, lc_bool rhs) noexcept { return lc_make_bool2(lhs.x | rhs, lhs.y | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs | rhs.x, lhs | rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool3 lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool3 lhs, lc_bool rhs) noexcept { return lc_make_bool3(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool4 lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z, lhs.w | rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool4 lhs, lc_bool rhs) noexcept { return lc_make_bool4(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs, lhs.w | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_bool lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z, lhs | rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x | rhs.x, lhs.y | rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x | rhs, lhs.y | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs | rhs.x, lhs | rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z, lhs.w | rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs, lhs.w | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z, lhs | rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x | rhs.x, lhs.y | rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x | rhs, lhs.y | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs | rhs.x, lhs | rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z, lhs.w | rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x | rhs, lhs.y | rhs, lhs.z | rhs, lhs.w | rhs); } +[[nodiscard]] inline __device__ constexpr auto operator|(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs | rhs.x, lhs | rhs.y, lhs | rhs.z, lhs | rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator&(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x & rhs.x, lhs.y & rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x & rhs, lhs.y & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs & rhs.x, lhs & rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z, lhs.w & rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs, lhs.w & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z, lhs & rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x & rhs.x, lhs.y & rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x & rhs, lhs.y & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs & rhs.x, lhs & rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z, lhs.w & rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs, lhs.w & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z, lhs & rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x & rhs.x, lhs.y & rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x & rhs, lhs.y & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs & rhs.x, lhs & rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z, lhs.w & rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs, lhs.w & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z, lhs & rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x & rhs.x, lhs.y & rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x & rhs, lhs.y & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs & rhs.x, lhs & rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z, lhs.w & rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs, lhs.w & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z, lhs & rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool2 lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs.x & rhs.x, lhs.y & rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool2 lhs, lc_bool rhs) noexcept { return lc_make_bool2(lhs.x & rhs, lhs.y & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs & rhs.x, lhs & rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool3 lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool3 lhs, lc_bool rhs) noexcept { return lc_make_bool3(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool4 lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z, lhs.w & rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool4 lhs, lc_bool rhs) noexcept { return lc_make_bool4(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs, lhs.w & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_bool lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z, lhs & rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x & rhs.x, lhs.y & rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x & rhs, lhs.y & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs & rhs.x, lhs & rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z, lhs.w & rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs, lhs.w & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z, lhs & rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x & rhs.x, lhs.y & rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x & rhs, lhs.y & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs & rhs.x, lhs & rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z, lhs.w & rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x & rhs, lhs.y & rhs, lhs.z & rhs, lhs.w & rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs & rhs.x, lhs & rhs.y, lhs & rhs.z, lhs & rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator^(lc_short2 lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs.x ^ rhs.x, lhs.y ^ rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_short2 lhs, lc_short rhs) noexcept { return lc_make_short2(lhs.x ^ rhs, lhs.y ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_short lhs, lc_short2 rhs) noexcept { return lc_make_short2(lhs ^ rhs.x, lhs ^ rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_short3 lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_short3 lhs, lc_short rhs) noexcept { return lc_make_short3(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_short lhs, lc_short3 rhs) noexcept { return lc_make_short3(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_short4 lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z, lhs.w ^ rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_short4 lhs, lc_short rhs) noexcept { return lc_make_short4(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs, lhs.w ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_short lhs, lc_short4 rhs) noexcept { return lc_make_short4(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z, lhs ^ rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort2 lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs.x ^ rhs.x, lhs.y ^ rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort2 lhs, lc_ushort rhs) noexcept { return lc_make_ushort2(lhs.x ^ rhs, lhs.y ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort lhs, lc_ushort2 rhs) noexcept { return lc_make_ushort2(lhs ^ rhs.x, lhs ^ rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort3 lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort3 lhs, lc_ushort rhs) noexcept { return lc_make_ushort3(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort lhs, lc_ushort3 rhs) noexcept { return lc_make_ushort3(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort4 lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z, lhs.w ^ rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort4 lhs, lc_ushort rhs) noexcept { return lc_make_ushort4(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs, lhs.w ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ushort lhs, lc_ushort4 rhs) noexcept { return lc_make_ushort4(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z, lhs ^ rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_int2 lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs.x ^ rhs.x, lhs.y ^ rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_int2 lhs, lc_int rhs) noexcept { return lc_make_int2(lhs.x ^ rhs, lhs.y ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_int lhs, lc_int2 rhs) noexcept { return lc_make_int2(lhs ^ rhs.x, lhs ^ rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_int3 lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_int3 lhs, lc_int rhs) noexcept { return lc_make_int3(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_int lhs, lc_int3 rhs) noexcept { return lc_make_int3(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_int4 lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z, lhs.w ^ rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_int4 lhs, lc_int rhs) noexcept { return lc_make_int4(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs, lhs.w ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_int lhs, lc_int4 rhs) noexcept { return lc_make_int4(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z, lhs ^ rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint2 lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs.x ^ rhs.x, lhs.y ^ rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint2 lhs, lc_uint rhs) noexcept { return lc_make_uint2(lhs.x ^ rhs, lhs.y ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint lhs, lc_uint2 rhs) noexcept { return lc_make_uint2(lhs ^ rhs.x, lhs ^ rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint3 lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint3 lhs, lc_uint rhs) noexcept { return lc_make_uint3(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint lhs, lc_uint3 rhs) noexcept { return lc_make_uint3(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint4 lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z, lhs.w ^ rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint4 lhs, lc_uint rhs) noexcept { return lc_make_uint4(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs, lhs.w ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_uint lhs, lc_uint4 rhs) noexcept { return lc_make_uint4(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z, lhs ^ rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool2 lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs.x ^ rhs.x, lhs.y ^ rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool2 lhs, lc_bool rhs) noexcept { return lc_make_bool2(lhs.x ^ rhs, lhs.y ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs ^ rhs.x, lhs ^ rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool3 lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool3 lhs, lc_bool rhs) noexcept { return lc_make_bool3(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool4 lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z, lhs.w ^ rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool4 lhs, lc_bool rhs) noexcept { return lc_make_bool4(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs, lhs.w ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_bool lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z, lhs ^ rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_long2 lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs.x ^ rhs.x, lhs.y ^ rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_long2 lhs, lc_long rhs) noexcept { return lc_make_long2(lhs.x ^ rhs, lhs.y ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_long lhs, lc_long2 rhs) noexcept { return lc_make_long2(lhs ^ rhs.x, lhs ^ rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_long3 lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_long3 lhs, lc_long rhs) noexcept { return lc_make_long3(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_long lhs, lc_long3 rhs) noexcept { return lc_make_long3(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_long4 lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z, lhs.w ^ rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_long4 lhs, lc_long rhs) noexcept { return lc_make_long4(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs, lhs.w ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_long lhs, lc_long4 rhs) noexcept { return lc_make_long4(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z, lhs ^ rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong2 lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs.x ^ rhs.x, lhs.y ^ rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong2 lhs, lc_ulong rhs) noexcept { return lc_make_ulong2(lhs.x ^ rhs, lhs.y ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong lhs, lc_ulong2 rhs) noexcept { return lc_make_ulong2(lhs ^ rhs.x, lhs ^ rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong3 lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong3 lhs, lc_ulong rhs) noexcept { return lc_make_ulong3(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong lhs, lc_ulong3 rhs) noexcept { return lc_make_ulong3(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong4 lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z, lhs.w ^ rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong4 lhs, lc_ulong rhs) noexcept { return lc_make_ulong4(lhs.x ^ rhs, lhs.y ^ rhs, lhs.z ^ rhs, lhs.w ^ rhs); } +[[nodiscard]] inline __device__ constexpr auto operator^(lc_ulong lhs, lc_ulong4 rhs) noexcept { return lc_make_ulong4(lhs ^ rhs.x, lhs ^ rhs.y, lhs ^ rhs.z, lhs ^ rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool2 lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs.x || rhs.x, lhs.y || rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool2 lhs, lc_bool rhs) noexcept { return lc_make_bool2(lhs.x || rhs, lhs.y || rhs); } +[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs || rhs.x, lhs || rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool3 lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs.x || rhs.x, lhs.y || rhs.y, lhs.z || rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool3 lhs, lc_bool rhs) noexcept { return lc_make_bool3(lhs.x || rhs, lhs.y || rhs, lhs.z || rhs); } +[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs || rhs.x, lhs || rhs.y, lhs || rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool4 lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs.x || rhs.x, lhs.y || rhs.y, lhs.z || rhs.z, lhs.w || rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool4 lhs, lc_bool rhs) noexcept { return lc_make_bool4(lhs.x || rhs, lhs.y || rhs, lhs.z || rhs, lhs.w || rhs); } +[[nodiscard]] inline __device__ constexpr auto operator||(lc_bool lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs || rhs.x, lhs || rhs.y, lhs || rhs.z, lhs || rhs.w); } + +[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool2 lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs.x && rhs.x, lhs.y && rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool2 lhs, lc_bool rhs) noexcept { return lc_make_bool2(lhs.x && rhs, lhs.y && rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool lhs, lc_bool2 rhs) noexcept { return lc_make_bool2(lhs && rhs.x, lhs && rhs.y); } +[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool3 lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs.x && rhs.x, lhs.y && rhs.y, lhs.z && rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool3 lhs, lc_bool rhs) noexcept { return lc_make_bool3(lhs.x && rhs, lhs.y && rhs, lhs.z && rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool lhs, lc_bool3 rhs) noexcept { return lc_make_bool3(lhs && rhs.x, lhs && rhs.y, lhs && rhs.z); } +[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool4 lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs.x && rhs.x, lhs.y && rhs.y, lhs.z && rhs.z, lhs.w && rhs.w); } +[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool4 lhs, lc_bool rhs) noexcept { return lc_make_bool4(lhs.x && rhs, lhs.y && rhs, lhs.z && rhs, lhs.w && rhs); } +[[nodiscard]] inline __device__ constexpr auto operator&&(lc_bool lhs, lc_bool4 rhs) noexcept { return lc_make_bool4(lhs && rhs.x, lhs && rhs.y, lhs && rhs.z, lhs && rhs.w); } + +[[nodiscard]] __device__ inline constexpr auto lc_any(lc_bool2 v) noexcept { return v.x || v.y; } +[[nodiscard]] __device__ inline constexpr auto lc_any(lc_bool3 v) noexcept { return v.x || v.y || v.z; } +[[nodiscard]] __device__ inline constexpr auto lc_any(lc_bool4 v) noexcept { return v.x || v.y || v.z || v.w; } +[[nodiscard]] __device__ inline constexpr auto lc_all(lc_bool2 v) noexcept { return v.x && v.y; } +[[nodiscard]] __device__ inline constexpr auto lc_all(lc_bool3 v) noexcept { return v.x && v.y && v.z; } +[[nodiscard]] __device__ inline constexpr auto lc_all(lc_bool4 v) noexcept { return v.x && v.y && v.z && v.w; } +[[nodiscard]] __device__ inline constexpr auto lc_none(lc_bool2 v) noexcept { return !v.x && !v.y; } +[[nodiscard]] __device__ inline constexpr auto lc_none(lc_bool3 v) noexcept { return !v.x && !v.y && !v.z; } +[[nodiscard]] __device__ inline constexpr auto lc_none(lc_bool4 v) noexcept { return !v.x && !v.y && !v.z && !v.w; } + +struct lc_float2x2 { + lc_float2 cols[2]; + __device__ inline constexpr lc_float2x2() noexcept : cols{} {} + __device__ inline explicit constexpr lc_float2x2(lc_float s) noexcept + : cols{lc_make_float2(s, 0.0f), lc_make_float2(0.0f, s)} {} + __device__ inline constexpr static auto full(lc_float s) noexcept { return lc_float2x2{lc_float2(s), lc_float2(s)}; } + __device__ inline constexpr static auto zero() noexcept { return lc_float2x2{lc_float2::zero(), lc_float2::zero()}; } + __device__ inline constexpr static auto one() noexcept { return lc_float2x2{lc_float2::one(), lc_float2::one()}; } + __device__ inline constexpr lc_float2x2(lc_float2 c0, lc_float2 c1) noexcept + : cols{c0, c1} {} + [[nodiscard]] __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return cols[i]; } + [[nodiscard]] __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return cols[i]; } + [[nodiscard]] __device__ inline constexpr auto comp_mul(const lc_float2x2 &rhs) const noexcept { return lc_float2x2{cols[0] * rhs[0], cols[1] * rhs[1]}; } +}; + +struct lc_float3x3 { + lc_float3 cols[3]; + __device__ inline constexpr lc_float3x3() noexcept : cols{} {} + __device__ inline explicit constexpr lc_float3x3(lc_float s) noexcept + : cols{lc_make_float3(s, 0.0f, 0.0f), lc_make_float3(0.0f, s, 0.0f), lc_make_float3(0.0f, 0.0f, s)} {} + __device__ inline constexpr static auto full(lc_float s) noexcept { return lc_float3x3{lc_float3(s), lc_float3(s), lc_float3(s)}; } + __device__ inline constexpr static auto zero() noexcept { return lc_float3x3{lc_float3::zero(), lc_float3::zero(), lc_float3::zero()}; } + __device__ inline constexpr static auto one() noexcept { return lc_float3x3{lc_float3::one(), lc_float3::one(), lc_float3::one()}; } + __device__ inline constexpr lc_float3x3(lc_float3 c0, lc_float3 c1, lc_float3 c2) noexcept + : cols{c0, c1, c2} {} + [[nodiscard]] __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return cols[i]; } + [[nodiscard]] __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return cols[i]; } + [[nodiscard]] __device__ inline constexpr auto comp_mul(const lc_float3x3 &rhs) const noexcept { return lc_float3x3{cols[0] * rhs[0], cols[1] * rhs[1], cols[2] * rhs[2]}; } +}; + +struct lc_float4x4 { + lc_float4 cols[4]; + __device__ inline constexpr lc_float4x4() noexcept : cols{} {} + __device__ inline explicit constexpr lc_float4x4(lc_float s) noexcept + : cols{lc_make_float4(s, 0.0f, 0.0f, 0.0f), lc_make_float4(0.0f, s, 0.0f, 0.0f), lc_make_float4(0.0f, 0.0f, s, 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, s)} {} + __device__ inline constexpr static auto full(lc_float s) noexcept { return lc_float4x4{lc_float4(s), lc_float4(s), lc_float4(s), lc_float4(s)}; } + __device__ inline constexpr static auto zero() noexcept { return lc_float4x4{lc_float4::zero(), lc_float4::zero(), lc_float4::zero(), lc_float4::zero()}; } + __device__ inline constexpr static auto one() noexcept { return lc_float4x4{lc_float4::one(), lc_float4::one(), lc_float4::one(), lc_float4::one()}; } + __device__ inline constexpr lc_float4x4(lc_float4 c0, lc_float4 c1, lc_float4 c2, lc_float4 c3) noexcept + : cols{c0, c1, c2, c3} {} + [[nodiscard]] __device__ inline constexpr auto &operator[](lc_uint i) noexcept { return cols[i]; } + [[nodiscard]] __device__ inline constexpr auto operator[](lc_uint i) const noexcept { return cols[i]; } + [[nodiscard]] __device__ inline constexpr auto comp_mul(const lc_float4x4 &rhs) const noexcept { return lc_float4x4{cols[0] * rhs[0], cols[1] * rhs[1], cols[2] * rhs[2], cols[3] * rhs[3]}; } +}; + +[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float2x2 m, lc_float s) noexcept { return lc_float2x2{m[0] * s, m[1] * s}; } +[[nodiscard]] __device__ inline constexpr auto operator*(lc_float s, const lc_float2x2 m) noexcept { return m * s; } +[[nodiscard]] __device__ inline constexpr auto operator/(const lc_float2x2 m, lc_float s) noexcept { return m * (1.0f / s); } +[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float2x2 m, const lc_float2 v) noexcept { return v.x * m[0] + v.y * m[1]; } +[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float2x2 lhs, const lc_float2x2 rhs) noexcept { return lc_float2x2{lhs * rhs[0], lhs * rhs[1]}; } +[[nodiscard]] __device__ inline constexpr auto operator+(const lc_float2x2 lhs, const lc_float2x2 rhs) noexcept { return lc_float2x2{lhs[0] + rhs[0], lhs[1] + rhs[1]}; } +[[nodiscard]] __device__ inline constexpr auto operator-(const lc_float2x2 lhs, const lc_float2x2 rhs) noexcept { return lc_float2x2{lhs[0] - rhs[0], lhs[1] - rhs[1]}; } + +[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float3x3 m, lc_float s) noexcept { return lc_float3x3{m[0] * s, m[1] * s, m[2] * s}; } +[[nodiscard]] __device__ inline constexpr auto operator*(lc_float s, const lc_float3x3 m) noexcept { return m * s; } +[[nodiscard]] __device__ inline constexpr auto operator/(const lc_float3x3 m, lc_float s) noexcept { return m * (1.0f / s); } +[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float3x3 m, const lc_float3 v) noexcept { return v.x * m[0] + v.y * m[1] + v.z * m[2]; } +[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float3x3 lhs, const lc_float3x3 rhs) noexcept { return lc_float3x3{lhs * rhs[0], lhs * rhs[1], lhs * rhs[2]}; } +[[nodiscard]] __device__ inline constexpr auto operator+(const lc_float3x3 lhs, const lc_float3x3 rhs) noexcept { return lc_float3x3{lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2]}; } +[[nodiscard]] __device__ inline constexpr auto operator-(const lc_float3x3 lhs, const lc_float3x3 rhs) noexcept { return lc_float3x3{lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2]}; } + +[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float4x4 m, lc_float s) noexcept { return lc_float4x4{m[0] * s, m[1] * s, m[2] * s, m[3] * s}; } +[[nodiscard]] __device__ inline constexpr auto operator*(lc_float s, const lc_float4x4 m) noexcept { return m * s; } +[[nodiscard]] __device__ inline constexpr auto operator/(const lc_float4x4 m, lc_float s) noexcept { return m * (1.0f / s); } +[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float4x4 m, const lc_float4 v) noexcept { return v.x * m[0] + v.y * m[1] + v.z * m[2] + v.w * m[3]; } +[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float4x4 lhs, const lc_float4x4 rhs) noexcept { return lc_float4x4{lhs * rhs[0], lhs * rhs[1], lhs * rhs[2], lhs * rhs[3]}; } +[[nodiscard]] __device__ inline constexpr auto operator+(const lc_float4x4 lhs, const lc_float4x4 rhs) noexcept { return lc_float4x4{lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2], lhs[3] + rhs[3]}; } +[[nodiscard]] __device__ inline constexpr auto operator-(const lc_float4x4 lhs, const lc_float4x4 rhs) noexcept { return lc_float4x4{lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2], lhs[3] - rhs[3]}; } + +[[nodiscard]] __device__ inline constexpr auto lc_make_float2x2(lc_float s = 1.0f) noexcept { return lc_float2x2{lc_make_float2(s, 0.0f), lc_make_float2(0.0f, s)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2x2(lc_float m00, lc_float m01, lc_float m10, lc_float m11) noexcept { return lc_float2x2{lc_make_float2(m00, m01), lc_make_float2(m10, m11)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2x2(lc_float2 c0, lc_float2 c1) noexcept { return lc_float2x2{c0, c1}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2x2(lc_float2x2 m) noexcept { return m; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2x2(lc_float3x3 m) noexcept { return lc_float2x2{lc_make_float2(m[0]), lc_make_float2(m[1])}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float2x2(lc_float4x4 m) noexcept { return lc_float2x2{lc_make_float2(m[0]), lc_make_float2(m[1])}; } + +[[nodiscard]] __device__ inline constexpr auto lc_make_float3x3(lc_float s = 1.0f) noexcept { return lc_float3x3{lc_make_float3(s, 0.0f, 0.0f), lc_make_float3(0.0f, s, 0.0f), lc_make_float3(0.0f, 0.0f, s)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float3x3(lc_float m00, lc_float m01, lc_float m02, lc_float m10, lc_float m11, lc_float m12, lc_float m20, lc_float m21, lc_float m22) noexcept { return lc_float3x3{lc_make_float3(m00, m01, m02), lc_make_float3(m10, m11, m12), lc_make_float3(m20, m21, m22)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float3x3(lc_float3 c0, lc_float3 c1, lc_float3 c2) noexcept { return lc_float3x3{c0, c1, c2}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float3x3(lc_float2x2 m) noexcept { return lc_float3x3{lc_make_float3(m[0], 0.0f), lc_make_float3(m[1], 0.0f), lc_make_float3(0.0f, 0.0f, 1.0f)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float3x3(lc_float3x3 m) noexcept { return m; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float3x3(lc_float4x4 m) noexcept { return lc_float3x3{lc_make_float3(m[0]), lc_make_float3(m[1]), lc_make_float3(m[2])}; } + +[[nodiscard]] __device__ inline constexpr auto lc_make_float4x4(lc_float s = 1.0f) noexcept { return lc_float4x4{lc_make_float4(s, 0.0f, 0.0f, 0.0f), lc_make_float4(0.0f, s, 0.0f, 0.0f), lc_make_float4(0.0f, 0.0f, s, 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, s)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float4x4(lc_float m00, lc_float m01, lc_float m02, lc_float m03, lc_float m10, lc_float m11, lc_float m12, lc_float m13, lc_float m20, lc_float m21, lc_float m22, lc_float m23, lc_float m30, lc_float m31, lc_float m32, lc_float m33) noexcept { return lc_float4x4{lc_make_float4(m00, m01, m02, m03), lc_make_float4(m10, m11, m12, m13), lc_make_float4(m20, m21, m22, m23), lc_make_float4(m30, m31, m32, m33)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float4x4(lc_float4 c0, lc_float4 c1, lc_float4 c2, lc_float4 c3) noexcept { return lc_float4x4{c0, c1, c2, c3}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float4x4(lc_float2x2 m) noexcept { return lc_float4x4{lc_make_float4(m[0], 0.0f, 0.0f), lc_make_float4(m[1], 0.0f, 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, 1.0f)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float4x4(lc_float3x3 m) noexcept { return lc_float4x4{lc_make_float4(m[0], 0.0f), lc_make_float4(m[1], 0.0f), lc_make_float4(m[2], 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, 1.0f)}; } +[[nodiscard]] __device__ inline constexpr auto lc_make_float4x4(lc_float4x4 m) noexcept { return m; } + +template +[[nodiscard]] __device__ inline auto lc_select(T f, T t, bool p) noexcept { return p ? t : f; } +[[nodiscard]] __device__ inline auto lc_select(lc_short2 f, lc_short2 t, lc_bool2 p) noexcept { return lc_make_short2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } +[[nodiscard]] __device__ inline auto lc_select(lc_short3 f, lc_short3 t, lc_bool3 p) noexcept { return lc_make_short3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } +[[nodiscard]] __device__ inline auto lc_select(lc_short4 f, lc_short4 t, lc_bool4 p) noexcept { return lc_make_short4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } +[[nodiscard]] __device__ inline auto lc_select(lc_ushort2 f, lc_ushort2 t, lc_bool2 p) noexcept { return lc_make_ushort2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } +[[nodiscard]] __device__ inline auto lc_select(lc_ushort3 f, lc_ushort3 t, lc_bool3 p) noexcept { return lc_make_ushort3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } +[[nodiscard]] __device__ inline auto lc_select(lc_ushort4 f, lc_ushort4 t, lc_bool4 p) noexcept { return lc_make_ushort4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } +[[nodiscard]] __device__ inline auto lc_select(lc_int2 f, lc_int2 t, lc_bool2 p) noexcept { return lc_make_int2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } +[[nodiscard]] __device__ inline auto lc_select(lc_int3 f, lc_int3 t, lc_bool3 p) noexcept { return lc_make_int3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } +[[nodiscard]] __device__ inline auto lc_select(lc_int4 f, lc_int4 t, lc_bool4 p) noexcept { return lc_make_int4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } +[[nodiscard]] __device__ inline auto lc_select(lc_uint2 f, lc_uint2 t, lc_bool2 p) noexcept { return lc_make_uint2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } +[[nodiscard]] __device__ inline auto lc_select(lc_uint3 f, lc_uint3 t, lc_bool3 p) noexcept { return lc_make_uint3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } +[[nodiscard]] __device__ inline auto lc_select(lc_uint4 f, lc_uint4 t, lc_bool4 p) noexcept { return lc_make_uint4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } +[[nodiscard]] __device__ inline auto lc_select(lc_half2 f, lc_half2 t, lc_bool2 p) noexcept { return lc_make_half2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } +[[nodiscard]] __device__ inline auto lc_select(lc_half3 f, lc_half3 t, lc_bool3 p) noexcept { return lc_make_half3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } +[[nodiscard]] __device__ inline auto lc_select(lc_half4 f, lc_half4 t, lc_bool4 p) noexcept { return lc_make_half4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } +[[nodiscard]] __device__ inline auto lc_select(lc_float2 f, lc_float2 t, lc_bool2 p) noexcept { return lc_make_float2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } +[[nodiscard]] __device__ inline auto lc_select(lc_float3 f, lc_float3 t, lc_bool3 p) noexcept { return lc_make_float3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } +[[nodiscard]] __device__ inline auto lc_select(lc_float4 f, lc_float4 t, lc_bool4 p) noexcept { return lc_make_float4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } +[[nodiscard]] __device__ inline auto lc_select(lc_bool2 f, lc_bool2 t, lc_bool2 p) noexcept { return lc_make_bool2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } +[[nodiscard]] __device__ inline auto lc_select(lc_bool3 f, lc_bool3 t, lc_bool3 p) noexcept { return lc_make_bool3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } +[[nodiscard]] __device__ inline auto lc_select(lc_bool4 f, lc_bool4 t, lc_bool4 p) noexcept { return lc_make_bool4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } +[[nodiscard]] __device__ inline auto lc_select(lc_long2 f, lc_long2 t, lc_bool2 p) noexcept { return lc_make_long2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } +[[nodiscard]] __device__ inline auto lc_select(lc_long3 f, lc_long3 t, lc_bool3 p) noexcept { return lc_make_long3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } +[[nodiscard]] __device__ inline auto lc_select(lc_long4 f, lc_long4 t, lc_bool4 p) noexcept { return lc_make_long4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } +[[nodiscard]] __device__ inline auto lc_select(lc_ulong2 f, lc_ulong2 t, lc_bool2 p) noexcept { return lc_make_ulong2(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y)); } +[[nodiscard]] __device__ inline auto lc_select(lc_ulong3 f, lc_ulong3 t, lc_bool3 p) noexcept { return lc_make_ulong3(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z)); } +[[nodiscard]] __device__ inline auto lc_select(lc_ulong4 f, lc_ulong4 t, lc_bool4 p) noexcept { return lc_make_ulong4(lc_select(f.x, t.x, p.x), lc_select(f.y, t.y, p.y), lc_select(f.z, t.z, p.z), lc_select(f.w, t.w, p.w)); } + +[[nodiscard]] __device__ inline auto lc_outer_product(lc_float2 a, lc_float2 b) noexcept { return lc_float2x2(a * b.x, a * b.y); } +[[nodiscard]] __device__ inline auto lc_outer_product(lc_float3 a, lc_float3 b) noexcept { return lc_float3x3(a * b.x, a * b.y, a * b.z); } +[[nodiscard]] __device__ inline auto lc_outer_product(lc_float4 a, lc_float4 b) noexcept { return lc_float4x4(a * b.x, a * b.y, a * b.z, a * b.w); } +[[nodiscard]] __device__ inline lc_float lc_min(lc_float a, lc_float b) noexcept { return fminf(a, b); } +[[nodiscard]] __device__ inline lc_float2 lc_min(lc_float2 a, lc_float2 b) noexcept { return lc_make_float2(fminf(a.x, b.x), fminf(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_min(lc_float3 a, lc_float3 b) noexcept { return lc_make_float3(fminf(a.x, b.x), fminf(a.y, b.y), fminf(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_min(lc_float4 a, lc_float4 b) noexcept { return lc_make_float4(fminf(a.x, b.x), fminf(a.y, b.y), fminf(a.z, b.z), fminf(a.w, b.w)); } + +[[nodiscard]] __device__ inline lc_half lc_min(lc_half a, lc_half b) noexcept { return __hmin(a, b); } +[[nodiscard]] __device__ inline lc_half2 lc_min(lc_half2 a, lc_half2 b) noexcept { return lc_make_half2(__hmin(a.x, b.x), __hmin(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_min(lc_half3 a, lc_half3 b) noexcept { return lc_make_half3(__hmin(a.x, b.x), __hmin(a.y, b.y), __hmin(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_min(lc_half4 a, lc_half4 b) noexcept { return lc_make_half4(__hmin(a.x, b.x), __hmin(a.y, b.y), __hmin(a.z, b.z), __hmin(a.w, b.w)); } + +[[nodiscard]] __device__ inline lc_float lc_max(lc_float a, lc_float b) noexcept { return fmaxf(a, b); } +[[nodiscard]] __device__ inline lc_float2 lc_max(lc_float2 a, lc_float2 b) noexcept { return lc_make_float2(fmaxf(a.x, b.x), fmaxf(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_max(lc_float3 a, lc_float3 b) noexcept { return lc_make_float3(fmaxf(a.x, b.x), fmaxf(a.y, b.y), fmaxf(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_max(lc_float4 a, lc_float4 b) noexcept { return lc_make_float4(fmaxf(a.x, b.x), fmaxf(a.y, b.y), fmaxf(a.z, b.z), fmaxf(a.w, b.w)); } + +[[nodiscard]] __device__ inline lc_half lc_max(lc_half a, lc_half b) noexcept { return __hmax(a, b); } +[[nodiscard]] __device__ inline lc_half2 lc_max(lc_half2 a, lc_half2 b) noexcept { return lc_make_half2(__hmax(a.x, b.x), __hmax(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_max(lc_half3 a, lc_half3 b) noexcept { return lc_make_half3(__hmax(a.x, b.x), __hmax(a.y, b.y), __hmax(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_max(lc_half4 a, lc_half4 b) noexcept { return lc_make_half4(__hmax(a.x, b.x), __hmax(a.y, b.y), __hmax(a.z, b.z), __hmax(a.w, b.w)); } + +[[nodiscard]] __device__ inline lc_float lc_abs(lc_float x) noexcept { return fabsf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_abs(lc_float2 x) noexcept { return lc_make_float2(fabsf(x.x), fabsf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_abs(lc_float3 x) noexcept { return lc_make_float3(fabsf(x.x), fabsf(x.y), fabsf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_abs(lc_float4 x) noexcept { return lc_make_float4(fabsf(x.x), fabsf(x.y), fabsf(x.z), fabsf(x.w)); } + +[[nodiscard]] __device__ inline lc_int lc_abs(lc_int x) noexcept { return abs(x); } +[[nodiscard]] __device__ inline lc_int2 lc_abs(lc_int2 x) noexcept { return lc_make_int2(abs(x.x), abs(x.y)); } +[[nodiscard]] __device__ inline lc_int3 lc_abs(lc_int3 x) noexcept { return lc_make_int3(abs(x.x), abs(x.y), abs(x.z)); } +[[nodiscard]] __device__ inline lc_int4 lc_abs(lc_int4 x) noexcept { return lc_make_int4(abs(x.x), abs(x.y), abs(x.z), abs(x.w)); } + +[[nodiscard]] __device__ inline lc_long lc_abs(lc_long x) noexcept { return llabs(x); } +[[nodiscard]] __device__ inline lc_long2 lc_abs(lc_long2 x) noexcept { return lc_make_long2(llabs(x.x), llabs(x.y)); } +[[nodiscard]] __device__ inline lc_long3 lc_abs(lc_long3 x) noexcept { return lc_make_long3(llabs(x.x), llabs(x.y), llabs(x.z)); } +[[nodiscard]] __device__ inline lc_long4 lc_abs(lc_long4 x) noexcept { return lc_make_long4(llabs(x.x), llabs(x.y), llabs(x.z), llabs(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_abs(lc_half x) noexcept { return __habs(x); } +[[nodiscard]] __device__ inline lc_half2 lc_abs(lc_half2 x) noexcept { return lc_make_half2(__habs(x.x), __habs(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_abs(lc_half3 x) noexcept { return lc_make_half3(__habs(x.x), __habs(x.y), __habs(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_abs(lc_half4 x) noexcept { return lc_make_half4(__habs(x.x), __habs(x.y), __habs(x.z), __habs(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_acos(lc_half x) noexcept { return acosf(x); } +[[nodiscard]] __device__ inline lc_half2 lc_acos(lc_half2 x) noexcept { return lc_make_half2(acosf(x.x), acosf(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_acos(lc_half3 x) noexcept { return lc_make_half3(acosf(x.x), acosf(x.y), acosf(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_acos(lc_half4 x) noexcept { return lc_make_half4(acosf(x.x), acosf(x.y), acosf(x.z), acosf(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_acos(lc_float x) noexcept { return acosf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_acos(lc_float2 x) noexcept { return lc_make_float2(acosf(x.x), acosf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_acos(lc_float3 x) noexcept { return lc_make_float3(acosf(x.x), acosf(x.y), acosf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_acos(lc_float4 x) noexcept { return lc_make_float4(acosf(x.x), acosf(x.y), acosf(x.z), acosf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_asin(lc_half x) noexcept { return asinf(x); } +[[nodiscard]] __device__ inline lc_half2 lc_asin(lc_half2 x) noexcept { return lc_make_half2(asinf(x.x), asinf(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_asin(lc_half3 x) noexcept { return lc_make_half3(asinf(x.x), asinf(x.y), asinf(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_asin(lc_half4 x) noexcept { return lc_make_half4(asinf(x.x), asinf(x.y), asinf(x.z), asinf(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_asin(lc_float x) noexcept { return asinf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_asin(lc_float2 x) noexcept { return lc_make_float2(asinf(x.x), asinf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_asin(lc_float3 x) noexcept { return lc_make_float3(asinf(x.x), asinf(x.y), asinf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_asin(lc_float4 x) noexcept { return lc_make_float4(asinf(x.x), asinf(x.y), asinf(x.z), asinf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_atan(lc_half x) noexcept { return atanf(x); } +[[nodiscard]] __device__ inline lc_half2 lc_atan(lc_half2 x) noexcept { return lc_make_half2(atanf(x.x), atanf(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_atan(lc_half3 x) noexcept { return lc_make_half3(atanf(x.x), atanf(x.y), atanf(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_atan(lc_half4 x) noexcept { return lc_make_half4(atanf(x.x), atanf(x.y), atanf(x.z), atanf(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_atan(lc_float x) noexcept { return atanf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_atan(lc_float2 x) noexcept { return lc_make_float2(atanf(x.x), atanf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_atan(lc_float3 x) noexcept { return lc_make_float3(atanf(x.x), atanf(x.y), atanf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_atan(lc_float4 x) noexcept { return lc_make_float4(atanf(x.x), atanf(x.y), atanf(x.z), atanf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_acosh(lc_half x) noexcept { return acoshf(x); } +[[nodiscard]] __device__ inline lc_half2 lc_acosh(lc_half2 x) noexcept { return lc_make_half2(acoshf(x.x), acoshf(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_acosh(lc_half3 x) noexcept { return lc_make_half3(acoshf(x.x), acoshf(x.y), acoshf(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_acosh(lc_half4 x) noexcept { return lc_make_half4(acoshf(x.x), acoshf(x.y), acoshf(x.z), acoshf(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_acosh(lc_float x) noexcept { return acoshf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_acosh(lc_float2 x) noexcept { return lc_make_float2(acoshf(x.x), acoshf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_acosh(lc_float3 x) noexcept { return lc_make_float3(acoshf(x.x), acoshf(x.y), acoshf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_acosh(lc_float4 x) noexcept { return lc_make_float4(acoshf(x.x), acoshf(x.y), acoshf(x.z), acoshf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_asinh(lc_half x) noexcept { return asinhf(x); } +[[nodiscard]] __device__ inline lc_half2 lc_asinh(lc_half2 x) noexcept { return lc_make_half2(asinhf(x.x), asinhf(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_asinh(lc_half3 x) noexcept { return lc_make_half3(asinhf(x.x), asinhf(x.y), asinhf(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_asinh(lc_half4 x) noexcept { return lc_make_half4(asinhf(x.x), asinhf(x.y), asinhf(x.z), asinhf(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_asinh(lc_float x) noexcept { return asinhf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_asinh(lc_float2 x) noexcept { return lc_make_float2(asinhf(x.x), asinhf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_asinh(lc_float3 x) noexcept { return lc_make_float3(asinhf(x.x), asinhf(x.y), asinhf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_asinh(lc_float4 x) noexcept { return lc_make_float4(asinhf(x.x), asinhf(x.y), asinhf(x.z), asinhf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_atanh(lc_half x) noexcept { return atanhf(x); } +[[nodiscard]] __device__ inline lc_half2 lc_atanh(lc_half2 x) noexcept { return lc_make_half2(atanhf(x.x), atanhf(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_atanh(lc_half3 x) noexcept { return lc_make_half3(atanhf(x.x), atanhf(x.y), atanhf(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_atanh(lc_half4 x) noexcept { return lc_make_half4(atanhf(x.x), atanhf(x.y), atanhf(x.z), atanhf(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_atanh(lc_float x) noexcept { return atanhf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_atanh(lc_float2 x) noexcept { return lc_make_float2(atanhf(x.x), atanhf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_atanh(lc_float3 x) noexcept { return lc_make_float3(atanhf(x.x), atanhf(x.y), atanhf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_atanh(lc_float4 x) noexcept { return lc_make_float4(atanhf(x.x), atanhf(x.y), atanhf(x.z), atanhf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_atan2(lc_half y, lc_half x) noexcept { return atan2f(y, x); } +[[nodiscard]] __device__ inline lc_half2 lc_atan2(lc_half2 y, lc_half2 x) noexcept { return lc_make_half2(atan2f(y.x, x.x), atan2f(y.y, x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_atan2(lc_half3 y, lc_half3 x) noexcept { return lc_make_half3(atan2f(y.x, x.x), atan2f(y.y, x.y), atan2f(y.z, x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_atan2(lc_half4 y, lc_half4 x) noexcept { return lc_make_half4(atan2f(y.x, x.x), atan2f(y.y, x.y), atan2f(y.z, x.z), atan2f(y.w, x.w)); } +[[nodiscard]] __device__ inline lc_float lc_atan2(lc_float y, lc_float x) noexcept { return atan2f(y, x); } +[[nodiscard]] __device__ inline lc_float2 lc_atan2(lc_float2 y, lc_float2 x) noexcept { return lc_make_float2(atan2f(y.x, x.x), atan2f(y.y, x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_atan2(lc_float3 y, lc_float3 x) noexcept { return lc_make_float3(atan2f(y.x, x.x), atan2f(y.y, x.y), atan2f(y.z, x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_atan2(lc_float4 y, lc_float4 x) noexcept { return lc_make_float4(atan2f(y.x, x.x), atan2f(y.y, x.y), atan2f(y.z, x.z), atan2f(y.w, x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_cosh(lc_half x) noexcept { return coshf(x); } +[[nodiscard]] __device__ inline lc_half2 lc_cosh(lc_half2 x) noexcept { return lc_make_half2(coshf(x.x), coshf(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_cosh(lc_half3 x) noexcept { return lc_make_half3(coshf(x.x), coshf(x.y), coshf(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_cosh(lc_half4 x) noexcept { return lc_make_half4(coshf(x.x), coshf(x.y), coshf(x.z), coshf(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_cosh(lc_float x) noexcept { return coshf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_cosh(lc_float2 x) noexcept { return lc_make_float2(coshf(x.x), coshf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_cosh(lc_float3 x) noexcept { return lc_make_float3(coshf(x.x), coshf(x.y), coshf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_cosh(lc_float4 x) noexcept { return lc_make_float4(coshf(x.x), coshf(x.y), coshf(x.z), coshf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_sinh(lc_half x) noexcept { return sinhf(x); } +[[nodiscard]] __device__ inline lc_half2 lc_sinh(lc_half2 x) noexcept { return lc_make_half2(sinhf(x.x), sinhf(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_sinh(lc_half3 x) noexcept { return lc_make_half3(sinhf(x.x), sinhf(x.y), sinhf(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_sinh(lc_half4 x) noexcept { return lc_make_half4(sinhf(x.x), sinhf(x.y), sinhf(x.z), sinhf(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_sinh(lc_float x) noexcept { return sinhf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_sinh(lc_float2 x) noexcept { return lc_make_float2(sinhf(x.x), sinhf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_sinh(lc_float3 x) noexcept { return lc_make_float3(sinhf(x.x), sinhf(x.y), sinhf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_sinh(lc_float4 x) noexcept { return lc_make_float4(sinhf(x.x), sinhf(x.y), sinhf(x.z), sinhf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_tanh(lc_half x) noexcept { return tanhf(x); } +[[nodiscard]] __device__ inline lc_half2 lc_tanh(lc_half2 x) noexcept { return lc_make_half2(tanhf(x.x), tanhf(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_tanh(lc_half3 x) noexcept { return lc_make_half3(tanhf(x.x), tanhf(x.y), tanhf(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_tanh(lc_half4 x) noexcept { return lc_make_half4(tanhf(x.x), tanhf(x.y), tanhf(x.z), tanhf(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_tanh(lc_float x) noexcept { return tanhf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_tanh(lc_float2 x) noexcept { return lc_make_float2(tanhf(x.x), tanhf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_tanh(lc_float3 x) noexcept { return lc_make_float3(tanhf(x.x), tanhf(x.y), tanhf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_tanh(lc_float4 x) noexcept { return lc_make_float4(tanhf(x.x), tanhf(x.y), tanhf(x.z), tanhf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_cos(lc_half x) noexcept { return cosf(x); } +[[nodiscard]] __device__ inline lc_half2 lc_cos(lc_half2 x) noexcept { return lc_make_half2(cosf(x.x), cosf(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_cos(lc_half3 x) noexcept { return lc_make_half3(cosf(x.x), cosf(x.y), cosf(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_cos(lc_half4 x) noexcept { return lc_make_half4(cosf(x.x), cosf(x.y), cosf(x.z), cosf(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_cos(lc_float x) noexcept { return cosf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_cos(lc_float2 x) noexcept { return lc_make_float2(cosf(x.x), cosf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_cos(lc_float3 x) noexcept { return lc_make_float3(cosf(x.x), cosf(x.y), cosf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_cos(lc_float4 x) noexcept { return lc_make_float4(cosf(x.x), cosf(x.y), cosf(x.z), cosf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_sin(lc_half x) noexcept { return sinf(x); } +[[nodiscard]] __device__ inline lc_half2 lc_sin(lc_half2 x) noexcept { return lc_make_half2(sinf(x.x), sinf(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_sin(lc_half3 x) noexcept { return lc_make_half3(sinf(x.x), sinf(x.y), sinf(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_sin(lc_half4 x) noexcept { return lc_make_half4(sinf(x.x), sinf(x.y), sinf(x.z), sinf(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_sin(lc_float x) noexcept { return sinf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_sin(lc_float2 x) noexcept { return lc_make_float2(sinf(x.x), sinf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_sin(lc_float3 x) noexcept { return lc_make_float3(sinf(x.x), sinf(x.y), sinf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_sin(lc_float4 x) noexcept { return lc_make_float4(sinf(x.x), sinf(x.y), sinf(x.z), sinf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_tan(lc_half x) noexcept { return tanf(x); } +[[nodiscard]] __device__ inline lc_half2 lc_tan(lc_half2 x) noexcept { return lc_make_half2(tanf(x.x), tanf(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_tan(lc_half3 x) noexcept { return lc_make_half3(tanf(x.x), tanf(x.y), tanf(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_tan(lc_half4 x) noexcept { return lc_make_half4(tanf(x.x), tanf(x.y), tanf(x.z), tanf(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_tan(lc_float x) noexcept { return tanf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_tan(lc_float2 x) noexcept { return lc_make_float2(tanf(x.x), tanf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_tan(lc_float3 x) noexcept { return lc_make_float3(tanf(x.x), tanf(x.y), tanf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_tan(lc_float4 x) noexcept { return lc_make_float4(tanf(x.x), tanf(x.y), tanf(x.z), tanf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_exp(lc_half x) noexcept { return expf(x); } +[[nodiscard]] __device__ inline lc_half2 lc_exp(lc_half2 x) noexcept { return lc_make_half2(expf(x.x), expf(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_exp(lc_half3 x) noexcept { return lc_make_half3(expf(x.x), expf(x.y), expf(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_exp(lc_half4 x) noexcept { return lc_make_half4(expf(x.x), expf(x.y), expf(x.z), expf(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_exp(lc_float x) noexcept { return expf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_exp(lc_float2 x) noexcept { return lc_make_float2(expf(x.x), expf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_exp(lc_float3 x) noexcept { return lc_make_float3(expf(x.x), expf(x.y), expf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_exp(lc_float4 x) noexcept { return lc_make_float4(expf(x.x), expf(x.y), expf(x.z), expf(x.w)); } + +[[nodiscard]] __device__ inline lc_float lc_exp2(lc_float x) noexcept { return exp2f(x); } +[[nodiscard]] __device__ inline lc_float2 lc_exp2(lc_float2 x) noexcept { return lc_make_float2(exp2f(x.x), exp2f(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_exp2(lc_float3 x) noexcept { return lc_make_float3(exp2f(x.x), exp2f(x.y), exp2f(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_exp2(lc_float4 x) noexcept { return lc_make_float4(exp2f(x.x), exp2f(x.y), exp2f(x.z), exp2f(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_exp2(lc_half x) noexcept { return hexp2(x); } +[[nodiscard]] __device__ inline lc_half2 lc_exp2(lc_half2 x) noexcept { return lc_make_half2(hexp2(x.x), hexp2(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_exp2(lc_half3 x) noexcept { return lc_make_half3(hexp2(x.x), hexp2(x.y), hexp2(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_exp2(lc_half4 x) noexcept { return lc_make_half4(hexp2(x.x), hexp2(x.y), hexp2(x.z), hexp2(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_exp10(lc_half x) noexcept { return exp10f(x); } +[[nodiscard]] __device__ inline lc_half2 lc_exp10(lc_half2 x) noexcept { return lc_make_half2(exp10f(x.x), exp10f(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_exp10(lc_half3 x) noexcept { return lc_make_half3(exp10f(x.x), exp10f(x.y), exp10f(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_exp10(lc_half4 x) noexcept { return lc_make_half4(exp10f(x.x), exp10f(x.y), exp10f(x.z), exp10f(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_exp10(lc_float x) noexcept { return exp10f(x); } +[[nodiscard]] __device__ inline lc_float2 lc_exp10(lc_float2 x) noexcept { return lc_make_float2(exp10f(x.x), exp10f(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_exp10(lc_float3 x) noexcept { return lc_make_float3(exp10f(x.x), exp10f(x.y), exp10f(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_exp10(lc_float4 x) noexcept { return lc_make_float4(exp10f(x.x), exp10f(x.y), exp10f(x.z), exp10f(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_log(lc_half x) noexcept { return logf(x); } +[[nodiscard]] __device__ inline lc_half2 lc_log(lc_half2 x) noexcept { return lc_make_half2(logf(x.x), logf(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_log(lc_half3 x) noexcept { return lc_make_half3(logf(x.x), logf(x.y), logf(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_log(lc_half4 x) noexcept { return lc_make_half4(logf(x.x), logf(x.y), logf(x.z), logf(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_log(lc_float x) noexcept { return logf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_log(lc_float2 x) noexcept { return lc_make_float2(logf(x.x), logf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_log(lc_float3 x) noexcept { return lc_make_float3(logf(x.x), logf(x.y), logf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_log(lc_float4 x) noexcept { return lc_make_float4(logf(x.x), logf(x.y), logf(x.z), logf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_log2(lc_half x) noexcept { return log2f(x); } +[[nodiscard]] __device__ inline lc_half2 lc_log2(lc_half2 x) noexcept { return lc_make_half2(log2f(x.x), log2f(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_log2(lc_half3 x) noexcept { return lc_make_half3(log2f(x.x), log2f(x.y), log2f(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_log2(lc_half4 x) noexcept { return lc_make_half4(log2f(x.x), log2f(x.y), log2f(x.z), log2f(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_log2(lc_float x) noexcept { return log2f(x); } +[[nodiscard]] __device__ inline lc_float2 lc_log2(lc_float2 x) noexcept { return lc_make_float2(log2f(x.x), log2f(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_log2(lc_float3 x) noexcept { return lc_make_float3(log2f(x.x), log2f(x.y), log2f(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_log2(lc_float4 x) noexcept { return lc_make_float4(log2f(x.x), log2f(x.y), log2f(x.z), log2f(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_log10(lc_half x) noexcept { return log10f(x); } +[[nodiscard]] __device__ inline lc_half2 lc_log10(lc_half2 x) noexcept { return lc_make_half2(log10f(x.x), log10f(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_log10(lc_half3 x) noexcept { return lc_make_half3(log10f(x.x), log10f(x.y), log10f(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_log10(lc_half4 x) noexcept { return lc_make_half4(log10f(x.x), log10f(x.y), log10f(x.z), log10f(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_log10(lc_float x) noexcept { return log10f(x); } +[[nodiscard]] __device__ inline lc_float2 lc_log10(lc_float2 x) noexcept { return lc_make_float2(log10f(x.x), log10f(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_log10(lc_float3 x) noexcept { return lc_make_float3(log10f(x.x), log10f(x.y), log10f(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_log10(lc_float4 x) noexcept { return lc_make_float4(log10f(x.x), log10f(x.y), log10f(x.z), log10f(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_pow(lc_half x, lc_half a) noexcept { return powf_impl(x, a); } +[[nodiscard]] __device__ inline lc_half2 lc_pow(lc_half2 x, lc_half2 a) noexcept { return lc_make_half2(powf_impl(x.x, a.x), powf_impl(x.y, a.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_pow(lc_half3 x, lc_half3 a) noexcept { return lc_make_half3(powf_impl(x.x, a.x), powf_impl(x.y, a.y), powf_impl(x.z, a.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_pow(lc_half4 x, lc_half4 a) noexcept { return lc_make_half4(powf_impl(x.x, a.x), powf_impl(x.y, a.y), powf_impl(x.z, a.z), powf_impl(x.w, a.w)); } +[[nodiscard]] __device__ inline lc_float lc_pow(lc_float x, lc_float a) noexcept { return powf_impl(x, a); } +[[nodiscard]] __device__ inline lc_float2 lc_pow(lc_float2 x, lc_float2 a) noexcept { return lc_make_float2(powf_impl(x.x, a.x), powf_impl(x.y, a.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_pow(lc_float3 x, lc_float3 a) noexcept { return lc_make_float3(powf_impl(x.x, a.x), powf_impl(x.y, a.y), powf_impl(x.z, a.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_pow(lc_float4 x, lc_float4 a) noexcept { return lc_make_float4(powf_impl(x.x, a.x), powf_impl(x.y, a.y), powf_impl(x.z, a.z), powf_impl(x.w, a.w)); } + +[[nodiscard]] __device__ inline lc_half lc_powi(lc_half x, lc_half a) noexcept { return powi_impl(x, a); } +[[nodiscard]] __device__ inline lc_half2 lc_powi(lc_half2 x, lc_half2 a) noexcept { return lc_make_half2(powi_impl(x.x, a.x), powi_impl(x.y, a.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_powi(lc_half3 x, lc_half3 a) noexcept { return lc_make_half3(powi_impl(x.x, a.x), powi_impl(x.y, a.y), powi_impl(x.z, a.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_powi(lc_half4 x, lc_half4 a) noexcept { return lc_make_half4(powi_impl(x.x, a.x), powi_impl(x.y, a.y), powi_impl(x.z, a.z), powi_impl(x.w, a.w)); } +[[nodiscard]] __device__ inline lc_float lc_powi(lc_float x, lc_float a) noexcept { return powi_impl(x, a); } +[[nodiscard]] __device__ inline lc_float2 lc_powi(lc_float2 x, lc_float2 a) noexcept { return lc_make_float2(powi_impl(x.x, a.x), powi_impl(x.y, a.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_powi(lc_float3 x, lc_float3 a) noexcept { return lc_make_float3(powi_impl(x.x, a.x), powi_impl(x.y, a.y), powi_impl(x.z, a.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_powi(lc_float4 x, lc_float4 a) noexcept { return lc_make_float4(powi_impl(x.x, a.x), powi_impl(x.y, a.y), powi_impl(x.z, a.z), powi_impl(x.w, a.w)); } + +[[nodiscard]] __device__ inline lc_float lc_sqrt(lc_float x) noexcept { return sqrtf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_sqrt(lc_float2 x) noexcept { return lc_make_float2(sqrtf(x.x), sqrtf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_sqrt(lc_float3 x) noexcept { return lc_make_float3(sqrtf(x.x), sqrtf(x.y), sqrtf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_sqrt(lc_float4 x) noexcept { return lc_make_float4(sqrtf(x.x), sqrtf(x.y), sqrtf(x.z), sqrtf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_sqrt(lc_half x) noexcept { return hsqrt(x); } +[[nodiscard]] __device__ inline lc_half2 lc_sqrt(lc_half2 x) noexcept { return lc_make_half2(hsqrt(x.x), hsqrt(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_sqrt(lc_half3 x) noexcept { return lc_make_half3(hsqrt(x.x), hsqrt(x.y), hsqrt(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_sqrt(lc_half4 x) noexcept { return lc_make_half4(hsqrt(x.x), hsqrt(x.y), hsqrt(x.z), hsqrt(x.w)); } + +[[nodiscard]] __device__ inline lc_float lc_rsqrt(lc_float x) noexcept { return rsqrtf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_rsqrt(lc_float2 x) noexcept { return lc_make_float2(rsqrtf(x.x), rsqrtf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_rsqrt(lc_float3 x) noexcept { return lc_make_float3(rsqrtf(x.x), rsqrtf(x.y), rsqrtf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_rsqrt(lc_float4 x) noexcept { return lc_make_float4(rsqrtf(x.x), rsqrtf(x.y), rsqrtf(x.z), rsqrtf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_rsqrt(lc_half x) noexcept { return hrsqrt(x); } +[[nodiscard]] __device__ inline lc_half2 lc_rsqrt(lc_half2 x) noexcept { return lc_make_half2(hrsqrt(x.x), hrsqrt(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_rsqrt(lc_half3 x) noexcept { return lc_make_half3(hrsqrt(x.x), hrsqrt(x.y), hrsqrt(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_rsqrt(lc_half4 x) noexcept { return lc_make_half4(hrsqrt(x.x), hrsqrt(x.y), hrsqrt(x.z), hrsqrt(x.w)); } + +[[nodiscard]] __device__ inline lc_float lc_ceil(lc_float x) noexcept { return ceilf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_ceil(lc_float2 x) noexcept { return lc_make_float2(ceilf(x.x), ceilf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_ceil(lc_float3 x) noexcept { return lc_make_float3(ceilf(x.x), ceilf(x.y), ceilf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_ceil(lc_float4 x) noexcept { return lc_make_float4(ceilf(x.x), ceilf(x.y), ceilf(x.z), ceilf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_ceil(lc_half x) noexcept { return hceil(x); } +[[nodiscard]] __device__ inline lc_half2 lc_ceil(lc_half2 x) noexcept { return lc_make_half2(hceil(x.x), hceil(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_ceil(lc_half3 x) noexcept { return lc_make_half3(hceil(x.x), hceil(x.y), hceil(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_ceil(lc_half4 x) noexcept { return lc_make_half4(hceil(x.x), hceil(x.y), hceil(x.z), hceil(x.w)); } + +[[nodiscard]] __device__ inline lc_float lc_floor(lc_float x) noexcept { return floorf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_floor(lc_float2 x) noexcept { return lc_make_float2(floorf(x.x), floorf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_floor(lc_float3 x) noexcept { return lc_make_float3(floorf(x.x), floorf(x.y), floorf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_floor(lc_float4 x) noexcept { return lc_make_float4(floorf(x.x), floorf(x.y), floorf(x.z), floorf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_floor(lc_half x) noexcept { return hfloor(x); } +[[nodiscard]] __device__ inline lc_half2 lc_floor(lc_half2 x) noexcept { return lc_make_half2(hfloor(x.x), hfloor(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_floor(lc_half3 x) noexcept { return lc_make_half3(hfloor(x.x), hfloor(x.y), hfloor(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_floor(lc_half4 x) noexcept { return lc_make_half4(hfloor(x.x), hfloor(x.y), hfloor(x.z), hfloor(x.w)); } + +[[nodiscard]] __device__ inline lc_float lc_trunc(lc_float x) noexcept { return truncf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_trunc(lc_float2 x) noexcept { return lc_make_float2(truncf(x.x), truncf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_trunc(lc_float3 x) noexcept { return lc_make_float3(truncf(x.x), truncf(x.y), truncf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_trunc(lc_float4 x) noexcept { return lc_make_float4(truncf(x.x), truncf(x.y), truncf(x.z), truncf(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_trunc(lc_half x) noexcept { return htrunc(x); } +[[nodiscard]] __device__ inline lc_half2 lc_trunc(lc_half2 x) noexcept { return lc_make_half2(htrunc(x.x), htrunc(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_trunc(lc_half3 x) noexcept { return lc_make_half3(htrunc(x.x), htrunc(x.y), htrunc(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_trunc(lc_half4 x) noexcept { return lc_make_half4(htrunc(x.x), htrunc(x.y), htrunc(x.z), htrunc(x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_round(lc_half x) noexcept { return rintf(x); } +[[nodiscard]] __device__ inline lc_half2 lc_round(lc_half2 x) noexcept { return lc_make_half2(rintf(x.x), rintf(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_round(lc_half3 x) noexcept { return lc_make_half3(rintf(x.x), rintf(x.y), rintf(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_round(lc_half4 x) noexcept { return lc_make_half4(rintf(x.x), rintf(x.y), rintf(x.z), rintf(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_round(lc_float x) noexcept { return rintf(x); } +[[nodiscard]] __device__ inline lc_float2 lc_round(lc_float2 x) noexcept { return lc_make_float2(rintf(x.x), rintf(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_round(lc_float3 x) noexcept { return lc_make_float3(rintf(x.x), rintf(x.y), rintf(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_round(lc_float4 x) noexcept { return lc_make_float4(rintf(x.x), rintf(x.y), rintf(x.z), rintf(x.w)); } + +[[nodiscard]] __device__ inline lc_float lc_fma(lc_float x, lc_float y, lc_float z) noexcept { return fmaf(x, y, z); } +[[nodiscard]] __device__ inline lc_float2 lc_fma(lc_float2 x, lc_float2 y, lc_float2 z) noexcept { return lc_make_float2(fmaf(x.x, y.x, z.x), fmaf(x.y, y.y, z.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_fma(lc_float3 x, lc_float3 y, lc_float3 z) noexcept { return lc_make_float3(fmaf(x.x, y.x, z.x), fmaf(x.y, y.y, z.y), fmaf(x.z, y.z, z.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_fma(lc_float4 x, lc_float4 y, lc_float4 z) noexcept { return lc_make_float4(fmaf(x.x, y.x, z.x), fmaf(x.y, y.y, z.y), fmaf(x.z, y.z, z.z), fmaf(x.w, y.w, z.w)); } + +[[nodiscard]] __device__ inline lc_half lc_fma(lc_half x, lc_half y, lc_half z) noexcept { return __hfma(x, y, z); } +[[nodiscard]] __device__ inline lc_half2 lc_fma(lc_half2 x, lc_half2 y, lc_half2 z) noexcept { return lc_make_half2(__hfma(x.x, y.x, z.x), __hfma(x.y, y.y, z.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_fma(lc_half3 x, lc_half3 y, lc_half3 z) noexcept { return lc_make_half3(__hfma(x.x, y.x, z.x), __hfma(x.y, y.y, z.y), __hfma(x.z, y.z, z.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_fma(lc_half4 x, lc_half4 y, lc_half4 z) noexcept { return lc_make_half4(__hfma(x.x, y.x, z.x), __hfma(x.y, y.y, z.y), __hfma(x.z, y.z, z.z), __hfma(x.w, y.w, z.w)); } + + +[[nodiscard]] __device__ inline auto lc_copysign_impl(lc_half x, lc_half y) noexcept { + auto ux = __half_as_short(x); + auto uy = __half_as_short(y); + return __short_as_half((ux & 0x7fffu) | (uy & 0x8000u)); +} +[[nodiscard]] __device__ inline lc_float lc_copysign(lc_float x, lc_float y) noexcept { return copysignf(x, y); } +[[nodiscard]] __device__ inline lc_float2 lc_copysign(lc_float2 x, lc_float2 y) noexcept { return lc_make_float2(copysignf(x.x, y.x), copysignf(x.y, y.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_copysign(lc_float3 x, lc_float3 y) noexcept { return lc_make_float3(copysignf(x.x, y.x), copysignf(x.y, y.y), copysignf(x.z, y.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_copysign(lc_float4 x, lc_float4 y) noexcept { return lc_make_float4(copysignf(x.x, y.x), copysignf(x.y, y.y), copysignf(x.z, y.z), copysignf(x.w, y.w)); } + +[[nodiscard]] __device__ inline lc_half lc_copysign(lc_half x, lc_half y) noexcept { return lc_copysign_impl(x, y); } +[[nodiscard]] __device__ inline lc_half2 lc_copysign(lc_half2 x, lc_half2 y) noexcept { return lc_make_half2(lc_copysign_impl(x.x, y.x), lc_copysign_impl(x.y, y.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_copysign(lc_half3 x, lc_half3 y) noexcept { return lc_make_half3(lc_copysign_impl(x.x, y.x), lc_copysign_impl(x.y, y.y), lc_copysign_impl(x.z, y.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_copysign(lc_half4 x, lc_half4 y) noexcept { return lc_make_half4(lc_copysign_impl(x.x, y.x), lc_copysign_impl(x.y, y.y), lc_copysign_impl(x.z, y.z), lc_copysign_impl(x.w, y.w)); } + +[[nodiscard]] __device__ inline lc_bool lc_isinf(lc_float x) noexcept { return isinf_impl(x); } +[[nodiscard]] __device__ inline lc_bool2 lc_isinf(lc_float2 x) noexcept { return lc_make_bool2(isinf_impl(x.x), isinf_impl(x.y)); } +[[nodiscard]] __device__ inline lc_bool3 lc_isinf(lc_float3 x) noexcept { return lc_make_bool3(isinf_impl(x.x), isinf_impl(x.y), isinf_impl(x.z)); } +[[nodiscard]] __device__ inline lc_bool4 lc_isinf(lc_float4 x) noexcept { return lc_make_bool4(isinf_impl(x.x), isinf_impl(x.y), isinf_impl(x.z), isinf_impl(x.w)); } + +[[nodiscard]] __device__ inline lc_bool lc_isnan(lc_float x) noexcept { return isnan_impl(x); } +[[nodiscard]] __device__ inline lc_bool2 lc_isnan(lc_float2 x) noexcept { return lc_make_bool2(isnan_impl(x.x), isnan_impl(x.y)); } +[[nodiscard]] __device__ inline lc_bool3 lc_isnan(lc_float3 x) noexcept { return lc_make_bool3(isnan_impl(x.x), isnan_impl(x.y), isnan_impl(x.z)); } +[[nodiscard]] __device__ inline lc_bool4 lc_isnan(lc_float4 x) noexcept { return lc_make_bool4(isnan_impl(x.x), isnan_impl(x.y), isnan_impl(x.z), isnan_impl(x.w)); } + +[[nodiscard]] __device__ inline lc_bool lc_isinf(lc_half x) noexcept { return __hisinf(x); } +[[nodiscard]] __device__ inline lc_bool2 lc_isinf(lc_half2 x) noexcept { return lc_make_bool2(__hisinf(x.x), __hisinf(x.y)); } +[[nodiscard]] __device__ inline lc_bool3 lc_isinf(lc_half3 x) noexcept { return lc_make_bool3(__hisinf(x.x), __hisinf(x.y), __hisinf(x.z)); } +[[nodiscard]] __device__ inline lc_bool4 lc_isinf(lc_half4 x) noexcept { return lc_make_bool4(__hisinf(x.x), __hisinf(x.y), __hisinf(x.z), __hisinf(x.w)); } + +[[nodiscard]] __device__ inline lc_bool lc_isnan(lc_half x) noexcept { return __hisnan(x); } +[[nodiscard]] __device__ inline lc_bool2 lc_isnan(lc_half2 x) noexcept { return lc_make_bool2(__hisnan(x.x), __hisnan(x.y)); } +[[nodiscard]] __device__ inline lc_bool3 lc_isnan(lc_half3 x) noexcept { return lc_make_bool3(__hisnan(x.x), __hisnan(x.y), __hisnan(x.z)); } +[[nodiscard]] __device__ inline lc_bool4 lc_isnan(lc_half4 x) noexcept { return lc_make_bool4(__hisnan(x.x), __hisnan(x.y), __hisnan(x.z), __hisnan(x.w)); } + +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_short2 v) noexcept { return lc_short(v.x+v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_short2 v) noexcept { return lc_short(v.x*v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_short2 v) noexcept { return lc_short(lc_min(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_short2 v) noexcept { return lc_short(lc_max(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_short3 v) noexcept { return lc_short(v.x+v.y+v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_short3 v) noexcept { return lc_short(v.x*v.y*v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_short3 v) noexcept { return lc_short(lc_min(v.x, lc_min(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_short3 v) noexcept { return lc_short(lc_max(v.x, lc_max(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_short4 v) noexcept { return lc_short(v.x+v.y+v.z+v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_short4 v) noexcept { return lc_short(v.x*v.y*v.z*v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_short4 v) noexcept { return lc_short(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_short4 v) noexcept { return lc_short(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_ushort2 v) noexcept { return lc_ushort(v.x+v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_ushort2 v) noexcept { return lc_ushort(v.x*v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_ushort2 v) noexcept { return lc_ushort(lc_min(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_ushort2 v) noexcept { return lc_ushort(lc_max(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_ushort3 v) noexcept { return lc_ushort(v.x+v.y+v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_ushort3 v) noexcept { return lc_ushort(v.x*v.y*v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_ushort3 v) noexcept { return lc_ushort(lc_min(v.x, lc_min(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_ushort3 v) noexcept { return lc_ushort(lc_max(v.x, lc_max(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_ushort4 v) noexcept { return lc_ushort(v.x+v.y+v.z+v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_ushort4 v) noexcept { return lc_ushort(v.x*v.y*v.z*v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_ushort4 v) noexcept { return lc_ushort(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_ushort4 v) noexcept { return lc_ushort(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_int2 v) noexcept { return lc_int(v.x+v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_int2 v) noexcept { return lc_int(v.x*v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_int2 v) noexcept { return lc_int(lc_min(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_int2 v) noexcept { return lc_int(lc_max(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_int3 v) noexcept { return lc_int(v.x+v.y+v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_int3 v) noexcept { return lc_int(v.x*v.y*v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_int3 v) noexcept { return lc_int(lc_min(v.x, lc_min(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_int3 v) noexcept { return lc_int(lc_max(v.x, lc_max(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_int4 v) noexcept { return lc_int(v.x+v.y+v.z+v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_int4 v) noexcept { return lc_int(v.x*v.y*v.z*v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_int4 v) noexcept { return lc_int(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_int4 v) noexcept { return lc_int(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_uint2 v) noexcept { return lc_uint(v.x+v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_uint2 v) noexcept { return lc_uint(v.x*v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_uint2 v) noexcept { return lc_uint(lc_min(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_uint2 v) noexcept { return lc_uint(lc_max(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_uint3 v) noexcept { return lc_uint(v.x+v.y+v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_uint3 v) noexcept { return lc_uint(v.x*v.y*v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_uint3 v) noexcept { return lc_uint(lc_min(v.x, lc_min(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_uint3 v) noexcept { return lc_uint(lc_max(v.x, lc_max(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_uint4 v) noexcept { return lc_uint(v.x+v.y+v.z+v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_uint4 v) noexcept { return lc_uint(v.x*v.y*v.z*v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_uint4 v) noexcept { return lc_uint(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_uint4 v) noexcept { return lc_uint(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_half2 v) noexcept { return lc_half(v.x+v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_half2 v) noexcept { return lc_half(v.x*v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_half2 v) noexcept { return lc_half(lc_min(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_half2 v) noexcept { return lc_half(lc_max(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_half3 v) noexcept { return lc_half(v.x+v.y+v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_half3 v) noexcept { return lc_half(v.x*v.y*v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_half3 v) noexcept { return lc_half(lc_min(v.x, lc_min(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_half3 v) noexcept { return lc_half(lc_max(v.x, lc_max(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_half4 v) noexcept { return lc_half(v.x+v.y+v.z+v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_half4 v) noexcept { return lc_half(v.x*v.y*v.z*v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_half4 v) noexcept { return lc_half(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_half4 v) noexcept { return lc_half(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_float2 v) noexcept { return lc_float(v.x+v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_float2 v) noexcept { return lc_float(v.x*v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_float2 v) noexcept { return lc_float(lc_min(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_float2 v) noexcept { return lc_float(lc_max(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_float3 v) noexcept { return lc_float(v.x+v.y+v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_float3 v) noexcept { return lc_float(v.x*v.y*v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_float3 v) noexcept { return lc_float(lc_min(v.x, lc_min(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_float3 v) noexcept { return lc_float(lc_max(v.x, lc_max(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_float4 v) noexcept { return lc_float(v.x+v.y+v.z+v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_float4 v) noexcept { return lc_float(v.x*v.y*v.z*v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_float4 v) noexcept { return lc_float(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_float4 v) noexcept { return lc_float(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_long2 v) noexcept { return lc_long(v.x+v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_long2 v) noexcept { return lc_long(v.x*v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_long2 v) noexcept { return lc_long(lc_min(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_long2 v) noexcept { return lc_long(lc_max(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_long3 v) noexcept { return lc_long(v.x+v.y+v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_long3 v) noexcept { return lc_long(v.x*v.y*v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_long3 v) noexcept { return lc_long(lc_min(v.x, lc_min(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_long3 v) noexcept { return lc_long(lc_max(v.x, lc_max(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_long4 v) noexcept { return lc_long(v.x+v.y+v.z+v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_long4 v) noexcept { return lc_long(v.x*v.y*v.z*v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_long4 v) noexcept { return lc_long(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_long4 v) noexcept { return lc_long(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_ulong2 v) noexcept { return lc_ulong(v.x+v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_ulong2 v) noexcept { return lc_ulong(v.x*v.y); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_ulong2 v) noexcept { return lc_ulong(lc_min(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_ulong2 v) noexcept { return lc_ulong(lc_max(v.x, v.y)); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_ulong3 v) noexcept { return lc_ulong(v.x+v.y+v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_ulong3 v) noexcept { return lc_ulong(v.x*v.y*v.z); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_ulong3 v) noexcept { return lc_ulong(lc_min(v.x, lc_min(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_ulong3 v) noexcept { return lc_ulong(lc_max(v.x, lc_max(v.y, v.z))); } +[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_ulong4 v) noexcept { return lc_ulong(v.x+v.y+v.z+v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_ulong4 v) noexcept { return lc_ulong(v.x*v.y*v.z*v.w); } +[[nodiscard]] __device__ inline auto lc_reduce_min(lc_ulong4 v) noexcept { return lc_ulong(lc_min(v.x, lc_min(v.y, lc_min(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_reduce_max(lc_ulong4 v) noexcept { return lc_ulong(lc_max(v.x, lc_max(v.y, lc_max(v.z, v.w)))); } +[[nodiscard]] __device__ inline auto lc_min_impl(lc_short a, lc_short b) noexcept { return a < b ? a : b; } +[[nodiscard]] __device__ inline auto lc_max_impl(lc_short a, lc_short b) noexcept { return a > b ? a : b; } +[[nodiscard]] __device__ inline auto lc_min_impl(lc_ushort a, lc_ushort b) noexcept { return a < b ? a : b; } +[[nodiscard]] __device__ inline auto lc_max_impl(lc_ushort a, lc_ushort b) noexcept { return a > b ? a : b; } +[[nodiscard]] __device__ inline auto lc_min_impl(lc_int a, lc_int b) noexcept { return a < b ? a : b; } +[[nodiscard]] __device__ inline auto lc_max_impl(lc_int a, lc_int b) noexcept { return a > b ? a : b; } +[[nodiscard]] __device__ inline auto lc_min_impl(lc_uint a, lc_uint b) noexcept { return a < b ? a : b; } +[[nodiscard]] __device__ inline auto lc_max_impl(lc_uint a, lc_uint b) noexcept { return a > b ? a : b; } +[[nodiscard]] __device__ inline auto lc_min_impl(lc_long a, lc_long b) noexcept { return a < b ? a : b; } +[[nodiscard]] __device__ inline auto lc_max_impl(lc_long a, lc_long b) noexcept { return a > b ? a : b; } +[[nodiscard]] __device__ inline auto lc_min_impl(lc_ulong a, lc_ulong b) noexcept { return a < b ? a : b; } +[[nodiscard]] __device__ inline auto lc_max_impl(lc_ulong a, lc_ulong b) noexcept { return a > b ? a : b; } +[[nodiscard]] __device__ inline lc_short lc_min(lc_short a, lc_short b) noexcept { return lc_min_impl(a, b); } +[[nodiscard]] __device__ inline lc_short2 lc_min(lc_short2 a, lc_short2 b) noexcept { return lc_make_short2(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_short3 lc_min(lc_short3 a, lc_short3 b) noexcept { return lc_make_short3(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_short4 lc_min(lc_short4 a, lc_short4 b) noexcept { return lc_make_short4(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z), lc_min_impl(a.w, b.w)); } +[[nodiscard]] __device__ inline lc_ushort lc_min(lc_ushort a, lc_ushort b) noexcept { return lc_min_impl(a, b); } +[[nodiscard]] __device__ inline lc_ushort2 lc_min(lc_ushort2 a, lc_ushort2 b) noexcept { return lc_make_ushort2(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_ushort3 lc_min(lc_ushort3 a, lc_ushort3 b) noexcept { return lc_make_ushort3(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_ushort4 lc_min(lc_ushort4 a, lc_ushort4 b) noexcept { return lc_make_ushort4(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z), lc_min_impl(a.w, b.w)); } +[[nodiscard]] __device__ inline lc_int lc_min(lc_int a, lc_int b) noexcept { return lc_min_impl(a, b); } +[[nodiscard]] __device__ inline lc_int2 lc_min(lc_int2 a, lc_int2 b) noexcept { return lc_make_int2(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_int3 lc_min(lc_int3 a, lc_int3 b) noexcept { return lc_make_int3(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_int4 lc_min(lc_int4 a, lc_int4 b) noexcept { return lc_make_int4(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z), lc_min_impl(a.w, b.w)); } +[[nodiscard]] __device__ inline lc_uint lc_min(lc_uint a, lc_uint b) noexcept { return lc_min_impl(a, b); } +[[nodiscard]] __device__ inline lc_uint2 lc_min(lc_uint2 a, lc_uint2 b) noexcept { return lc_make_uint2(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_uint3 lc_min(lc_uint3 a, lc_uint3 b) noexcept { return lc_make_uint3(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_uint4 lc_min(lc_uint4 a, lc_uint4 b) noexcept { return lc_make_uint4(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z), lc_min_impl(a.w, b.w)); } +[[nodiscard]] __device__ inline lc_long lc_min(lc_long a, lc_long b) noexcept { return lc_min_impl(a, b); } +[[nodiscard]] __device__ inline lc_long2 lc_min(lc_long2 a, lc_long2 b) noexcept { return lc_make_long2(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_long3 lc_min(lc_long3 a, lc_long3 b) noexcept { return lc_make_long3(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_long4 lc_min(lc_long4 a, lc_long4 b) noexcept { return lc_make_long4(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z), lc_min_impl(a.w, b.w)); } +[[nodiscard]] __device__ inline lc_ulong lc_min(lc_ulong a, lc_ulong b) noexcept { return lc_min_impl(a, b); } +[[nodiscard]] __device__ inline lc_ulong2 lc_min(lc_ulong2 a, lc_ulong2 b) noexcept { return lc_make_ulong2(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_ulong3 lc_min(lc_ulong3 a, lc_ulong3 b) noexcept { return lc_make_ulong3(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_ulong4 lc_min(lc_ulong4 a, lc_ulong4 b) noexcept { return lc_make_ulong4(lc_min_impl(a.x, b.x), lc_min_impl(a.y, b.y), lc_min_impl(a.z, b.z), lc_min_impl(a.w, b.w)); } + +[[nodiscard]] __device__ inline lc_short lc_max(lc_short a, lc_short b) noexcept { return lc_max_impl(a, b); } +[[nodiscard]] __device__ inline lc_short2 lc_max(lc_short2 a, lc_short2 b) noexcept { return lc_make_short2(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_short3 lc_max(lc_short3 a, lc_short3 b) noexcept { return lc_make_short3(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_short4 lc_max(lc_short4 a, lc_short4 b) noexcept { return lc_make_short4(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z), lc_max_impl(a.w, b.w)); } +[[nodiscard]] __device__ inline lc_ushort lc_max(lc_ushort a, lc_ushort b) noexcept { return lc_max_impl(a, b); } +[[nodiscard]] __device__ inline lc_ushort2 lc_max(lc_ushort2 a, lc_ushort2 b) noexcept { return lc_make_ushort2(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_ushort3 lc_max(lc_ushort3 a, lc_ushort3 b) noexcept { return lc_make_ushort3(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_ushort4 lc_max(lc_ushort4 a, lc_ushort4 b) noexcept { return lc_make_ushort4(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z), lc_max_impl(a.w, b.w)); } +[[nodiscard]] __device__ inline lc_int lc_max(lc_int a, lc_int b) noexcept { return lc_max_impl(a, b); } +[[nodiscard]] __device__ inline lc_int2 lc_max(lc_int2 a, lc_int2 b) noexcept { return lc_make_int2(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_int3 lc_max(lc_int3 a, lc_int3 b) noexcept { return lc_make_int3(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_int4 lc_max(lc_int4 a, lc_int4 b) noexcept { return lc_make_int4(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z), lc_max_impl(a.w, b.w)); } +[[nodiscard]] __device__ inline lc_uint lc_max(lc_uint a, lc_uint b) noexcept { return lc_max_impl(a, b); } +[[nodiscard]] __device__ inline lc_uint2 lc_max(lc_uint2 a, lc_uint2 b) noexcept { return lc_make_uint2(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_uint3 lc_max(lc_uint3 a, lc_uint3 b) noexcept { return lc_make_uint3(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_uint4 lc_max(lc_uint4 a, lc_uint4 b) noexcept { return lc_make_uint4(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z), lc_max_impl(a.w, b.w)); } +[[nodiscard]] __device__ inline lc_long lc_max(lc_long a, lc_long b) noexcept { return lc_max_impl(a, b); } +[[nodiscard]] __device__ inline lc_long2 lc_max(lc_long2 a, lc_long2 b) noexcept { return lc_make_long2(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_long3 lc_max(lc_long3 a, lc_long3 b) noexcept { return lc_make_long3(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_long4 lc_max(lc_long4 a, lc_long4 b) noexcept { return lc_make_long4(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z), lc_max_impl(a.w, b.w)); } +[[nodiscard]] __device__ inline lc_ulong lc_max(lc_ulong a, lc_ulong b) noexcept { return lc_max_impl(a, b); } +[[nodiscard]] __device__ inline lc_ulong2 lc_max(lc_ulong2 a, lc_ulong2 b) noexcept { return lc_make_ulong2(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y)); } +[[nodiscard]] __device__ inline lc_ulong3 lc_max(lc_ulong3 a, lc_ulong3 b) noexcept { return lc_make_ulong3(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z)); } +[[nodiscard]] __device__ inline lc_ulong4 lc_max(lc_ulong4 a, lc_ulong4 b) noexcept { return lc_make_ulong4(lc_max_impl(a.x, b.x), lc_max_impl(a.y, b.y), lc_max_impl(a.z, b.z), lc_max_impl(a.w, b.w)); } + +[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_short v, lc_short lo, lc_short hi) noexcept { return lc_min(lc_max(v, lo), hi); } +[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_ushort v, lc_ushort lo, lc_ushort hi) noexcept { return lc_min(lc_max(v, lo), hi); } +[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_int v, lc_int lo, lc_int hi) noexcept { return lc_min(lc_max(v, lo), hi); } +[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_uint v, lc_uint lo, lc_uint hi) noexcept { return lc_min(lc_max(v, lo), hi); } +[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_half v, lc_half lo, lc_half hi) noexcept { return lc_min(lc_max(v, lo), hi); } +[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_float v, lc_float lo, lc_float hi) noexcept { return lc_min(lc_max(v, lo), hi); } +[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_long v, lc_long lo, lc_long hi) noexcept { return lc_min(lc_max(v, lo), hi); } +[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_ulong v, lc_ulong lo, lc_ulong hi) noexcept { return lc_min(lc_max(v, lo), hi); } +[[nodiscard]] __device__ inline lc_short lc_clamp(lc_short v, lc_short lo, lc_short hi) noexcept { return lc_clamp_impl(v, lo, hi); } +[[nodiscard]] __device__ inline lc_short2 lc_clamp(lc_short2 v, lc_short2 lo, lc_short2 hi) noexcept { return lc_make_short2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } +[[nodiscard]] __device__ inline lc_short3 lc_clamp(lc_short3 v, lc_short3 lo, lc_short3 hi) noexcept { return lc_make_short3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } +[[nodiscard]] __device__ inline lc_short4 lc_clamp(lc_short4 v, lc_short4 lo, lc_short4 hi) noexcept { return lc_make_short4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } +[[nodiscard]] __device__ inline lc_ushort lc_clamp(lc_ushort v, lc_ushort lo, lc_ushort hi) noexcept { return lc_clamp_impl(v, lo, hi); } +[[nodiscard]] __device__ inline lc_ushort2 lc_clamp(lc_ushort2 v, lc_ushort2 lo, lc_ushort2 hi) noexcept { return lc_make_ushort2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } +[[nodiscard]] __device__ inline lc_ushort3 lc_clamp(lc_ushort3 v, lc_ushort3 lo, lc_ushort3 hi) noexcept { return lc_make_ushort3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } +[[nodiscard]] __device__ inline lc_ushort4 lc_clamp(lc_ushort4 v, lc_ushort4 lo, lc_ushort4 hi) noexcept { return lc_make_ushort4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } +[[nodiscard]] __device__ inline lc_int lc_clamp(lc_int v, lc_int lo, lc_int hi) noexcept { return lc_clamp_impl(v, lo, hi); } +[[nodiscard]] __device__ inline lc_int2 lc_clamp(lc_int2 v, lc_int2 lo, lc_int2 hi) noexcept { return lc_make_int2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } +[[nodiscard]] __device__ inline lc_int3 lc_clamp(lc_int3 v, lc_int3 lo, lc_int3 hi) noexcept { return lc_make_int3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } +[[nodiscard]] __device__ inline lc_int4 lc_clamp(lc_int4 v, lc_int4 lo, lc_int4 hi) noexcept { return lc_make_int4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } +[[nodiscard]] __device__ inline lc_uint lc_clamp(lc_uint v, lc_uint lo, lc_uint hi) noexcept { return lc_clamp_impl(v, lo, hi); } +[[nodiscard]] __device__ inline lc_uint2 lc_clamp(lc_uint2 v, lc_uint2 lo, lc_uint2 hi) noexcept { return lc_make_uint2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } +[[nodiscard]] __device__ inline lc_uint3 lc_clamp(lc_uint3 v, lc_uint3 lo, lc_uint3 hi) noexcept { return lc_make_uint3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } +[[nodiscard]] __device__ inline lc_uint4 lc_clamp(lc_uint4 v, lc_uint4 lo, lc_uint4 hi) noexcept { return lc_make_uint4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } +[[nodiscard]] __device__ inline lc_long lc_clamp(lc_long v, lc_long lo, lc_long hi) noexcept { return lc_clamp_impl(v, lo, hi); } +[[nodiscard]] __device__ inline lc_long2 lc_clamp(lc_long2 v, lc_long2 lo, lc_long2 hi) noexcept { return lc_make_long2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } +[[nodiscard]] __device__ inline lc_long3 lc_clamp(lc_long3 v, lc_long3 lo, lc_long3 hi) noexcept { return lc_make_long3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } +[[nodiscard]] __device__ inline lc_long4 lc_clamp(lc_long4 v, lc_long4 lo, lc_long4 hi) noexcept { return lc_make_long4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } +[[nodiscard]] __device__ inline lc_ulong lc_clamp(lc_ulong v, lc_ulong lo, lc_ulong hi) noexcept { return lc_clamp_impl(v, lo, hi); } +[[nodiscard]] __device__ inline lc_ulong2 lc_clamp(lc_ulong2 v, lc_ulong2 lo, lc_ulong2 hi) noexcept { return lc_make_ulong2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } +[[nodiscard]] __device__ inline lc_ulong3 lc_clamp(lc_ulong3 v, lc_ulong3 lo, lc_ulong3 hi) noexcept { return lc_make_ulong3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } +[[nodiscard]] __device__ inline lc_ulong4 lc_clamp(lc_ulong4 v, lc_ulong4 lo, lc_ulong4 hi) noexcept { return lc_make_ulong4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } +[[nodiscard]] __device__ inline lc_half lc_clamp(lc_half v, lc_half lo, lc_half hi) noexcept { return lc_clamp_impl(v, lo, hi); } +[[nodiscard]] __device__ inline lc_half2 lc_clamp(lc_half2 v, lc_half2 lo, lc_half2 hi) noexcept { return lc_make_half2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_clamp(lc_half3 v, lc_half3 lo, lc_half3 hi) noexcept { return lc_make_half3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_clamp(lc_half4 v, lc_half4 lo, lc_half4 hi) noexcept { return lc_make_half4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } +[[nodiscard]] __device__ inline lc_float lc_clamp(lc_float v, lc_float lo, lc_float hi) noexcept { return lc_clamp_impl(v, lo, hi); } +[[nodiscard]] __device__ inline lc_float2 lc_clamp(lc_float2 v, lc_float2 lo, lc_float2 hi) noexcept { return lc_make_float2(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_clamp(lc_float3 v, lc_float3 lo, lc_float3 hi) noexcept { return lc_make_float3(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_clamp(lc_float4 v, lc_float4 lo, lc_float4 hi) noexcept { return lc_make_float4(lc_clamp_impl(v.x, lo.x, hi.x), lc_clamp_impl(v.y, lo.y, hi.y), lc_clamp_impl(v.z, lo.z, hi.z), lc_clamp_impl(v.w, lo.w, hi.w)); } + +[[nodiscard]] __device__ inline auto lc_lerp_impl(lc_half a, lc_half b, lc_half t) noexcept { return t * (b - a) + a; } +[[nodiscard]] __device__ inline auto lc_saturate(lc_half x) noexcept { return lc_clamp(x, lc_half(0.0f), lc_half(1.0f)); } +[[nodiscard]] __device__ inline auto lc_saturate(lc_half2 x) noexcept { return lc_clamp(x, lc_make_half2(0.0f), lc_make_half2(1.0f)); } +[[nodiscard]] __device__ inline auto lc_saturate(lc_half3 x) noexcept { return lc_clamp(x, lc_make_half3(0.0f), lc_make_half3(1.0f)); } +[[nodiscard]] __device__ inline auto lc_saturate(lc_half4 x) noexcept { return lc_clamp(x, lc_make_half4(0.0f), lc_make_half4(1.0f)); } + +[[nodiscard]] __device__ inline auto lc_degrees_impl(lc_half rad) noexcept { return rad * (lc_half)(180.0f * 0.318309886183790671537767526745028724f); } +[[nodiscard]] __device__ inline auto lc_radians_impl(lc_half deg) noexcept { return deg * (lc_half)(3.14159265358979323846264338327950288f / 180.0f); } +[[nodiscard]] __device__ inline auto lc_step_impl(lc_half edge, lc_half x) noexcept { return lc_select(lc_half(1.f), lc_half(0.f), x < edge); } +[[nodiscard]] __device__ inline auto lc_smoothstep_impl(lc_half edge0, lc_half edge1, lc_half x) noexcept { + auto t = lc_clamp((x - edge0) / (edge1 - edge0), lc_half(0.0f), lc_half(1.0f)); + return t * t * (lc_half(3.f) - lc_half(2.f) * t); +} +[[nodiscard]] __device__ inline auto lc_mod_impl(lc_half x, lc_half y) noexcept { return x - y * lc_floor(x / y); } +[[nodiscard]] __device__ inline auto lc_fmod_impl(lc_half x, lc_half y) noexcept { return x - y * lc_trunc(x / y); } +[[nodiscard]] __device__ inline auto lc_fract_impl(lc_half x) noexcept { return x - lc_floor(x); } +[[nodiscard]] __device__ inline auto lc_lerp_impl(lc_float a, lc_float b, lc_float t) noexcept { return t * (b - a) + a; } +[[nodiscard]] __device__ inline auto lc_saturate(lc_float x) noexcept { return lc_clamp(x, lc_float(0.0f), lc_float(1.0f)); } +[[nodiscard]] __device__ inline auto lc_saturate(lc_float2 x) noexcept { return lc_clamp(x, lc_make_float2(0.0f), lc_make_float2(1.0f)); } +[[nodiscard]] __device__ inline auto lc_saturate(lc_float3 x) noexcept { return lc_clamp(x, lc_make_float3(0.0f), lc_make_float3(1.0f)); } +[[nodiscard]] __device__ inline auto lc_saturate(lc_float4 x) noexcept { return lc_clamp(x, lc_make_float4(0.0f), lc_make_float4(1.0f)); } + +[[nodiscard]] __device__ inline auto lc_degrees_impl(lc_float rad) noexcept { return rad * (lc_float)(180.0f * 0.318309886183790671537767526745028724f); } +[[nodiscard]] __device__ inline auto lc_radians_impl(lc_float deg) noexcept { return deg * (lc_float)(3.14159265358979323846264338327950288f / 180.0f); } +[[nodiscard]] __device__ inline auto lc_step_impl(lc_float edge, lc_float x) noexcept { return lc_select(lc_float(1.f), lc_float(0.f), x < edge); } +[[nodiscard]] __device__ inline auto lc_smoothstep_impl(lc_float edge0, lc_float edge1, lc_float x) noexcept { + auto t = lc_clamp((x - edge0) / (edge1 - edge0), lc_float(0.0f), lc_float(1.0f)); + return t * t * (lc_float(3.f) - lc_float(2.f) * t); +} +[[nodiscard]] __device__ inline auto lc_mod_impl(lc_float x, lc_float y) noexcept { return x - y * lc_floor(x / y); } +[[nodiscard]] __device__ inline auto lc_fmod_impl(lc_float x, lc_float y) noexcept { return fmodf(x, y); } +[[nodiscard]] __device__ inline auto lc_fract_impl(lc_float x) noexcept { return x - lc_floor(x); } +[[nodiscard]] __device__ inline lc_half lc_lerp(lc_half a, lc_half b, lc_half t) noexcept { return lc_lerp_impl(a, b, t); } +[[nodiscard]] __device__ inline lc_half2 lc_lerp(lc_half2 a, lc_half2 b, lc_half2 t) noexcept { return lc_make_half2(lc_lerp_impl(a.x, b.x, t.x), lc_lerp_impl(a.y, b.y, t.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_lerp(lc_half3 a, lc_half3 b, lc_half3 t) noexcept { return lc_make_half3(lc_lerp_impl(a.x, b.x, t.x), lc_lerp_impl(a.y, b.y, t.y), lc_lerp_impl(a.z, b.z, t.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_lerp(lc_half4 a, lc_half4 b, lc_half4 t) noexcept { return lc_make_half4(lc_lerp_impl(a.x, b.x, t.x), lc_lerp_impl(a.y, b.y, t.y), lc_lerp_impl(a.z, b.z, t.z), lc_lerp_impl(a.w, b.w, t.w)); } +[[nodiscard]] __device__ inline lc_float lc_lerp(lc_float a, lc_float b, lc_float t) noexcept { return lc_lerp_impl(a, b, t); } +[[nodiscard]] __device__ inline lc_float2 lc_lerp(lc_float2 a, lc_float2 b, lc_float2 t) noexcept { return lc_make_float2(lc_lerp_impl(a.x, b.x, t.x), lc_lerp_impl(a.y, b.y, t.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_lerp(lc_float3 a, lc_float3 b, lc_float3 t) noexcept { return lc_make_float3(lc_lerp_impl(a.x, b.x, t.x), lc_lerp_impl(a.y, b.y, t.y), lc_lerp_impl(a.z, b.z, t.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_lerp(lc_float4 a, lc_float4 b, lc_float4 t) noexcept { return lc_make_float4(lc_lerp_impl(a.x, b.x, t.x), lc_lerp_impl(a.y, b.y, t.y), lc_lerp_impl(a.z, b.z, t.z), lc_lerp_impl(a.w, b.w, t.w)); } + +[[nodiscard]] __device__ inline lc_half lc_degrees(lc_half rad) noexcept { return lc_degrees_impl(rad); } +[[nodiscard]] __device__ inline lc_half2 lc_degrees(lc_half2 rad) noexcept { return lc_make_half2(lc_degrees_impl(rad.x), lc_degrees_impl(rad.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_degrees(lc_half3 rad) noexcept { return lc_make_half3(lc_degrees_impl(rad.x), lc_degrees_impl(rad.y), lc_degrees_impl(rad.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_degrees(lc_half4 rad) noexcept { return lc_make_half4(lc_degrees_impl(rad.x), lc_degrees_impl(rad.y), lc_degrees_impl(rad.z), lc_degrees_impl(rad.w)); } +[[nodiscard]] __device__ inline lc_float lc_degrees(lc_float rad) noexcept { return lc_degrees_impl(rad); } +[[nodiscard]] __device__ inline lc_float2 lc_degrees(lc_float2 rad) noexcept { return lc_make_float2(lc_degrees_impl(rad.x), lc_degrees_impl(rad.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_degrees(lc_float3 rad) noexcept { return lc_make_float3(lc_degrees_impl(rad.x), lc_degrees_impl(rad.y), lc_degrees_impl(rad.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_degrees(lc_float4 rad) noexcept { return lc_make_float4(lc_degrees_impl(rad.x), lc_degrees_impl(rad.y), lc_degrees_impl(rad.z), lc_degrees_impl(rad.w)); } + +[[nodiscard]] __device__ inline lc_half lc_radians(lc_half deg) noexcept { return lc_radians_impl(deg); } +[[nodiscard]] __device__ inline lc_half2 lc_radians(lc_half2 deg) noexcept { return lc_make_half2(lc_radians_impl(deg.x), lc_radians_impl(deg.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_radians(lc_half3 deg) noexcept { return lc_make_half3(lc_radians_impl(deg.x), lc_radians_impl(deg.y), lc_radians_impl(deg.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_radians(lc_half4 deg) noexcept { return lc_make_half4(lc_radians_impl(deg.x), lc_radians_impl(deg.y), lc_radians_impl(deg.z), lc_radians_impl(deg.w)); } +[[nodiscard]] __device__ inline lc_float lc_radians(lc_float deg) noexcept { return lc_radians_impl(deg); } +[[nodiscard]] __device__ inline lc_float2 lc_radians(lc_float2 deg) noexcept { return lc_make_float2(lc_radians_impl(deg.x), lc_radians_impl(deg.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_radians(lc_float3 deg) noexcept { return lc_make_float3(lc_radians_impl(deg.x), lc_radians_impl(deg.y), lc_radians_impl(deg.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_radians(lc_float4 deg) noexcept { return lc_make_float4(lc_radians_impl(deg.x), lc_radians_impl(deg.y), lc_radians_impl(deg.z), lc_radians_impl(deg.w)); } + +[[nodiscard]] __device__ inline lc_half lc_step(lc_half edge, lc_half x) noexcept { return lc_step_impl(edge, x); } +[[nodiscard]] __device__ inline lc_half2 lc_step(lc_half2 edge, lc_half2 x) noexcept { return lc_make_half2(lc_step_impl(edge.x, x.x), lc_step_impl(edge.y, x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_step(lc_half3 edge, lc_half3 x) noexcept { return lc_make_half3(lc_step_impl(edge.x, x.x), lc_step_impl(edge.y, x.y), lc_step_impl(edge.z, x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_step(lc_half4 edge, lc_half4 x) noexcept { return lc_make_half4(lc_step_impl(edge.x, x.x), lc_step_impl(edge.y, x.y), lc_step_impl(edge.z, x.z), lc_step_impl(edge.w, x.w)); } +[[nodiscard]] __device__ inline lc_float lc_step(lc_float edge, lc_float x) noexcept { return lc_step_impl(edge, x); } +[[nodiscard]] __device__ inline lc_float2 lc_step(lc_float2 edge, lc_float2 x) noexcept { return lc_make_float2(lc_step_impl(edge.x, x.x), lc_step_impl(edge.y, x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_step(lc_float3 edge, lc_float3 x) noexcept { return lc_make_float3(lc_step_impl(edge.x, x.x), lc_step_impl(edge.y, x.y), lc_step_impl(edge.z, x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_step(lc_float4 edge, lc_float4 x) noexcept { return lc_make_float4(lc_step_impl(edge.x, x.x), lc_step_impl(edge.y, x.y), lc_step_impl(edge.z, x.z), lc_step_impl(edge.w, x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_smoothstep(lc_half e0, lc_half e1, lc_half x) noexcept { return lc_smoothstep_impl(e0, e1, x); } +[[nodiscard]] __device__ inline lc_half2 lc_smoothstep(lc_half2 e0, lc_half2 e1, lc_half2 x) noexcept { return lc_make_half2(lc_smoothstep_impl(e0.x, e1.x, x.x), lc_smoothstep_impl(e0.y, e1.y, x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_smoothstep(lc_half3 e0, lc_half3 e1, lc_half3 x) noexcept { return lc_make_half3(lc_smoothstep_impl(e0.x, e1.x, x.x), lc_smoothstep_impl(e0.y, e1.y, x.y), lc_smoothstep_impl(e0.z, e1.z, x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_smoothstep(lc_half4 e0, lc_half4 e1, lc_half4 x) noexcept { return lc_make_half4(lc_smoothstep_impl(e0.x, e1.x, x.x), lc_smoothstep_impl(e0.y, e1.y, x.y), lc_smoothstep_impl(e0.z, e1.z, x.z), lc_smoothstep_impl(e0.w, e1.w, x.w)); } +[[nodiscard]] __device__ inline lc_float lc_smoothstep(lc_float e0, lc_float e1, lc_float x) noexcept { return lc_smoothstep_impl(e0, e1, x); } +[[nodiscard]] __device__ inline lc_float2 lc_smoothstep(lc_float2 e0, lc_float2 e1, lc_float2 x) noexcept { return lc_make_float2(lc_smoothstep_impl(e0.x, e1.x, x.x), lc_smoothstep_impl(e0.y, e1.y, x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_smoothstep(lc_float3 e0, lc_float3 e1, lc_float3 x) noexcept { return lc_make_float3(lc_smoothstep_impl(e0.x, e1.x, x.x), lc_smoothstep_impl(e0.y, e1.y, x.y), lc_smoothstep_impl(e0.z, e1.z, x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_smoothstep(lc_float4 e0, lc_float4 e1, lc_float4 x) noexcept { return lc_make_float4(lc_smoothstep_impl(e0.x, e1.x, x.x), lc_smoothstep_impl(e0.y, e1.y, x.y), lc_smoothstep_impl(e0.z, e1.z, x.z), lc_smoothstep_impl(e0.w, e1.w, x.w)); } + +[[nodiscard]] __device__ inline lc_half lc_mod(lc_half x, lc_half y) noexcept { return lc_mod_impl(x, y); } +[[nodiscard]] __device__ inline lc_half2 lc_mod(lc_half2 x, lc_half2 y) noexcept { return lc_make_half2(lc_mod_impl(x.x, y.x), lc_mod_impl(x.y, y.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_mod(lc_half3 x, lc_half3 y) noexcept { return lc_make_half3(lc_mod_impl(x.x, y.x), lc_mod_impl(x.y, y.y), lc_mod_impl(x.z, y.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_mod(lc_half4 x, lc_half4 y) noexcept { return lc_make_half4(lc_mod_impl(x.x, y.x), lc_mod_impl(x.y, y.y), lc_mod_impl(x.z, y.z), lc_mod_impl(x.w, y.w)); } +[[nodiscard]] __device__ inline lc_float lc_mod(lc_float x, lc_float y) noexcept { return lc_mod_impl(x, y); } +[[nodiscard]] __device__ inline lc_float2 lc_mod(lc_float2 x, lc_float2 y) noexcept { return lc_make_float2(lc_mod_impl(x.x, y.x), lc_mod_impl(x.y, y.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_mod(lc_float3 x, lc_float3 y) noexcept { return lc_make_float3(lc_mod_impl(x.x, y.x), lc_mod_impl(x.y, y.y), lc_mod_impl(x.z, y.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_mod(lc_float4 x, lc_float4 y) noexcept { return lc_make_float4(lc_mod_impl(x.x, y.x), lc_mod_impl(x.y, y.y), lc_mod_impl(x.z, y.z), lc_mod_impl(x.w, y.w)); } + +[[nodiscard]] __device__ inline lc_half lc_fmod(lc_half x, lc_half y) noexcept { return lc_fmod_impl(x, y); } +[[nodiscard]] __device__ inline lc_half2 lc_fmod(lc_half2 x, lc_half2 y) noexcept { return lc_make_half2(lc_fmod_impl(x.x, y.x), lc_fmod_impl(x.y, y.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_fmod(lc_half3 x, lc_half3 y) noexcept { return lc_make_half3(lc_fmod_impl(x.x, y.x), lc_fmod_impl(x.y, y.y), lc_fmod_impl(x.z, y.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_fmod(lc_half4 x, lc_half4 y) noexcept { return lc_make_half4(lc_fmod_impl(x.x, y.x), lc_fmod_impl(x.y, y.y), lc_fmod_impl(x.z, y.z), lc_fmod_impl(x.w, y.w)); } +[[nodiscard]] __device__ inline lc_float lc_fmod(lc_float x, lc_float y) noexcept { return lc_fmod_impl(x, y); } +[[nodiscard]] __device__ inline lc_float2 lc_fmod(lc_float2 x, lc_float2 y) noexcept { return lc_make_float2(lc_fmod_impl(x.x, y.x), lc_fmod_impl(x.y, y.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_fmod(lc_float3 x, lc_float3 y) noexcept { return lc_make_float3(lc_fmod_impl(x.x, y.x), lc_fmod_impl(x.y, y.y), lc_fmod_impl(x.z, y.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_fmod(lc_float4 x, lc_float4 y) noexcept { return lc_make_float4(lc_fmod_impl(x.x, y.x), lc_fmod_impl(x.y, y.y), lc_fmod_impl(x.z, y.z), lc_fmod_impl(x.w, y.w)); } + +[[nodiscard]] __device__ inline lc_half lc_fract(lc_half x) noexcept { return lc_fract_impl(x); } +[[nodiscard]] __device__ inline lc_half2 lc_fract(lc_half2 x) noexcept { return lc_make_half2(lc_fract_impl(x.x), lc_fract_impl(x.y)); } +[[nodiscard]] __device__ inline lc_half3 lc_fract(lc_half3 x) noexcept { return lc_make_half3(lc_fract_impl(x.x), lc_fract_impl(x.y), lc_fract_impl(x.z)); } +[[nodiscard]] __device__ inline lc_half4 lc_fract(lc_half4 x) noexcept { return lc_make_half4(lc_fract_impl(x.x), lc_fract_impl(x.y), lc_fract_impl(x.z), lc_fract_impl(x.w)); } +[[nodiscard]] __device__ inline lc_float lc_fract(lc_float x) noexcept { return lc_fract_impl(x); } +[[nodiscard]] __device__ inline lc_float2 lc_fract(lc_float2 x) noexcept { return lc_make_float2(lc_fract_impl(x.x), lc_fract_impl(x.y)); } +[[nodiscard]] __device__ inline lc_float3 lc_fract(lc_float3 x) noexcept { return lc_make_float3(lc_fract_impl(x.x), lc_fract_impl(x.y), lc_fract_impl(x.z)); } +[[nodiscard]] __device__ inline lc_float4 lc_fract(lc_float4 x) noexcept { return lc_make_float4(lc_fract_impl(x.x), lc_fract_impl(x.y), lc_fract_impl(x.z), lc_fract_impl(x.w)); } + +[[nodiscard]] __device__ inline lc_uint lc_clz(lc_uint x) noexcept { return __clz(x); } +[[nodiscard]] __device__ inline lc_uint2 lc_clz(lc_uint2 x) noexcept { return lc_make_uint2(__clz(x.x), __clz(x.y)); } +[[nodiscard]] __device__ inline lc_uint3 lc_clz(lc_uint3 x) noexcept { return lc_make_uint3(__clz(x.x), __clz(x.y), __clz(x.z)); } +[[nodiscard]] __device__ inline lc_uint4 lc_clz(lc_uint4 x) noexcept { return lc_make_uint4(__clz(x.x), __clz(x.y), __clz(x.z), __clz(x.w)); } + +[[nodiscard]] __device__ inline lc_ulong lc_clz(lc_ulong x) noexcept { return __clzll(x); } +[[nodiscard]] __device__ inline lc_ulong2 lc_clz(lc_ulong2 x) noexcept { return lc_make_ulong2(__clzll(x.x), __clzll(x.y)); } +[[nodiscard]] __device__ inline lc_ulong3 lc_clz(lc_ulong3 x) noexcept { return lc_make_ulong3(__clzll(x.x), __clzll(x.y), __clzll(x.z)); } +[[nodiscard]] __device__ inline lc_ulong4 lc_clz(lc_ulong4 x) noexcept { return lc_make_ulong4(__clzll(x.x), __clzll(x.y), __clzll(x.z), __clzll(x.w)); } + +[[nodiscard]] __device__ inline lc_uint lc_popcount(lc_uint x) noexcept { return __popc(x); } +[[nodiscard]] __device__ inline lc_uint2 lc_popcount(lc_uint2 x) noexcept { return lc_make_uint2(__popc(x.x), __popc(x.y)); } +[[nodiscard]] __device__ inline lc_uint3 lc_popcount(lc_uint3 x) noexcept { return lc_make_uint3(__popc(x.x), __popc(x.y), __popc(x.z)); } +[[nodiscard]] __device__ inline lc_uint4 lc_popcount(lc_uint4 x) noexcept { return lc_make_uint4(__popc(x.x), __popc(x.y), __popc(x.z), __popc(x.w)); } + +[[nodiscard]] __device__ inline lc_ulong lc_popcount(lc_ulong x) noexcept { return __popcll(x); } +[[nodiscard]] __device__ inline lc_ulong2 lc_popcount(lc_ulong2 x) noexcept { return lc_make_ulong2(__popcll(x.x), __popcll(x.y)); } +[[nodiscard]] __device__ inline lc_ulong3 lc_popcount(lc_ulong3 x) noexcept { return lc_make_ulong3(__popcll(x.x), __popcll(x.y), __popcll(x.z)); } +[[nodiscard]] __device__ inline lc_ulong4 lc_popcount(lc_ulong4 x) noexcept { return lc_make_ulong4(__popcll(x.x), __popcll(x.y), __popcll(x.z), __popcll(x.w)); } + +[[nodiscard]] __device__ inline lc_uint lc_reverse(lc_uint x) noexcept { return __brev(x); } +[[nodiscard]] __device__ inline lc_uint2 lc_reverse(lc_uint2 x) noexcept { return lc_make_uint2(__brev(x.x), __brev(x.y)); } +[[nodiscard]] __device__ inline lc_uint3 lc_reverse(lc_uint3 x) noexcept { return lc_make_uint3(__brev(x.x), __brev(x.y), __brev(x.z)); } +[[nodiscard]] __device__ inline lc_uint4 lc_reverse(lc_uint4 x) noexcept { return lc_make_uint4(__brev(x.x), __brev(x.y), __brev(x.z), __brev(x.w)); } + +[[nodiscard]] __device__ inline lc_ulong lc_reverse(lc_ulong x) noexcept { return __brevll(x); } +[[nodiscard]] __device__ inline lc_ulong2 lc_reverse(lc_ulong2 x) noexcept { return lc_make_ulong2(__brevll(x.x), __brevll(x.y)); } +[[nodiscard]] __device__ inline lc_ulong3 lc_reverse(lc_ulong3 x) noexcept { return lc_make_ulong3(__brevll(x.x), __brevll(x.y), __brevll(x.z)); } +[[nodiscard]] __device__ inline lc_ulong4 lc_reverse(lc_ulong4 x) noexcept { return lc_make_ulong4(__brevll(x.x), __brevll(x.y), __brevll(x.z), __brevll(x.w)); } + +[[nodiscard]] __device__ inline auto lc_ctz_impl(lc_uint x) noexcept { return (__ffs(x) - 1u) % 32u; } +[[nodiscard]] __device__ inline auto lc_ctz_impl(lc_ulong x) noexcept { return (__ffsll(x) - 1u) % 64u; } +[[nodiscard]] __device__ inline lc_uint lc_ctz(lc_uint x) noexcept { return lc_ctz_impl(x); } +[[nodiscard]] __device__ inline lc_uint2 lc_ctz(lc_uint2 x) noexcept { return lc_make_uint2(lc_ctz_impl(x.x), lc_ctz_impl(x.y)); } +[[nodiscard]] __device__ inline lc_uint3 lc_ctz(lc_uint3 x) noexcept { return lc_make_uint3(lc_ctz_impl(x.x), lc_ctz_impl(x.y), lc_ctz_impl(x.z)); } +[[nodiscard]] __device__ inline lc_uint4 lc_ctz(lc_uint4 x) noexcept { return lc_make_uint4(lc_ctz_impl(x.x), lc_ctz_impl(x.y), lc_ctz_impl(x.z), lc_ctz_impl(x.w)); } +[[nodiscard]] __device__ inline lc_ulong lc_ctz(lc_ulong x) noexcept { return lc_ctz_impl(x); } +[[nodiscard]] __device__ inline lc_ulong2 lc_ctz(lc_ulong2 x) noexcept { return lc_make_ulong2(lc_ctz_impl(x.x), lc_ctz_impl(x.y)); } +[[nodiscard]] __device__ inline lc_ulong3 lc_ctz(lc_ulong3 x) noexcept { return lc_make_ulong3(lc_ctz_impl(x.x), lc_ctz_impl(x.y), lc_ctz_impl(x.z)); } +[[nodiscard]] __device__ inline lc_ulong4 lc_ctz(lc_ulong4 x) noexcept { return lc_make_ulong4(lc_ctz_impl(x.x), lc_ctz_impl(x.y), lc_ctz_impl(x.z), lc_ctz_impl(x.w)); } + +[[nodiscard]] __device__ inline constexpr auto lc_cross(lc_float3 u, lc_float3 v) noexcept { + return lc_make_float3(u.y * v.z - v.y * u.z, + u.z * v.x - v.z * u.x, + u.x * v.y - v.x * u.y); +} + +[[nodiscard]] __device__ inline auto lc_dot(lc_float2 a, lc_float2 b) noexcept { + return a.x * b.x + a.y * b.y; +} +[[nodiscard]] __device__ inline auto lc_dot(lc_float3 a, lc_float3 b) noexcept { + return a.x * b.x + a.y * b.y + a.z * b.z; +} +[[nodiscard]] __device__ inline auto lc_dot(lc_float4 a, lc_float4 b) noexcept { + return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; +} + +[[nodiscard]] __device__ inline auto lc_length(lc_float2 v) noexcept { return lc_sqrt(lc_dot(v, v)); } +[[nodiscard]] __device__ inline auto lc_length(lc_float3 v) noexcept { return lc_sqrt(lc_dot(v, v)); } +[[nodiscard]] __device__ inline auto lc_length(lc_float4 v) noexcept { return lc_sqrt(lc_dot(v, v)); } + +[[nodiscard]] __device__ inline auto lc_length_squared(lc_float2 v) noexcept { return lc_dot(v, v); } +[[nodiscard]] __device__ inline auto lc_length_squared(lc_float3 v) noexcept { return lc_dot(v, v); } +[[nodiscard]] __device__ inline auto lc_length_squared(lc_float4 v) noexcept { return lc_dot(v, v); } + +[[nodiscard]] __device__ inline auto lc_distance(lc_float2 a, lc_float2 b) noexcept { return lc_length(a - b); } +[[nodiscard]] __device__ inline auto lc_distance(lc_float3 a, lc_float3 b) noexcept { return lc_length(a - b); } +[[nodiscard]] __device__ inline auto lc_distance(lc_float4 a, lc_float4 b) noexcept { return lc_length(a - b); } + +[[nodiscard]] __device__ inline auto lc_distance_squared(lc_float2 a, lc_float2 b) noexcept { return lc_length_squared(a - b); } +[[nodiscard]] __device__ inline auto lc_distance_squared(lc_float3 a, lc_float3 b) noexcept { return lc_length_squared(a - b); } +[[nodiscard]] __device__ inline auto lc_distance_squared(lc_float4 a, lc_float4 b) noexcept { return lc_length_squared(a - b); } + +[[nodiscard]] __device__ inline auto lc_faceforward(lc_float3 n, lc_float3 i, lc_float3 n_ref) noexcept { return lc_select(-n, n, lc_dot(n_ref, i) < lc_float(0.f)); } + +[[nodiscard]] __device__ inline auto lc_normalize(lc_float2 v) noexcept { return v * lc_rsqrt(lc_dot(v, v)); } +[[nodiscard]] __device__ inline auto lc_normalize(lc_float3 v) noexcept { return v * lc_rsqrt(lc_dot(v, v)); } +[[nodiscard]] __device__ inline auto lc_normalize(lc_float4 v) noexcept { return v * lc_rsqrt(lc_dot(v, v)); } + +[[nodiscard]] __device__ inline constexpr auto lc_cross(lc_half3 u, lc_half3 v) noexcept { + return lc_make_half3(u.y * v.z - v.y * u.z, + u.z * v.x - v.z * u.x, + u.x * v.y - v.x * u.y); +} + +[[nodiscard]] __device__ inline auto lc_dot(lc_half2 a, lc_half2 b) noexcept { + return a.x * b.x + a.y * b.y; +} +[[nodiscard]] __device__ inline auto lc_dot(lc_half3 a, lc_half3 b) noexcept { + return a.x * b.x + a.y * b.y + a.z * b.z; +} +[[nodiscard]] __device__ inline auto lc_dot(lc_half4 a, lc_half4 b) noexcept { + return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; +} + +[[nodiscard]] __device__ inline auto lc_length(lc_half2 v) noexcept { return lc_sqrt(lc_dot(v, v)); } +[[nodiscard]] __device__ inline auto lc_length(lc_half3 v) noexcept { return lc_sqrt(lc_dot(v, v)); } +[[nodiscard]] __device__ inline auto lc_length(lc_half4 v) noexcept { return lc_sqrt(lc_dot(v, v)); } + +[[nodiscard]] __device__ inline auto lc_length_squared(lc_half2 v) noexcept { return lc_dot(v, v); } +[[nodiscard]] __device__ inline auto lc_length_squared(lc_half3 v) noexcept { return lc_dot(v, v); } +[[nodiscard]] __device__ inline auto lc_length_squared(lc_half4 v) noexcept { return lc_dot(v, v); } + +[[nodiscard]] __device__ inline auto lc_distance(lc_half2 a, lc_half2 b) noexcept { return lc_length(a - b); } +[[nodiscard]] __device__ inline auto lc_distance(lc_half3 a, lc_half3 b) noexcept { return lc_length(a - b); } +[[nodiscard]] __device__ inline auto lc_distance(lc_half4 a, lc_half4 b) noexcept { return lc_length(a - b); } + +[[nodiscard]] __device__ inline auto lc_distance_squared(lc_half2 a, lc_half2 b) noexcept { return lc_length_squared(a - b); } +[[nodiscard]] __device__ inline auto lc_distance_squared(lc_half3 a, lc_half3 b) noexcept { return lc_length_squared(a - b); } +[[nodiscard]] __device__ inline auto lc_distance_squared(lc_half4 a, lc_half4 b) noexcept { return lc_length_squared(a - b); } + +[[nodiscard]] __device__ inline auto lc_faceforward(lc_half3 n, lc_half3 i, lc_half3 n_ref) noexcept { return lc_select(-n, n, lc_dot(n_ref, i) < lc_half(0.f)); } + +[[nodiscard]] __device__ inline auto lc_normalize(lc_half2 v) noexcept { return v * lc_rsqrt(lc_dot(v, v)); } +[[nodiscard]] __device__ inline auto lc_normalize(lc_half3 v) noexcept { return v * lc_rsqrt(lc_dot(v, v)); } +[[nodiscard]] __device__ inline auto lc_normalize(lc_half4 v) noexcept { return v * lc_rsqrt(lc_dot(v, v)); } + +[[nodiscard]] __device__ inline constexpr auto lc_transpose(const lc_float2x2 m) noexcept { return lc_make_float2x2(m[0].x, m[1].x, m[0].y, m[1].y); } +[[nodiscard]] __device__ inline constexpr auto lc_transpose(const lc_float3x3 m) noexcept { return lc_make_float3x3(m[0].x, m[1].x, m[2].x, m[0].y, m[1].y, m[2].y, m[0].z, m[1].z, m[2].z); } +[[nodiscard]] __device__ inline constexpr auto lc_transpose(const lc_float4x4 m) noexcept { return lc_make_float4x4(m[0].x, m[1].x, m[2].x, m[3].x, m[0].y, m[1].y, m[2].y, m[3].y, m[0].z, m[1].z, m[2].z, m[3].z, m[0].w, m[1].w, m[2].w, m[3].w); } + +[[nodiscard]] __device__ inline constexpr auto lc_determinant(const lc_float2x2 m) noexcept { + return m[0][0] * m[1][1] - m[1][0] * m[0][1]; +} + +[[nodiscard]] __device__ constexpr auto lc_determinant(const lc_float3x3 m) noexcept {// from GLM + return m[0].x * (m[1].y * m[2].z - m[2].y * m[1].z) + - m[1].x * (m[0].y * m[2].z - m[2].y * m[0].z) + + m[2].x * (m[0].y * m[1].z - m[1].y * m[0].z); +} + +[[nodiscard]] __device__ inline constexpr auto lc_determinant(const lc_float4x4 m) noexcept {// from GLM + const auto coef00 = m[2].z * m[3].w - m[3].z * m[2].w; + const auto coef02 = m[1].z * m[3].w - m[3].z * m[1].w; + const auto coef03 = m[1].z * m[2].w - m[2].z * m[1].w; + const auto coef04 = m[2].y * m[3].w - m[3].y * m[2].w; + const auto coef06 = m[1].y * m[3].w - m[3].y * m[1].w; + const auto coef07 = m[1].y * m[2].w - m[2].y * m[1].w; + const auto coef08 = m[2].y * m[3].z - m[3].y * m[2].z; + const auto coef10 = m[1].y * m[3].z - m[3].y * m[1].z; + const auto coef11 = m[1].y * m[2].z - m[2].y * m[1].z; + const auto coef12 = m[2].x * m[3].w - m[3].x * m[2].w; + const auto coef14 = m[1].x * m[3].w - m[3].x * m[1].w; + const auto coef15 = m[1].x * m[2].w - m[2].x * m[1].w; + const auto coef16 = m[2].x * m[3].z - m[3].x * m[2].z; + const auto coef18 = m[1].x * m[3].z - m[3].x * m[1].z; + const auto coef19 = m[1].x * m[2].z - m[2].x * m[1].z; + const auto coef20 = m[2].x * m[3].y - m[3].x * m[2].y; + const auto coef22 = m[1].x * m[3].y - m[3].x * m[1].y; + const auto coef23 = m[1].x * m[2].y - m[2].x * m[1].y; + const auto fac0 = lc_make_float4(coef00, coef00, coef02, coef03); + const auto fac1 = lc_make_float4(coef04, coef04, coef06, coef07); + const auto fac2 = lc_make_float4(coef08, coef08, coef10, coef11); + const auto fac3 = lc_make_float4(coef12, coef12, coef14, coef15); + const auto fac4 = lc_make_float4(coef16, coef16, coef18, coef19); + const auto fac5 = lc_make_float4(coef20, coef20, coef22, coef23); + const auto Vec0 = lc_make_float4(m[1].x, m[0].x, m[0].x, m[0].x); + const auto Vec1 = lc_make_float4(m[1].y, m[0].y, m[0].y, m[0].y); + const auto Vec2 = lc_make_float4(m[1].z, m[0].z, m[0].z, m[0].z); + const auto Vec3 = lc_make_float4(m[1].w, m[0].w, m[0].w, m[0].w); + const auto inv0 = Vec1 * fac0 - Vec2 * fac1 + Vec3 * fac2; + const auto inv1 = Vec0 * fac0 - Vec2 * fac3 + Vec3 * fac4; + const auto inv2 = Vec0 * fac1 - Vec1 * fac3 + Vec3 * fac5; + const auto inv3 = Vec0 * fac2 - Vec1 * fac4 + Vec2 * fac5; + constexpr auto sign_a = lc_make_float4(+1.0f, -1.0f, +1.0f, -1.0f); + constexpr auto sign_b = lc_make_float4(-1.0f, +1.0f, -1.0f, +1.0f); + const auto inv_0 = inv0 * sign_a; + const auto inv_1 = inv1 * sign_b; + const auto inv_2 = inv2 * sign_a; + const auto inv_3 = inv3 * sign_b; + const auto dot0 = m[0] * lc_make_float4(inv_0.x, inv_1.x, inv_2.x, inv_3.x); + return dot0.x + dot0.y + dot0.z + dot0.w; +} + +[[nodiscard]] __device__ inline constexpr auto lc_inverse(const lc_float2x2 m) noexcept { + const auto one_over_determinant = 1.0f / (m[0][0] * m[1][1] - m[1][0] * m[0][1]); + return lc_make_float2x2(m[1][1] * one_over_determinant, + - m[0][1] * one_over_determinant, + - m[1][0] * one_over_determinant, + + m[0][0] * one_over_determinant); +} + +[[nodiscard]] __device__ inline constexpr auto lc_inverse(const lc_float3x3 m) noexcept {// from GLM + const auto one_over_determinant = 1.0f + / (m[0].x * (m[1].y * m[2].z - m[2].y * m[1].z) + - m[1].x * (m[0].y * m[2].z - m[2].y * m[0].z) + + m[2].x * (m[0].y * m[1].z - m[1].y * m[0].z)); + return lc_make_float3x3( + (m[1].y * m[2].z - m[2].y * m[1].z) * one_over_determinant, + (m[2].y * m[0].z - m[0].y * m[2].z) * one_over_determinant, + (m[0].y * m[1].z - m[1].y * m[0].z) * one_over_determinant, + (m[2].x * m[1].z - m[1].x * m[2].z) * one_over_determinant, + (m[0].x * m[2].z - m[2].x * m[0].z) * one_over_determinant, + (m[1].x * m[0].z - m[0].x * m[1].z) * one_over_determinant, + (m[1].x * m[2].y - m[2].x * m[1].y) * one_over_determinant, + (m[2].x * m[0].y - m[0].x * m[2].y) * one_over_determinant, + (m[0].x * m[1].y - m[1].x * m[0].y) * one_over_determinant); +} + +[[nodiscard]] __device__ inline constexpr auto lc_inverse(const lc_float4x4 m) noexcept {// from GLM + const auto coef00 = m[2].z * m[3].w - m[3].z * m[2].w; + const auto coef02 = m[1].z * m[3].w - m[3].z * m[1].w; + const auto coef03 = m[1].z * m[2].w - m[2].z * m[1].w; + const auto coef04 = m[2].y * m[3].w - m[3].y * m[2].w; + const auto coef06 = m[1].y * m[3].w - m[3].y * m[1].w; + const auto coef07 = m[1].y * m[2].w - m[2].y * m[1].w; + const auto coef08 = m[2].y * m[3].z - m[3].y * m[2].z; + const auto coef10 = m[1].y * m[3].z - m[3].y * m[1].z; + const auto coef11 = m[1].y * m[2].z - m[2].y * m[1].z; + const auto coef12 = m[2].x * m[3].w - m[3].x * m[2].w; + const auto coef14 = m[1].x * m[3].w - m[3].x * m[1].w; + const auto coef15 = m[1].x * m[2].w - m[2].x * m[1].w; + const auto coef16 = m[2].x * m[3].z - m[3].x * m[2].z; + const auto coef18 = m[1].x * m[3].z - m[3].x * m[1].z; + const auto coef19 = m[1].x * m[2].z - m[2].x * m[1].z; + const auto coef20 = m[2].x * m[3].y - m[3].x * m[2].y; + const auto coef22 = m[1].x * m[3].y - m[3].x * m[1].y; + const auto coef23 = m[1].x * m[2].y - m[2].x * m[1].y; + const auto fac0 = lc_make_float4(coef00, coef00, coef02, coef03); + const auto fac1 = lc_make_float4(coef04, coef04, coef06, coef07); + const auto fac2 = lc_make_float4(coef08, coef08, coef10, coef11); + const auto fac3 = lc_make_float4(coef12, coef12, coef14, coef15); + const auto fac4 = lc_make_float4(coef16, coef16, coef18, coef19); + const auto fac5 = lc_make_float4(coef20, coef20, coef22, coef23); + const auto Vec0 = lc_make_float4(m[1].x, m[0].x, m[0].x, m[0].x); + const auto Vec1 = lc_make_float4(m[1].y, m[0].y, m[0].y, m[0].y); + const auto Vec2 = lc_make_float4(m[1].z, m[0].z, m[0].z, m[0].z); + const auto Vec3 = lc_make_float4(m[1].w, m[0].w, m[0].w, m[0].w); + const auto inv0 = Vec1 * fac0 - Vec2 * fac1 + Vec3 * fac2; + const auto inv1 = Vec0 * fac0 - Vec2 * fac3 + Vec3 * fac4; + const auto inv2 = Vec0 * fac1 - Vec1 * fac3 + Vec3 * fac5; + const auto inv3 = Vec0 * fac2 - Vec1 * fac4 + Vec2 * fac5; + constexpr auto sign_a = lc_make_float4(+1.0f, -1.0f, +1.0f, -1.0f); + constexpr auto sign_b = lc_make_float4(-1.0f, +1.0f, -1.0f, +1.0f); + const auto inv_0 = inv0 * sign_a; + const auto inv_1 = inv1 * sign_b; + const auto inv_2 = inv2 * sign_a; + const auto inv_3 = inv3 * sign_b; + const auto dot0 = m[0] * lc_make_float4(inv_0.x, inv_1.x, inv_2.x, inv_3.x); + const auto dot1 = dot0.x + dot0.y + dot0.z + dot0.w; + const auto one_over_determinant = 1.0f / dot1; + return lc_make_float4x4(inv_0 * one_over_determinant, + inv_1 * one_over_determinant, + inv_2 * one_over_determinant, + inv_3 * one_over_determinant); +} + +[[nodiscard]] __device__ inline auto lc_reflect(const lc_float3 v, const lc_float3 n) noexcept { + return v - 2.0f * lc_dot(v, n) * n; +} + +template +[[nodiscard]] __device__ inline auto lc_bit_cast(S s) noexcept { + static_assert(sizeof(D) == sizeof(S)); + return reinterpret_cast(s); +} +template +[[nodiscard]] __device__ inline constexpr auto lc_zero() noexcept { + return T{}; +} +template +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return T::one(); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_int(1); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_float(1.0f); +} +template<> +[[nodiscard]] __device__ inline auto lc_one() noexcept { + return lc_half(1.0f); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_uint(1u); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_long(1); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_ulong(1); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_short(1); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_ushort(1); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_byte(1); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_ubyte(1); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return true; +} +template +class lc_array { + +private: + T _data[N]; + +public: + template + __device__ constexpr lc_array(Elem... elem) noexcept : _data{elem...} {} + __device__ constexpr lc_array(lc_array &&) noexcept = default; + __device__ constexpr lc_array(const lc_array &) noexcept = default; + __device__ constexpr lc_array &operator=(lc_array &&) noexcept = default; + __device__ constexpr lc_array &operator=(const lc_array &) noexcept = default; + [[nodiscard]] __device__ T &operator[](size_t i) noexcept { return _data[i]; } + [[nodiscard]] __device__ T operator[](size_t i) const noexcept { return _data[i]; } + +public: + [[nodiscard]] __device__ static auto one() noexcept { + lc_array ret; + #pragma unroll + for (auto i = 0u; i < N; i++) { ret[i] = lc_one(); } + return ret; + } +}; + +[[nodiscard]] __device__ inline auto lc_mat_comp_mul(lc_float2x2 lhs, lc_float2x2 rhs) noexcept { + return lc_make_float2x2(lhs[0] * rhs[0], + lhs[1] * rhs[1]); +} + +[[nodiscard]] __device__ inline auto lc_mat_comp_mul(lc_float3x3 lhs, lc_float3x3 rhs) noexcept { + return lc_make_float3x3(lhs[0] * rhs[0], + lhs[1] * rhs[1], + lhs[2] * rhs[2]); +} + +[[nodiscard]] __device__ inline auto lc_mat_comp_mul(lc_float4x4 lhs, lc_float4x4 rhs) noexcept { + return lc_make_float4x4(lhs[0] * rhs[0], + lhs[1] * rhs[1], + lhs[2] * rhs[2], + lhs[3] * rhs[3]); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float2 v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float3 v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float4 v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half2 v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half3 v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half4 v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float2x2 v) noexcept { + v.cols[0] = lc_remove_nan(v.cols[0]); + v.cols[1] = lc_remove_nan(v.cols[1]); + return v; +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float3x3 v) noexcept { + v.cols[0] = lc_remove_nan(v.cols[0]); + v.cols[1] = lc_remove_nan(v.cols[1]); + v.cols[2] = lc_remove_nan(v.cols[2]); + return v; +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float4x4 v) noexcept { + v.cols[0] = lc_remove_nan(v.cols[0]); + v.cols[1] = lc_remove_nan(v.cols[1]); + v.cols[2] = lc_remove_nan(v.cols[2]); + v.cols[3] = lc_remove_nan(v.cols[3]); + return v; +} + +__device__ inline void lc_accumulate_grad(lc_float *dst, lc_float grad) noexcept { *dst = *dst + lc_remove_nan(grad); } +__device__ inline void lc_accumulate_grad(lc_float2x2 *dst, lc_float2x2 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } +__device__ inline void lc_accumulate_grad(lc_float3x3 *dst, lc_float3x3 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } +__device__ inline void lc_accumulate_grad(lc_float4x4 *dst, lc_float4x4 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } +__device__ inline void lc_accumulate_grad(lc_float2 *dst, lc_float2 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } +__device__ inline void lc_accumulate_grad(lc_float3 *dst, lc_float3 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } +__device__ inline void lc_accumulate_grad(lc_float4 *dst, lc_float4 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } +__device__ inline void lc_accumulate_grad(lc_half *dst, lc_half grad) noexcept { *dst = *dst + lc_remove_nan(grad); } +__device__ inline void lc_accumulate_grad(lc_half2 *dst, lc_half2 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } +__device__ inline void lc_accumulate_grad(lc_half3 *dst, lc_half3 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } +__device__ inline void lc_accumulate_grad(lc_half4 *dst, lc_half4 grad) noexcept { *dst = *dst + lc_remove_nan(grad); } +__device__ inline void lc_accumulate_grad(lc_short *dst, lc_short grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_ushort *dst, lc_ushort grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_int *dst, lc_int grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_uint *dst, lc_uint grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_long *dst, lc_long grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_ulong *dst, lc_ulong grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_bool *dst, lc_bool grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_byte *dst, lc_byte grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_ubyte *dst, lc_ubyte grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_byte2 *dst, lc_byte2 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_byte3 *dst, lc_byte3 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_byte4 *dst, lc_byte4 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_ubyte2 *dst, lc_ubyte2 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_ubyte3 *dst, lc_ubyte3 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_ubyte4 *dst, lc_ubyte4 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_short2 *dst, lc_short2 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_short3 *dst, lc_short3 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_short4 *dst, lc_short4 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_ushort2 *dst, lc_ushort2 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_ushort3 *dst, lc_ushort3 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_ushort4 *dst, lc_ushort4 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_int2 *dst, lc_int2 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_int3 *dst, lc_int3 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_int4 *dst, lc_int4 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_uint2 *dst, lc_uint2 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_uint3 *dst, lc_uint3 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_uint4 *dst, lc_uint4 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_long2 *dst, lc_long2 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_long3 *dst, lc_long3 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_long4 *dst, lc_long4 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_ulong2 *dst, lc_ulong2 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_ulong3 *dst, lc_ulong3 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_ulong4 *dst, lc_ulong4 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_bool2 *dst, lc_bool2 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_bool3 *dst, lc_bool3 grad) noexcept {} +__device__ inline void lc_accumulate_grad(lc_bool4 *dst, lc_bool4 grad) noexcept {} +struct lc_user_data_t{}; constexpr lc_user_data_t _lc_user_data{}; +template struct element_type_{using type = void;}; +template using element_type = typename element_type_::type; + +template<> struct element_type_ { using type = lc_float; }; +template<> struct element_type_ { using type = lc_float; }; +template<> struct element_type_ { using type = lc_float; }; +template<> struct element_type_ { using type = lc_half; }; +template<> struct element_type_ { using type = lc_half; }; +template<> struct element_type_ { using type = lc_half; }; +template<> struct element_type_ { using type = lc_short; }; +template<> struct element_type_ { using type = lc_short; }; +template<> struct element_type_ { using type = lc_short; }; +template<> struct element_type_ { using type = lc_ushort; }; +template<> struct element_type_ { using type = lc_ushort; }; +template<> struct element_type_ { using type = lc_ushort; }; +template<> struct element_type_ { using type = lc_byte; }; +template<> struct element_type_ { using type = lc_byte; }; +template<> struct element_type_ { using type = lc_byte; }; +template<> struct element_type_ { using type = lc_ubyte; }; +template<> struct element_type_ { using type = lc_ubyte; }; +template<> struct element_type_ { using type = lc_ubyte; }; +template<> struct element_type_ { using type = lc_int; }; +template<> struct element_type_ { using type = lc_int; }; +template<> struct element_type_ { using type = lc_int; }; +template<> struct element_type_ { using type = lc_uint; }; +template<> struct element_type_ { using type = lc_uint; }; +template<> struct element_type_ { using type = lc_uint; }; +template<> struct element_type_ { using type = lc_long; }; +template<> struct element_type_ { using type = lc_long; }; +template<> struct element_type_ { using type = lc_long; }; +template<> struct element_type_ { using type = lc_ulong; }; +template<> struct element_type_ { using type = lc_ulong; }; +template<> struct element_type_ { using type = lc_ulong; }; + +template +__device__ inline void lc_accumulate_grad(lc_array *dst, lc_array grad) noexcept { + #pragma unroll + for (auto i = 0u; i < N; i++) { lc_accumulate_grad(&(*dst)[i], grad[i]); } +} diff --git a/src/backends/cuda/cuda_builtin_embedded.cpp b/src/backends/cuda/cuda_builtin_embedded.cpp index d7bc02330..8b58d3072 100644 --- a/src/backends/cuda/cuda_builtin_embedded.cpp +++ b/src/backends/cuda/cuda_builtin_embedded.cpp @@ -5661,7 +5661,7 @@ extern "C" const char luisa_cuda_builtin_cuda_device_half[84397] = { 0x6c, 0x66, 0x32, 0x3b, 0x0a, 0x0a, 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x0a }; -extern "C" const char luisa_cuda_builtin_cuda_device_math[499474] = { +extern "C" const char luisa_cuda_builtin_cuda_device_math[499454] = { 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x68, 0x61, 0x72, 0x3b, 0x0a, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x20, 0x3d, 0x20, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, @@ -32051,1309 +32051,1268 @@ extern "C" const char luisa_cuda_builtin_cuda_device_math[499474] = { 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x6f, - 0x75, 0x6e, 0x64, 0x66, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x28, 0x6c, 0x63, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x66, 0x28, - 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x66, 0x28, 0x78, 0x2e, 0x79, - 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, - 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, - 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x33, 0x28, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, - 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x66, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x72, 0x6f, - 0x75, 0x6e, 0x64, 0x66, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x28, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x72, 0x6f, 0x75, 0x6e, - 0x64, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x66, 0x28, - 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x66, 0x28, 0x78, 0x2e, 0x7a, - 0x29, 0x2c, 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x66, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x69, + 0x6e, 0x74, 0x66, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, + 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x78, 0x2e, + 0x78, 0x29, 0x2c, 0x20, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, + 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x72, + 0x6f, 0x75, 0x6e, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x66, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x6f, 0x75, - 0x6e, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x78, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, - 0x28, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x72, 0x6f, - 0x75, 0x6e, 0x64, 0x66, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, - 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x72, 0x6f, 0x75, 0x6e, - 0x64, 0x66, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x66, 0x28, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, + 0x28, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x72, 0x69, 0x6e, + 0x74, 0x66, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x78, + 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, + 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x29, + 0x2c, 0x20, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x72, 0x69, + 0x6e, 0x74, 0x66, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, + 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x78, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, + 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x29, + 0x2c, 0x20, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x33, 0x28, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x72, 0x69, + 0x6e, 0x74, 0x66, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x66, - 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x66, 0x28, 0x78, 0x2e, - 0x79, 0x29, 0x2c, 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x66, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, - 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x66, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, - 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, - 0x61, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x20, 0x7a, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x6d, 0x61, 0x66, 0x28, 0x78, 0x2c, 0x20, - 0x79, 0x2c, 0x20, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x61, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x32, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, - 0x20, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x7a, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x32, 0x28, 0x66, 0x6d, 0x61, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x2c, - 0x20, 0x7a, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x66, 0x6d, 0x61, 0x66, 0x28, 0x78, 0x2e, 0x79, 0x2c, - 0x20, 0x79, 0x2e, 0x79, 0x2c, 0x20, 0x7a, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x61, 0x28, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x33, 0x20, 0x7a, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x66, 0x6d, 0x61, 0x66, 0x28, 0x78, 0x2e, 0x78, - 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x2c, 0x20, 0x7a, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x66, 0x6d, 0x61, - 0x66, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x2c, 0x20, 0x7a, 0x2e, 0x79, 0x29, - 0x2c, 0x20, 0x66, 0x6d, 0x61, 0x66, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x2c, - 0x20, 0x7a, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x61, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x34, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x34, 0x20, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x7a, + 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, + 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x78, 0x2e, 0x79, 0x29, + 0x2c, 0x20, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x72, 0x69, + 0x6e, 0x74, 0x66, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x61, 0x28, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x20, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x7a, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x34, 0x28, 0x66, 0x6d, 0x61, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, - 0x2c, 0x20, 0x7a, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x66, 0x6d, 0x61, 0x66, 0x28, 0x78, 0x2e, 0x79, - 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x2c, 0x20, 0x7a, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x66, 0x6d, 0x61, - 0x66, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x2c, 0x20, 0x7a, 0x2e, 0x7a, 0x29, - 0x2c, 0x20, 0x66, 0x6d, 0x61, 0x66, 0x28, 0x78, 0x2e, 0x77, 0x2c, 0x20, 0x79, 0x2e, 0x77, 0x2c, - 0x20, 0x7a, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x61, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, - 0x66, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x79, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x7a, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x68, - 0x66, 0x6d, 0x61, 0x28, 0x78, 0x2c, 0x20, 0x79, 0x2c, 0x20, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x61, 0x28, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x32, 0x20, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, - 0x20, 0x7a, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x32, 0x28, 0x5f, 0x5f, 0x68, 0x66, 0x6d, 0x61, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, - 0x79, 0x2e, 0x78, 0x2c, 0x20, 0x7a, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x66, 0x6d, - 0x61, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x2c, 0x20, 0x7a, 0x2e, 0x79, 0x29, + 0x75, 0x72, 0x6e, 0x20, 0x66, 0x6d, 0x61, 0x66, 0x28, 0x78, 0x2c, 0x20, 0x79, 0x2c, 0x20, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x63, - 0x5f, 0x66, 0x6d, 0x61, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x78, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x7a, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x5f, 0x5f, 0x68, 0x66, 0x6d, 0x61, 0x28, - 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x2c, 0x20, 0x7a, 0x2e, 0x78, 0x29, 0x2c, 0x20, - 0x5f, 0x5f, 0x68, 0x66, 0x6d, 0x61, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x2c, - 0x20, 0x7a, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x66, 0x6d, 0x61, 0x28, 0x78, 0x2e, - 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x2c, 0x20, 0x7a, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x6d, 0x61, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, + 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x79, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x7a, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, + 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x66, 0x6d, + 0x61, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x2c, 0x20, 0x7a, 0x2e, 0x78, + 0x29, 0x2c, 0x20, 0x66, 0x6d, 0x61, 0x66, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, + 0x2c, 0x20, 0x7a, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x61, 0x28, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x33, 0x20, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, + 0x7a, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x33, 0x28, 0x66, 0x6d, 0x61, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, + 0x78, 0x2c, 0x20, 0x7a, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x66, 0x6d, 0x61, 0x66, 0x28, 0x78, 0x2e, + 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x2c, 0x20, 0x7a, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x66, 0x6d, + 0x61, 0x66, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x2c, 0x20, 0x7a, 0x2e, 0x7a, + 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, + 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x61, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, + 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x79, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x7a, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x66, + 0x6d, 0x61, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x2c, 0x20, 0x7a, 0x2e, + 0x78, 0x29, 0x2c, 0x20, 0x66, 0x6d, 0x61, 0x66, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, + 0x79, 0x2c, 0x20, 0x7a, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x66, 0x6d, 0x61, 0x66, 0x28, 0x78, 0x2e, + 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x2c, 0x20, 0x7a, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x66, 0x6d, + 0x61, 0x66, 0x28, 0x78, 0x2e, 0x77, 0x2c, 0x20, 0x79, 0x2e, 0x77, 0x2c, 0x20, 0x7a, 0x2e, 0x77, + 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x6d, 0x61, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x20, 0x7a, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x68, 0x66, 0x6d, 0x61, 0x28, + 0x78, 0x2c, 0x20, 0x79, 0x2c, 0x20, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x61, 0x28, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, + 0x20, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x7a, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, + 0x5f, 0x5f, 0x68, 0x66, 0x6d, 0x61, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x2c, + 0x20, 0x7a, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x66, 0x6d, 0x61, 0x28, 0x78, 0x2e, + 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x2c, 0x20, 0x7a, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x61, - 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, - 0x34, 0x20, 0x7a, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, + 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x61, + 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x33, 0x20, 0x7a, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x34, 0x28, 0x5f, 0x5f, 0x68, 0x66, 0x6d, 0x61, 0x28, 0x78, 0x2e, 0x78, 0x2c, + 0x61, 0x6c, 0x66, 0x33, 0x28, 0x5f, 0x5f, 0x68, 0x66, 0x6d, 0x61, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x2c, 0x20, 0x7a, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x66, 0x6d, 0x61, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x2c, 0x20, 0x7a, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x66, 0x6d, 0x61, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, - 0x2e, 0x7a, 0x2c, 0x20, 0x7a, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x66, 0x6d, 0x61, - 0x28, 0x78, 0x2e, 0x77, 0x2c, 0x20, 0x79, 0x2e, 0x77, 0x2c, 0x20, 0x7a, 0x2e, 0x77, 0x29, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, - 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x79, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x75, 0x78, 0x20, 0x3d, 0x20, 0x5f, 0x5f, 0x68, 0x61, 0x6c, - 0x66, 0x5f, 0x61, 0x73, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x78, 0x29, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x75, 0x79, 0x20, 0x3d, 0x20, 0x5f, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x5f, 0x61, 0x73, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x79, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x5f, 0x61, 0x73, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x28, 0x75, 0x78, 0x20, - 0x26, 0x20, 0x30, 0x78, 0x37, 0x66, 0x66, 0x66, 0x75, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x75, 0x79, - 0x20, 0x26, 0x20, 0x30, 0x78, 0x38, 0x30, 0x30, 0x30, 0x75, 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, - 0x73, 0x69, 0x67, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, - 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x66, 0x28, 0x78, 0x2c, 0x20, 0x79, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x2e, 0x7a, 0x2c, 0x20, 0x7a, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x61, 0x28, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x34, 0x20, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x7a, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, + 0x28, 0x5f, 0x5f, 0x68, 0x66, 0x6d, 0x61, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, + 0x2c, 0x20, 0x7a, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x66, 0x6d, 0x61, 0x28, 0x78, + 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x2c, 0x20, 0x7a, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, + 0x5f, 0x68, 0x66, 0x6d, 0x61, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x2c, 0x20, + 0x7a, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x66, 0x6d, 0x61, 0x28, 0x78, 0x2e, 0x77, + 0x2c, 0x20, 0x79, 0x2e, 0x77, 0x2c, 0x20, 0x7a, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, - 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x32, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x79, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x32, 0x28, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x78, - 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, - 0x66, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, - 0x79, 0x73, 0x69, 0x67, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, - 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x79, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, - 0x28, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, - 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x66, 0x28, - 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x73, - 0x69, 0x67, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, - 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x34, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, - 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x66, 0x28, 0x78, 0x2e, - 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, - 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x63, 0x6f, - 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, - 0x29, 0x2c, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x77, - 0x2c, 0x20, 0x79, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, + 0x67, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, + 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x75, 0x74, + 0x6f, 0x20, 0x75, 0x78, 0x20, 0x3d, 0x20, 0x5f, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x5f, 0x61, 0x73, + 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x78, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x75, 0x79, 0x20, 0x3d, 0x20, 0x5f, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x5f, + 0x61, 0x73, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x79, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, + 0x61, 0x73, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x28, 0x75, 0x78, 0x20, 0x26, 0x20, 0x30, 0x78, + 0x37, 0x66, 0x66, 0x66, 0x75, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x75, 0x79, 0x20, 0x26, 0x20, 0x30, + 0x78, 0x38, 0x30, 0x30, 0x30, 0x75, 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x28, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, - 0x69, 0x67, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2c, 0x20, 0x79, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, - 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, - 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x79, 0x29, 0x20, 0x6e, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, + 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x73, + 0x69, 0x67, 0x6e, 0x66, 0x28, 0x78, 0x2c, 0x20, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, + 0x69, 0x67, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x78, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x63, + 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, + 0x78, 0x29, 0x2c, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x66, 0x28, 0x78, 0x2e, + 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, + 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x63, 0x6f, 0x70, + 0x79, 0x73, 0x69, 0x67, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, + 0x2c, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x79, 0x2c, + 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x66, + 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, + 0x73, 0x69, 0x67, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x78, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, - 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, - 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, - 0x20, 0x79, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, - 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x28, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x33, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, - 0x67, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, - 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, + 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, + 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x66, 0x28, 0x78, + 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, + 0x67, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x63, + 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x77, 0x2c, 0x20, 0x79, 0x2e, + 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, + 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x79, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2c, 0x20, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, - 0x67, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, + 0x67, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6f, + 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, + 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, + 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x33, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, + 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x69, + 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, + 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x2c, + 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x28, 0x6c, + 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x34, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, + 0x67, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, + 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x78, 0x2e, 0x77, 0x2c, 0x20, 0x79, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x73, - 0x69, 0x6e, 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6f, + 0x70, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x2c, + 0x20, 0x79, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, + 0x6f, 0x6c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, + 0x6f, 0x6c, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x32, 0x28, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x69, 0x6e, 0x66, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, - 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, + 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, + 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x32, 0x28, 0x69, 0x73, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, 0x28, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x69, - 0x73, 0x69, 0x6e, 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x69, - 0x73, 0x69, 0x6e, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, - 0x33, 0x28, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, - 0x29, 0x2c, 0x20, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, - 0x79, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, - 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, - 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, - 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x34, - 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, - 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x34, 0x28, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x73, - 0x6e, 0x61, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x73, 0x69, 0x6e, 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, + 0x69, 0x73, 0x69, 0x6e, 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, + 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, + 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x34, 0x20, 0x6c, 0x63, 0x5f, + 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, + 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, + 0x6c, 0x34, 0x28, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, + 0x78, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, + 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, + 0x6f, 0x6c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, + 0x6f, 0x6c, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x32, 0x28, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x6e, 0x61, 0x6e, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, - 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, + 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, + 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x32, 0x28, 0x69, 0x73, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, 0x28, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x69, - 0x73, 0x6e, 0x61, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x69, - 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, - 0x33, 0x28, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, - 0x29, 0x2c, 0x20, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, - 0x79, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, - 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, - 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, - 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x34, - 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, - 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x34, 0x28, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x68, - 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, - 0x6f, 0x6f, 0x6c, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x32, 0x28, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, - 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, - 0x66, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x73, 0x6e, 0x61, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, + 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, + 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, + 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x34, 0x20, 0x6c, 0x63, 0x5f, + 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, + 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, + 0x6c, 0x34, 0x28, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, + 0x78, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, + 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, - 0x6f, 0x6c, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x6c, 0x63, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, 0x28, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, - 0x66, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x66, - 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, - 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, - 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, - 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x34, 0x28, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, - 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x78, - 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x78, 0x2e, - 0x7a, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x77, - 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x6f, 0x6c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, + 0x66, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x32, + 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, + 0x62, 0x6f, 0x6f, 0x6c, 0x32, 0x28, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x78, + 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x78, 0x2e, + 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x6c, - 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, 0x20, + 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, + 0x6f, 0x6f, 0x6c, 0x33, 0x28, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x78, 0x2e, + 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x79, + 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x7a, 0x29, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x34, 0x20, 0x6c, 0x63, + 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x32, 0x20, 0x6c, 0x63, 0x5f, - 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, - 0x32, 0x28, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, - 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, + 0x6c, 0x34, 0x28, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x78, 0x29, + 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, + 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, + 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x69, - 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x78, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, - 0x28, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, - 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, - 0x5f, 0x68, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, - 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, - 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x34, 0x28, 0x5f, - 0x5f, 0x68, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, - 0x68, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, - 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, - 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, - 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, - 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, + 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, + 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, - 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, - 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, - 0x72, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, - 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, - 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, + 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, + 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, - 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, - 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, - 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, - 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, - 0x2b, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, - 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x32, 0x28, 0x5f, 0x5f, + 0x68, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, + 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, + 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, + 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, + 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, 0x28, 0x5f, 0x5f, 0x68, + 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, + 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, + 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, + 0x62, 0x6f, 0x6f, 0x6c, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x6c, + 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x34, 0x28, 0x5f, 0x5f, 0x68, 0x69, 0x73, + 0x6e, 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x6e, + 0x61, 0x6e, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x6e, 0x61, + 0x6e, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x68, 0x69, 0x73, 0x6e, 0x61, 0x6e, + 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, + 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, + 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, + 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, + 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, + 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, + 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, + 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, + 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, + 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, + 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, - 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, + 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, - 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, - 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, - 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, - 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x76, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, - 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, - 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, - 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, - 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x2b, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, - 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, - 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x2a, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, + 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, + 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, + 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x76, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, + 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, + 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, - 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, + 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, + 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, - 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, - 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, - 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, - 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, - 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, - 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x78, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, - 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, - 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, - 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, + 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, + 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, - 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, - 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, - 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, - 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, - 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, - 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, - 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, - 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, - 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x75, - 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, + 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, + 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, - 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, - 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x29, + 0x7a, 0x2b, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, + 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, + 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, + 0x7a, 0x2a, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, + 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, - 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, - 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, - 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, + 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, + 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x6c, + 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, + 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, + 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, + 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, + 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, + 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, + 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x6c, 0x63, + 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, - 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, + 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, - 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, - 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, - 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x2b, 0x76, 0x2e, 0x77, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, - 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, - 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, - 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x2a, 0x76, 0x2e, 0x77, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, - 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, - 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, + 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, - 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, - 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, + 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, + 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, + 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, + 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, + 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x76, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, + 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, + 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, + 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, + 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, + 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, + 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, + 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x2b, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, + 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x76, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x76, 0x2e, 0x78, + 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x2a, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, - 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x76, + 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, - 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x7a, + 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, + 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, + 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, + 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, + 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, + 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, + 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x69, + 0x6e, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, + 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, + 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, - 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, - 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x76, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, - 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, - 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, + 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, + 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, - 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, + 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x69, - 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, - 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x76, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, - 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, - 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, - 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, - 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x76, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, - 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, - 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x2b, - 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, + 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, - 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x69, + 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, + 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, 0x76, + 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, + 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, + 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, + 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, + 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, + 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, + 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, + 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, + 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, + 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, + 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, - 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x2a, 0x76, 0x2e, 0x77, 0x29, + 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x2b, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, - 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, - 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, - 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, - 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, - 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, - 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, - 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, - 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, + 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, + 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x2a, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, - 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, - 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, - 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x76, - 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, - 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, - 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, - 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, - 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, - 0x69, 0x6e, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, - 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, - 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, + 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, + 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, + 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, + 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, + 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, + 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, + 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x7a, 0x2c, + 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, + 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, + 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, + 0x75, 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, + 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x76, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, + 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, - 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, - 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, + 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, - 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, - 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, - 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, - 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, - 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, - 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, + 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, - 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, + 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, - 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, - 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, - 0x2b, 0x76, 0x2e, 0x7a, 0x2b, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, - 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, - 0x2e, 0x7a, 0x2a, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, - 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, - 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, + 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, - 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, + 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, - 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, - 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, - 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, - 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x76, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, - 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, - 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, - 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x6c, - 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, - 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, - 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, - 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, - 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, - 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, - 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x6c, 0x63, - 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, - 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, - 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, - 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, - 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x2b, - 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, - 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, - 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, - 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, - 0x66, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x2a, 0x76, 0x2e, - 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, - 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, - 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x6c, - 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, - 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, - 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, - 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, - 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, - 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, + 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, + 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, + 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, + 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, - 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, - 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, - 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, - 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, - 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, - 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, - 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, - 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, - 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x6c, + 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, + 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, + 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, + 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, + 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, - 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, - 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, + 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, + 0x75, 0x69, 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, + 0x2b, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, - 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, - 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, - 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x2b, 0x76, 0x2e, 0x77, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, - 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, + 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, + 0x6e, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x2a, 0x76, + 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, + 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x2a, 0x76, 0x2e, 0x77, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, - 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, - 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, - 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, - 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, - 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x6c, - 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, - 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, - 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, + 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, - 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, - 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, - 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, + 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, + 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, + 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, + 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, + 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, + 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, - 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x76, 0x29, + 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, + 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, - 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, + 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, - 0x2b, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, - 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, - 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, - 0x6e, 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, - 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x76, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, - 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, - 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, + 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, - 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, + 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, - 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, - 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, - 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x6c, - 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, - 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x2b, 0x76, 0x2e, - 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, - 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, - 0x67, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, - 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x2a, 0x76, 0x2e, 0x77, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, - 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, - 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, - 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, - 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x7a, 0x2c, - 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, + 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, + 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, + 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, + 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, + 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, - 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, + 0x68, 0x61, 0x6c, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, + 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, + 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, + 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x2b, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, - 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, + 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, - 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x76, 0x2e, + 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x2a, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, + 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x76, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, + 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, + 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, + 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, + 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x78, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, + 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x76, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x76, 0x2e, 0x78, + 0x2b, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, + 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, + 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x76, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, + 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, + 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x76, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, + 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2b, + 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, + 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, + 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, + 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, + 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, + 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, + 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x76, 0x2e, 0x78, + 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x2b, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, + 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x76, 0x2e, 0x78, + 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x2a, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, + 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, + 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, + 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, + 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, - 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, - 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, - 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, - 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, - 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, - 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, - 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, - 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, 0x2e, - 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, + 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, + 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, 0x2e, + 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, + 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, + 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, + 0x6f, 0x6e, 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, + 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, + 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, - 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, - 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, + 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, + 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, + 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, + 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, + 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, + 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, + 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, + 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, + 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, + 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, + 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, + 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, - 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, - 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, - 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, - 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, + 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, + 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, + 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, + 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, 0x2e, + 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x2b, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, + 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x76, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2a, + 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x2a, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, + 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, + 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, + 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, + 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, + 0x6e, 0x67, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, + 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, + 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, + 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x76, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, + 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, - 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, - 0x6e, 0x67, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, - 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, - 0x63, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, - 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, - 0x2e, 0x78, 0x2b, 0x76, 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x2b, 0x76, 0x2e, 0x77, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, - 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, - 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, - 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x2a, 0x76, 0x2e, 0x77, 0x29, 0x3b, + 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, + 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, + 0x6e, 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, + 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, + 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, + 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, + 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x76, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, 0x75, + 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, 0x2e, + 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, + 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x28, 0x6c, 0x63, + 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, + 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, 0x2e, 0x79, 0x2a, 0x76, 0x2e, + 0x7a, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, + 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, + 0x67, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, + 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, - 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, + 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, - 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, - 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x7a, - 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, - 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, - 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, - 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, - 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, - 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x62, 0x29, 0x20, + 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, + 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x76, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x73, + 0x75, 0x6d, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x76, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2b, 0x76, + 0x2e, 0x79, 0x2b, 0x76, 0x2e, 0x7a, 0x2b, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x70, 0x72, + 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x61, 0x20, 0x3c, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x76, 0x2e, 0x78, 0x2a, 0x76, + 0x2e, 0x79, 0x2a, 0x76, 0x2e, 0x7a, 0x2a, 0x76, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x69, + 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, + 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x79, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, + 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, + 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, + 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, + 0x6f, 0x6e, 0x67, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x78, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x76, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, + 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, - 0x3e, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x3c, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, - 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x3c, 0x20, - 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, - 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x3e, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x69, - 0x6e, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x61, 0x20, 0x3c, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x75, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, + 0x72, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x3c, 0x20, 0x62, 0x20, 0x3f, 0x20, + 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, + 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x3e, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, + 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x61, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, + 0x3c, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, + 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x3e, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, + 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, + 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x61, 0x20, 0x3c, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x75, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x3e, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x75, - 0x69, 0x6e, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x62, + 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x6c, + 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x3c, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x61, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x3e, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, - 0x6e, 0x67, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x3c, 0x20, 0x62, 0x20, 0x3f, 0x20, - 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, - 0x67, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x62, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x61, 0x20, 0x3e, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, - 0x3c, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, - 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x3e, 0x20, 0x62, 0x20, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x3c, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, - 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, - 0x72, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, - 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x73, - 0x68, 0x6f, 0x72, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, - 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x75, + 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, + 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x3e, 0x20, 0x62, 0x20, 0x3f, 0x20, 0x61, 0x20, + 0x3a, 0x20, 0x62, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, + 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, + 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, + 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x62, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, + 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, + 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, + 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, + 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x61, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x28, 0x6c, + 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, + 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, + 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, - 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x62, + 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, - 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, + 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, - 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x73, - 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, - 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, - 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, - 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, - 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, - 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x62, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, - 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, - 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, - 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, - 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, - 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, - 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, - 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, - 0x72, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, - 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, - 0x72, 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, - 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, - 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, - 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x61, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, - 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, - 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, - 0x62, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, - 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x62, + 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, + 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x61, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, + 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, + 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, + 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x6c, + 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, + 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, - 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x73, 0x68, 0x6f, + 0x72, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, + 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, + 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, + 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, + 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, + 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, + 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, - 0x69, 0x6e, 0x74, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, - 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x69, 0x6e, 0x74, - 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, - 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, - 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, + 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, + 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x69, + 0x6e, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, + 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x6b, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, + 0x20, 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, - 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, - 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, + 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, + 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x6c, 0x63, + 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, - 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, - 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, - 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, - 0x69, 0x6e, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x62, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, - 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, - 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x62, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, - 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, - 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, - 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, - 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, - 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, + 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, @@ -33361,39 +33320,39 @@ extern "C" const char luisa_cuda_builtin_cuda_device_math[499474] = { 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, - 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, + 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, + 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x61, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x61, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x28, 0x6c, 0x63, 0x5f, + 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, - 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, - 0x67, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, + 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, + 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, - 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, + 0x75, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, - 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, - 0x67, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, + 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, + 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, - 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, + 0x75, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, @@ -33401,200 +33360,200 @@ extern "C" const char luisa_cuda_builtin_cuda_device_math[499474] = { 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x61, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x28, - 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, - 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, - 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x28, 0x6c, 0x63, 0x5f, - 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, - 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, - 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, - 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x62, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, - 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, - 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, - 0x62, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, + 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x6b, 0x65, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, + 0x20, 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, + 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, + 0x67, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x62, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, + 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, + 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, + 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, + 0x67, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, + 0x67, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x62, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, + 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, + 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, + 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, + 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, - 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, + 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, + 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, - 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, + 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, - 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, - 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, + 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, + 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, - 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, - 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, + 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, + 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, - 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, + 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, - 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, + 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, + 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, + 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, - 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, - 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x28, 0x6c, 0x63, 0x5f, + 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, + 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, + 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, + 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, - 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, - 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x28, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, - 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, - 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x28, 0x6c, - 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, - 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, - 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, - 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, - 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, - 0x72, 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, - 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, - 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, - 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, - 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, - 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, - 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x69, 0x6e, - 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, - 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x6b, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, + 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, + 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, + 0x72, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, - 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, + 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, + 0x72, 0x74, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, + 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, + 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, + 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, + 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, + 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, + 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, + 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, + 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, + 0x72, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, + 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, + 0x65, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, + 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, + 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x6b, 0x65, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, + 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x29, 0x3b, + 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, + 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, + 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x62, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, + 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, + 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, + 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, + 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, + 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, + 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, + 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, + 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x28, 0x6c, + 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, + 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, - 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, - 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, + 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, + 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, + 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x69, - 0x6e, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x6e, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, - 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x29, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x75, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, - 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, - 0x6e, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, - 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, - 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, - 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, - 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, - 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x28, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, - 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, - 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, - 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, - 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, - 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x28, + 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x69, + 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, + 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x62, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, @@ -33603,38 +33562,38 @@ extern "C" const char luisa_cuda_builtin_cuda_device_math[499474] = { 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, - 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, + 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, + 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, - 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, - 0x6e, 0x67, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, + 0x6e, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, + 0x6e, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x6c, 0x6f, 0x6e, - 0x67, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, + 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x61, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x61, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x61, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, @@ -33642,141 +33601,232 @@ extern "C" const char luisa_cuda_builtin_cuda_device_math[499474] = { 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, - 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, - 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, - 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, - 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, - 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, - 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, - 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, - 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, + 0x6e, 0x67, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, + 0x67, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x62, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, + 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, + 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x28, 0x6c, + 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, + 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, + 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, + 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, + 0x65, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, + 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, + 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, + 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, + 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, + 0x65, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, + 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, + 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, + 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, + 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x62, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, + 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, + 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x62, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, + 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, + 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x29, 0x3b, + 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, + 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x61, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x28, 0x6c, + 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, + 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, + 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, - 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x62, + 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, - 0x67, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, + 0x67, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, - 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, + 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, + 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x76, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2c, 0x20, 0x6c, + 0x6f, 0x29, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, - 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x63, 0x5f, 0x75, - 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, - 0x67, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, - 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, - 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x61, 0x78, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, - 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, - 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, - 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, - 0x72, 0x74, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x6c, - 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, - 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x29, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, - 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x76, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, + 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, + 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, + 0x72, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x29, 0x2c, 0x20, 0x68, + 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, + 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, + 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, + 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x29, 0x2c, + 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, + 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, + 0x6e, 0x74, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x6f, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2c, + 0x20, 0x6c, 0x6f, 0x29, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, + 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x68, + 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x78, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x29, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x76, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x29, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, - 0x69, 0x6e, 0x74, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x6f, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2c, 0x20, - 0x6c, 0x6f, 0x29, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, - 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, - 0x74, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x68, 0x69, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x78, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x29, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, - 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x76, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x29, 0x2c, 0x20, 0x68, - 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, - 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x6f, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, + 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, + 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, + 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x29, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, + 0x6f, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, + 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x29, 0x2c, 0x20, + 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, + 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, + 0x74, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x6c, 0x6f, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, - 0x2c, 0x20, 0x6c, 0x6f, 0x29, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, - 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, - 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x29, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x76, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, + 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, + 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x32, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x6b, 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, + 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, + 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, + 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, + 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, + 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x33, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x6b, 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, + 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, + 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, + 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, + 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, + 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, + 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, + 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x34, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x6b, 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, + 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, + 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, + 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, + 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, + 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, + 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, + 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x77, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, + 0x77, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, + 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, + 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, + 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, + 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, + 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, + 0x72, 0x74, 0x32, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, + 0x74, 0x32, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, + 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, + 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, + 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, + 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, + 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x69, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x28, 0x76, 0x2c, 0x20, 0x6c, - 0x6f, 0x29, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, - 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, - 0x74, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x68, - 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, - 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, - 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x28, 0x6c, 0x63, - 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, - 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, - 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, - 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, - 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x76, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x28, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, @@ -33785,296 +33835,96 @@ extern "C" const char luisa_cuda_builtin_cuda_device_math[499474] = { 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, - 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x76, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x28, 0x6c, 0x63, - 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, - 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, - 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, 0x2c, - 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x77, 0x2c, - 0x20, 0x6c, 0x6f, 0x2e, 0x77, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, - 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, - 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x76, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2c, 0x20, - 0x6c, 0x6f, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, - 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, - 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, - 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, - 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, - 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, - 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, - 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x76, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x6c, 0x6f, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x68, 0x69, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, - 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, - 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, - 0x72, 0x74, 0x34, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, - 0x34, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, - 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, - 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, + 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, + 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x6c, 0x6f, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x68, 0x69, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, + 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x76, 0x2e, 0x77, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x77, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x77, + 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x63, 0x5f, + 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x76, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, + 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x68, 0x69, 0x29, + 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, + 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, + 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x76, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, + 0x6e, 0x74, 0x32, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, + 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, - 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, - 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x77, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x77, 0x2c, 0x20, - 0x68, 0x69, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x68, 0x69, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, - 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, - 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, + 0x74, 0x33, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x6f, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, + 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, + 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, + 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, + 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, + 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, + 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, + 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x69, 0x6e, + 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x76, 0x2e, 0x77, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x77, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x77, + 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x63, + 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x76, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, - 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, - 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, - 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x6c, 0x6f, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, - 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, - 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, - 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, - 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, - 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, - 0x33, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x68, 0x69, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x33, - 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, - 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, - 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, - 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, - 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, - 0x6e, 0x74, 0x34, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, - 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, - 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, - 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, - 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x77, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x77, 0x2c, 0x20, - 0x68, 0x69, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, - 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, - 0x6e, 0x74, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x6f, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2c, - 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, - 0x69, 0x6e, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, - 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, - 0x74, 0x32, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, - 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, - 0x6e, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, - 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, - 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, - 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, - 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, - 0x33, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x6f, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x6c, - 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, - 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, - 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, - 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, - 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, - 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, - 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, - 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, - 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, - 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, - 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, - 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x77, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, - 0x77, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, - 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, - 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, - 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, - 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, - 0x67, 0x32, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, - 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, - 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, - 0x68, 0x69, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, - 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x6c, - 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, - 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x68, 0x69, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, - 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x63, - 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, - 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x6f, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x28, 0x6c, 0x63, 0x5f, - 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, - 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, - 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, - 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x77, 0x2c, 0x20, - 0x6c, 0x6f, 0x2e, 0x77, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, - 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, - 0x6f, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, - 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x68, - 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, - 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, - 0x67, 0x32, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, - 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x68, 0x69, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, - 0x67, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, - 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, - 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, - 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, - 0x67, 0x33, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, - 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x68, 0x69, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, - 0x67, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, - 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, - 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, - 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, - 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, - 0x67, 0x34, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, - 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x68, 0x69, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, - 0x67, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, - 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, - 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, - 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x76, 0x2e, 0x77, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x77, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x77, - 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x63, - 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x76, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, - 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, - 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, - 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, - 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, - 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, - 0x66, 0x32, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, - 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x68, 0x69, 0x29, 0x20, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, + 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, + 0x74, 0x32, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x6c, + 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, - 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, + 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x76, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, + 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, @@ -34083,12 +33933,12 @@ extern "C" const char luisa_cuda_builtin_cuda_device_math[499474] = { 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, + 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, + 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, + 0x75, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, @@ -34098,1387 +33948,1381 @@ extern "C" const char luisa_cuda_builtin_cuda_device_math[499474] = { 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x77, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x77, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, - 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x68, 0x69, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, - 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x76, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, + 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, + 0x67, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x6f, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, + 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2c, 0x20, + 0x6c, 0x6f, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, + 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, + 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, + 0x32, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x68, + 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x6c, 0x6f, 0x6e, + 0x67, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, + 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, + 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, + 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, 0x6f, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x28, 0x6c, 0x63, + 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, + 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, + 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, 0x2c, + 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, + 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x76, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, + 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x6b, 0x65, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, + 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, + 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, + 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, + 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, + 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, + 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, + 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x77, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x77, + 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, + 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, + 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, + 0x6e, 0x67, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, + 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, + 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, + 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x76, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x6f, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x28, 0x6c, + 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, + 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, + 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, + 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x76, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, 0x6f, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x28, 0x6c, + 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, + 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, + 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, + 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, + 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x76, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x6f, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x28, 0x6c, + 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, + 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, + 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, + 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x77, + 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x77, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, + 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x68, 0x69, 0x29, + 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, + 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, + 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x76, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, - 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x63, - 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, - 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, - 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, - 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, - 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, - 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, + 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x33, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, + 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, + 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, + 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x34, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, + 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x68, 0x69, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x76, 0x2e, 0x77, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x77, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x77, 0x29, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, + 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, + 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x6f, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, + 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2c, 0x20, + 0x6c, 0x6f, 0x2c, 0x20, 0x68, 0x69, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x32, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, + 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, + 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x33, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, + 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, + 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, + 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x34, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x78, 0x2c, + 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x79, 0x2c, + 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x7a, 0x2c, + 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x77, 0x2c, 0x20, 0x6c, 0x6f, 0x2e, 0x77, 0x2c, + 0x20, 0x68, 0x69, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, + 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x74, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x74, 0x20, 0x2a, 0x20, 0x28, 0x62, 0x20, 0x2d, 0x20, 0x61, 0x29, 0x20, 0x2b, 0x20, 0x61, + 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, + 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x61, 0x74, 0x75, + 0x72, 0x61, 0x74, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x78, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, - 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x68, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, - 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x78, 0x2c, 0x20, 0x6c, - 0x6f, 0x2e, 0x78, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, - 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x79, 0x2c, 0x20, 0x6c, - 0x6f, 0x2e, 0x79, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, - 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x7a, 0x2c, 0x20, 0x6c, - 0x6f, 0x2e, 0x7a, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, - 0x6c, 0x61, 0x6d, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x76, 0x2e, 0x77, 0x2c, 0x20, 0x6c, - 0x6f, 0x2e, 0x77, 0x2c, 0x20, 0x68, 0x69, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, - 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x20, 0x2a, 0x20, 0x28, 0x62, 0x20, 0x2d, 0x20, 0x61, 0x29, - 0x20, 0x2b, 0x20, 0x61, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x61, 0x74, 0x75, 0x72, 0x61, 0x74, 0x65, 0x28, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, + 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x31, 0x2e, 0x30, + 0x66, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, + 0x61, 0x74, 0x75, 0x72, 0x61, 0x74, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, + 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x78, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, + 0x30, 0x2e, 0x30, 0x66, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x33, 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x61, 0x74, 0x75, 0x72, 0x61, 0x74, 0x65, 0x28, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, + 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x31, 0x2e, 0x30, + 0x66, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, - 0x73, 0x61, 0x74, 0x75, 0x72, 0x61, 0x74, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x61, 0x64, 0x20, + 0x2a, 0x20, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x29, 0x28, 0x31, 0x38, 0x30, 0x2e, + 0x30, 0x66, 0x20, 0x2a, 0x20, 0x30, 0x2e, 0x33, 0x31, 0x38, 0x33, 0x30, 0x39, 0x38, 0x38, 0x36, + 0x31, 0x38, 0x33, 0x37, 0x39, 0x30, 0x36, 0x37, 0x31, 0x35, 0x33, 0x37, 0x37, 0x36, 0x37, 0x35, + 0x32, 0x36, 0x37, 0x34, 0x35, 0x30, 0x32, 0x38, 0x37, 0x32, 0x34, 0x66, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x64, 0x65, + 0x67, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x65, 0x67, 0x20, 0x2a, 0x20, 0x28, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x29, 0x28, 0x33, 0x2e, 0x31, 0x34, 0x31, 0x35, 0x39, 0x32, 0x36, 0x35, 0x33, + 0x35, 0x38, 0x39, 0x37, 0x39, 0x33, 0x32, 0x33, 0x38, 0x34, 0x36, 0x32, 0x36, 0x34, 0x33, 0x33, + 0x38, 0x33, 0x32, 0x37, 0x39, 0x35, 0x30, 0x32, 0x38, 0x38, 0x66, 0x20, 0x2f, 0x20, 0x31, 0x38, + 0x30, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, + 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x20, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x78, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x61, 0x74, 0x75, 0x72, - 0x61, 0x74, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x78, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x30, 0x2e, 0x30, 0x66, - 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, - 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x6c, 0x63, 0x5f, 0x73, 0x61, 0x74, 0x75, 0x72, 0x61, 0x74, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, - 0x6d, 0x70, 0x28, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x33, 0x28, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x61, 0x74, 0x75, 0x72, - 0x61, 0x74, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x78, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x30, 0x2e, 0x30, 0x66, - 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, - 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x72, 0x61, 0x64, 0x20, 0x2a, 0x20, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x29, 0x28, - 0x31, 0x38, 0x30, 0x2e, 0x30, 0x66, 0x20, 0x2a, 0x20, 0x30, 0x2e, 0x33, 0x31, 0x38, 0x33, 0x30, - 0x39, 0x38, 0x38, 0x36, 0x31, 0x38, 0x33, 0x37, 0x39, 0x30, 0x36, 0x37, 0x31, 0x35, 0x33, 0x37, - 0x37, 0x36, 0x37, 0x35, 0x32, 0x36, 0x37, 0x34, 0x35, 0x30, 0x32, 0x38, 0x37, 0x32, 0x34, 0x66, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x28, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x31, 0x2e, 0x66, 0x29, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x30, 0x2e, 0x66, 0x29, 0x2c, 0x20, 0x78, 0x20, 0x3c, 0x20, + 0x65, 0x64, 0x67, 0x65, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, + 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x65, 0x64, 0x67, 0x65, 0x30, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x65, 0x64, 0x67, 0x65, 0x31, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x74, 0x20, + 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x28, 0x78, 0x20, 0x2d, 0x20, + 0x65, 0x64, 0x67, 0x65, 0x30, 0x29, 0x20, 0x2f, 0x20, 0x28, 0x65, 0x64, 0x67, 0x65, 0x31, 0x20, + 0x2d, 0x20, 0x65, 0x64, 0x67, 0x65, 0x30, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x28, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x74, 0x20, 0x2a, 0x20, 0x74, 0x20, 0x2a, 0x20, 0x28, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x28, 0x33, 0x2e, 0x66, 0x29, 0x20, 0x2d, 0x20, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x28, 0x32, 0x2e, 0x66, 0x29, 0x20, 0x2a, 0x20, 0x74, 0x29, 0x3b, 0x0a, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x78, 0x20, 0x2d, 0x20, 0x79, 0x20, + 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x6f, 0x72, 0x28, 0x78, 0x20, 0x2f, 0x20, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, - 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, - 0x66, 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x65, 0x67, 0x20, 0x2a, 0x20, 0x28, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x29, 0x28, 0x33, 0x2e, 0x31, 0x34, 0x31, 0x35, 0x39, - 0x32, 0x36, 0x35, 0x33, 0x35, 0x38, 0x39, 0x37, 0x39, 0x33, 0x32, 0x33, 0x38, 0x34, 0x36, 0x32, - 0x36, 0x34, 0x33, 0x33, 0x38, 0x33, 0x32, 0x37, 0x39, 0x35, 0x30, 0x32, 0x38, 0x38, 0x66, 0x20, - 0x2f, 0x20, 0x31, 0x38, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, + 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x78, + 0x20, 0x2d, 0x20, 0x79, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x28, + 0x78, 0x20, 0x2f, 0x20, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x31, 0x2e, 0x66, 0x29, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x30, 0x2e, 0x66, 0x29, 0x2c, 0x20, - 0x78, 0x20, 0x3c, 0x20, 0x65, 0x64, 0x67, 0x65, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x78, 0x20, 0x2d, 0x20, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x6f, 0x72, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x65, 0x64, 0x67, - 0x65, 0x30, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x65, 0x64, 0x67, 0x65, - 0x31, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x74, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x28, - 0x78, 0x20, 0x2d, 0x20, 0x65, 0x64, 0x67, 0x65, 0x30, 0x29, 0x20, 0x2f, 0x20, 0x28, 0x65, 0x64, - 0x67, 0x65, 0x31, 0x20, 0x2d, 0x20, 0x65, 0x64, 0x67, 0x65, 0x30, 0x29, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x20, 0x2a, 0x20, 0x74, 0x20, 0x2a, 0x20, - 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x33, 0x2e, 0x66, 0x29, 0x20, 0x2d, 0x20, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x32, 0x2e, 0x66, 0x29, 0x20, 0x2a, 0x20, 0x74, - 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x78, 0x20, - 0x2d, 0x20, 0x79, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x6f, 0x72, 0x28, 0x78, - 0x20, 0x2f, 0x20, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, - 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x79, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x78, 0x20, 0x2d, 0x20, 0x79, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x74, 0x72, - 0x75, 0x6e, 0x63, 0x28, 0x78, 0x20, 0x2f, 0x20, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x78, 0x20, - 0x2d, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x6f, 0x72, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, + 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, + 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x20, 0x2a, 0x20, 0x28, 0x62, 0x20, 0x2d, 0x20, 0x61, 0x29, + 0x20, 0x2b, 0x20, 0x61, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, + 0x73, 0x61, 0x74, 0x75, 0x72, 0x61, 0x74, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, + 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x30, 0x2e, 0x30, 0x66, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x31, 0x2e, 0x30, 0x66, + 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x61, + 0x74, 0x75, 0x72, 0x61, 0x74, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, + 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x78, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, + 0x28, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x20, 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x20, 0x2a, 0x20, 0x28, 0x62, 0x20, - 0x2d, 0x20, 0x61, 0x29, 0x20, 0x2b, 0x20, 0x61, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x61, 0x74, 0x75, 0x72, 0x61, 0x74, + 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x30, 0x2e, 0x30, 0x66, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x33, 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x61, 0x74, 0x75, 0x72, 0x61, 0x74, 0x65, 0x28, 0x6c, 0x63, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, - 0x61, 0x6d, 0x70, 0x28, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, - 0x30, 0x2e, 0x30, 0x66, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, - 0x31, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, - 0x63, 0x5f, 0x73, 0x61, 0x74, 0x75, 0x72, 0x61, 0x74, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, - 0x6d, 0x70, 0x28, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x32, 0x28, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x61, 0x74, - 0x75, 0x72, 0x61, 0x74, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, - 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x78, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, - 0x30, 0x2e, 0x30, 0x66, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, + 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x31, 0x2e, 0x30, + 0x66, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, + 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x61, 0x64, + 0x20, 0x2a, 0x20, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x28, 0x31, 0x38, + 0x30, 0x2e, 0x30, 0x66, 0x20, 0x2a, 0x20, 0x30, 0x2e, 0x33, 0x31, 0x38, 0x33, 0x30, 0x39, 0x38, + 0x38, 0x36, 0x31, 0x38, 0x33, 0x37, 0x39, 0x30, 0x36, 0x37, 0x31, 0x35, 0x33, 0x37, 0x37, 0x36, + 0x37, 0x35, 0x32, 0x36, 0x37, 0x34, 0x35, 0x30, 0x32, 0x38, 0x37, 0x32, 0x34, 0x66, 0x29, 0x3b, + 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, + 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, + 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x65, 0x67, 0x20, 0x2a, 0x20, 0x28, 0x6c, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x28, 0x33, 0x2e, 0x31, 0x34, 0x31, 0x35, 0x39, + 0x32, 0x36, 0x35, 0x33, 0x35, 0x38, 0x39, 0x37, 0x39, 0x33, 0x32, 0x33, 0x38, 0x34, 0x36, 0x32, + 0x36, 0x34, 0x33, 0x33, 0x38, 0x33, 0x32, 0x37, 0x39, 0x35, 0x30, 0x32, 0x38, 0x38, 0x66, 0x20, + 0x2f, 0x20, 0x31, 0x38, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, + 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x31, + 0x2e, 0x66, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x30, 0x2e, + 0x66, 0x29, 0x2c, 0x20, 0x78, 0x20, 0x3c, 0x20, 0x65, 0x64, 0x67, 0x65, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, + 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x20, 0x65, 0x64, 0x67, 0x65, 0x30, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x20, 0x65, 0x64, 0x67, 0x65, 0x31, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x74, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, + 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x28, 0x78, 0x20, 0x2d, 0x20, 0x65, 0x64, 0x67, 0x65, 0x30, + 0x29, 0x20, 0x2f, 0x20, 0x28, 0x65, 0x64, 0x67, 0x65, 0x31, 0x20, 0x2d, 0x20, 0x65, 0x64, 0x67, + 0x65, 0x30, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x30, 0x2e, + 0x30, 0x66, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x31, 0x2e, + 0x30, 0x66, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x74, 0x20, 0x2a, 0x20, 0x74, 0x20, 0x2a, 0x20, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x28, 0x33, 0x2e, 0x66, 0x29, 0x20, 0x2d, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x28, 0x32, 0x2e, 0x66, 0x29, 0x20, 0x2a, 0x20, 0x74, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x61, 0x74, 0x75, 0x72, 0x61, 0x74, 0x65, - 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x30, 0x2e, 0x30, 0x66, 0x29, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, - 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x72, 0x61, 0x64, 0x20, 0x2a, 0x20, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x29, 0x28, 0x31, 0x38, 0x30, 0x2e, 0x30, 0x66, 0x20, 0x2a, 0x20, 0x30, 0x2e, 0x33, 0x31, 0x38, - 0x33, 0x30, 0x39, 0x38, 0x38, 0x36, 0x31, 0x38, 0x33, 0x37, 0x39, 0x30, 0x36, 0x37, 0x31, 0x35, - 0x33, 0x37, 0x37, 0x36, 0x37, 0x35, 0x32, 0x36, 0x37, 0x34, 0x35, 0x30, 0x32, 0x38, 0x37, 0x32, - 0x34, 0x66, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, - 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, - 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x65, 0x67, 0x20, - 0x2a, 0x20, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x28, 0x33, 0x2e, 0x31, - 0x34, 0x31, 0x35, 0x39, 0x32, 0x36, 0x35, 0x33, 0x35, 0x38, 0x39, 0x37, 0x39, 0x33, 0x32, 0x33, - 0x38, 0x34, 0x36, 0x32, 0x36, 0x34, 0x33, 0x33, 0x38, 0x33, 0x32, 0x37, 0x39, 0x35, 0x30, 0x32, - 0x38, 0x38, 0x66, 0x20, 0x2f, 0x20, 0x31, 0x38, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x20, 0x7d, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x78, 0x20, 0x2d, 0x20, 0x79, + 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x6f, 0x72, 0x28, 0x78, 0x20, 0x2f, 0x20, + 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, + 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x79, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x66, 0x6d, 0x6f, 0x64, 0x66, 0x28, 0x78, 0x2c, 0x20, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x65, 0x64, 0x67, 0x65, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x28, 0x31, 0x2e, 0x66, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x28, 0x30, 0x2e, 0x66, 0x29, 0x2c, 0x20, 0x78, 0x20, 0x3c, 0x20, 0x65, 0x64, 0x67, 0x65, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, - 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x65, 0x64, 0x67, 0x65, 0x30, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x65, 0x64, 0x67, 0x65, 0x31, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x74, 0x20, 0x3d, - 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x28, 0x78, 0x20, 0x2d, 0x20, 0x65, - 0x64, 0x67, 0x65, 0x30, 0x29, 0x20, 0x2f, 0x20, 0x28, 0x65, 0x64, 0x67, 0x65, 0x31, 0x20, 0x2d, - 0x20, 0x65, 0x64, 0x67, 0x65, 0x30, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x28, 0x30, 0x2e, 0x30, 0x66, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x20, 0x2a, 0x20, 0x74, 0x20, 0x2a, 0x20, 0x28, 0x6c, 0x63, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x33, 0x2e, 0x66, 0x29, 0x20, 0x2d, 0x20, 0x6c, 0x63, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x32, 0x2e, 0x66, 0x29, 0x20, 0x2a, 0x20, 0x74, 0x29, - 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x78, - 0x20, 0x2d, 0x20, 0x79, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x6f, 0x72, 0x28, - 0x78, 0x20, 0x2f, 0x20, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x6d, 0x6f, 0x64, 0x66, 0x28, 0x78, 0x2c, 0x20, 0x79, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, - 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x78, 0x20, 0x2d, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, - 0x6f, 0x72, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, - 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, - 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x62, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, - 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x74, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, + 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x78, 0x20, 0x2d, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x6f, 0x72, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, - 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x61, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, - 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x2c, - 0x20, 0x74, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x2c, 0x20, 0x74, 0x2e, - 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, - 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, - 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, - 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x62, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6c, - 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, - 0x78, 0x2c, 0x20, 0x74, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x2c, 0x20, - 0x74, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x2c, 0x20, 0x74, 0x2e, 0x7a, - 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x6c, - 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, - 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x62, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x65, - 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, - 0x2c, 0x20, 0x74, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x2c, 0x20, 0x74, - 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x2c, 0x20, 0x74, 0x2e, 0x7a, 0x29, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, + 0x6c, 0x65, 0x72, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x61, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x20, 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x74, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, + 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x32, 0x20, 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, + 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x2c, 0x20, 0x74, 0x2e, 0x78, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x2c, 0x20, 0x74, 0x2e, 0x79, 0x29, 0x29, 0x3b, + 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, + 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6c, + 0x65, 0x72, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x61, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x33, 0x20, 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, + 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x2c, 0x20, 0x74, + 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x2c, 0x20, 0x74, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, - 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x2c, 0x20, 0x74, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, - 0x72, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x20, 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x74, 0x29, 0x3b, 0x20, + 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x2c, 0x20, 0x74, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6c, - 0x65, 0x72, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x61, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6c, - 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, - 0x78, 0x2c, 0x20, 0x74, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x2c, 0x20, - 0x74, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x33, 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x74, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x2c, 0x20, 0x74, 0x2e, 0x78, 0x29, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, - 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x2c, 0x20, 0x74, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, - 0x2e, 0x7a, 0x2c, 0x20, 0x74, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x28, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x34, 0x20, 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, + 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, + 0x72, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x34, 0x20, 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x2c, 0x20, 0x74, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x2c, 0x20, 0x74, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x2c, 0x20, 0x74, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, - 0x62, 0x2e, 0x77, 0x2c, 0x20, 0x74, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, - 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, - 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x28, 0x6c, 0x63, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x65, - 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x78, - 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x62, 0x2e, 0x77, 0x2c, 0x20, 0x74, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, - 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, - 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x72, 0x61, 0x64, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, - 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x79, 0x29, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x72, 0x61, 0x64, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x28, 0x6c, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, + 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x74, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x28, + 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x32, 0x20, 0x74, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x2c, 0x20, 0x74, + 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x2c, 0x20, 0x74, 0x2e, 0x79, 0x29, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, + 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, + 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x62, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x74, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, + 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x78, 0x2c, + 0x20, 0x62, 0x2e, 0x78, 0x2c, 0x20, 0x74, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, + 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, 0x2c, 0x20, 0x62, 0x2e, + 0x79, 0x2c, 0x20, 0x74, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x2e, 0x7a, 0x2c, 0x20, + 0x74, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x34, 0x20, 0x62, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x74, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x61, 0x2e, 0x78, 0x2c, 0x20, 0x62, 0x2e, 0x78, 0x2c, 0x20, 0x74, 0x2e, 0x78, 0x29, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x79, + 0x2c, 0x20, 0x62, 0x2e, 0x79, 0x2c, 0x20, 0x74, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x6c, 0x65, 0x72, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x7a, 0x2c, 0x20, 0x62, + 0x2e, 0x7a, 0x2c, 0x20, 0x74, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x72, + 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x61, 0x2e, 0x77, 0x2c, 0x20, 0x62, 0x2e, 0x77, 0x2c, + 0x20, 0x74, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x28, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, - 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, - 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x28, 0x6c, 0x63, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, - 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, - 0x65, 0x65, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x72, 0x61, 0x64, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, - 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, - 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x72, 0x61, 0x64, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, - 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x79, 0x29, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, - 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x33, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, - 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, - 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x78, 0x29, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x72, 0x61, 0x64, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, - 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x7a, 0x29, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, - 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x34, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, - 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, + 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x32, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, + 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, + 0x61, 0x64, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x28, 0x6c, 0x63, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x64, + 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, + 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, + 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, + 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, + 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, + 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x34, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x72, 0x61, 0x64, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x28, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, - 0x65, 0x67, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, - 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, - 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x32, 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, - 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x78, 0x29, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x64, 0x65, 0x67, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x28, 0x72, 0x61, 0x64, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x28, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x28, + 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x6c, 0x63, - 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, - 0x67, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, - 0x67, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x28, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, + 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, + 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, + 0x72, 0x65, 0x65, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x72, + 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, + 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, + 0x72, 0x65, 0x65, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x72, + 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, + 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x72, 0x61, 0x64, + 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, - 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x28, 0x6c, 0x63, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x72, 0x61, + 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, + 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x29, 0x3b, + 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, + 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x72, + 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, + 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, + 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, + 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x33, 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, + 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x78, 0x29, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, + 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x7a, 0x29, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x63, + 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x34, 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, + 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, + 0x65, 0x67, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, + 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, + 0x65, 0x67, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x28, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, + 0x67, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, + 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x32, 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, - 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x7a, + 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, + 0x6e, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x64, 0x65, 0x67, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, + 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, + 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, - 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, + 0x6e, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x64, 0x65, 0x67, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, + 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, + 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x79, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, + 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, + 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x77, + 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, + 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x65, + 0x64, 0x67, 0x65, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x64, 0x65, 0x67, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x28, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x6c, - 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, - 0x65, 0x67, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, - 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x72, - 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, - 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, - 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, - 0x65, 0x67, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, - 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, + 0x64, 0x67, 0x65, 0x2c, 0x20, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x32, 0x20, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, + 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x78, 0x2c, 0x20, 0x78, 0x2e, 0x78, 0x29, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, + 0x64, 0x67, 0x65, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, + 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x73, + 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x78, 0x2c, + 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, + 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, + 0x64, 0x67, 0x65, 0x2e, 0x7a, 0x2c, 0x20, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, + 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x73, + 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x78, 0x2c, + 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, + 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, + 0x64, 0x67, 0x65, 0x2e, 0x7a, 0x2c, 0x20, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x77, + 0x2c, 0x20, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x72, - 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, - 0x20, 0x64, 0x65, 0x67, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, - 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, - 0x65, 0x67, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, - 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, 0x65, 0x67, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x64, - 0x65, 0x67, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x73, + 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x65, 0x64, + 0x67, 0x65, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x78, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, + 0x64, 0x67, 0x65, 0x2e, 0x78, 0x2c, 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x79, + 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x20, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, - 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x28, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x74, - 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x78, 0x2c, 0x20, - 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, - 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x65, 0x64, - 0x67, 0x65, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x78, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, - 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, - 0x65, 0x2e, 0x78, 0x2c, 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, - 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x79, 0x2c, 0x20, - 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x7a, 0x2c, 0x20, 0x78, 0x2e, 0x7a, 0x29, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, - 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x65, 0x64, - 0x67, 0x65, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, - 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, - 0x65, 0x2e, 0x78, 0x2c, 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, - 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x79, 0x2c, 0x20, - 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x7a, 0x2c, 0x20, 0x78, 0x2e, 0x7a, 0x29, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, - 0x67, 0x65, 0x2e, 0x77, 0x2c, 0x20, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x28, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, - 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, - 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x32, 0x20, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x78, 0x2c, 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x74, + 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x78, 0x2c, 0x20, + 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, + 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, - 0x67, 0x65, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x67, 0x65, 0x2e, 0x7a, 0x2c, 0x20, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, - 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x65, 0x64, 0x67, 0x65, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, + 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x65, 0x64, 0x67, 0x65, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x78, 0x2c, 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x7a, 0x2c, 0x20, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, - 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x65, - 0x64, 0x67, 0x65, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x78, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x65, 0x64, 0x67, 0x65, 0x2e, 0x78, 0x2c, 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, - 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x7a, 0x2c, 0x20, 0x78, 0x2e, - 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x77, 0x2c, 0x20, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, - 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, - 0x20, 0x65, 0x30, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x65, 0x31, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x65, 0x30, 0x2c, 0x20, 0x65, 0x31, 0x2c, 0x20, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x6c, 0x28, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x7a, 0x2c, 0x20, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x64, 0x67, + 0x65, 0x2e, 0x77, 0x2c, 0x20, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, - 0x68, 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x65, - 0x30, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x65, 0x31, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x73, + 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, + 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x65, 0x30, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x65, 0x31, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, + 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2c, + 0x20, 0x65, 0x31, 0x2c, 0x20, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, + 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x65, 0x30, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x65, 0x31, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, + 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, + 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x78, 0x2c, + 0x20, 0x65, 0x31, 0x2e, 0x78, 0x2c, 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x65, 0x30, 0x2e, 0x79, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x63, + 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x33, 0x20, 0x65, 0x30, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x33, 0x20, 0x65, 0x31, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x78, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x78, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x78, 0x2c, + 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, + 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x79, 0x2c, 0x20, + 0x65, 0x31, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, - 0x30, 0x2e, 0x78, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x78, 0x2c, 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x79, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x79, 0x2c, 0x20, - 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, - 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x28, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x65, 0x30, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x65, 0x31, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, - 0x66, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, - 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x78, 0x2c, 0x20, 0x65, - 0x31, 0x2e, 0x78, 0x2c, 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, + 0x30, 0x2e, 0x7a, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x7a, 0x2c, 0x20, 0x78, 0x2e, 0x7a, 0x29, 0x29, + 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, + 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, + 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x34, 0x20, 0x65, 0x30, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, + 0x20, 0x65, 0x31, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, + 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, + 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x78, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x78, 0x2c, 0x20, + 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, + 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x79, 0x2c, 0x20, 0x65, + 0x31, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, - 0x2e, 0x79, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, + 0x2e, 0x7a, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x7a, 0x2c, 0x20, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x7a, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x7a, 0x2c, 0x20, 0x78, - 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x77, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x77, 0x2c, 0x20, 0x78, + 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, - 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x65, 0x30, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x34, 0x20, 0x65, 0x31, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, - 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, - 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x78, 0x2c, 0x20, 0x65, 0x31, - 0x2e, 0x78, 0x2c, 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x65, 0x30, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x65, 0x31, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, + 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2c, 0x20, 0x65, 0x31, + 0x2c, 0x20, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x28, + 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x65, 0x30, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x65, 0x31, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, - 0x79, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, + 0x78, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x78, 0x2c, 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x7a, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x7a, 0x2c, 0x20, 0x78, 0x2e, - 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, - 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x77, 0x2c, 0x20, 0x65, 0x31, 0x2e, - 0x77, 0x2c, 0x20, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, - 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x65, 0x30, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x65, 0x31, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, - 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, - 0x2c, 0x20, 0x65, 0x31, 0x2c, 0x20, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, - 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x65, 0x30, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x65, 0x31, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x6c, 0x63, + 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x79, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, + 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, + 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x65, 0x30, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x65, 0x31, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, + 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, + 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x78, + 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x78, 0x2c, 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x65, 0x30, 0x2e, 0x78, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x78, 0x2c, 0x20, 0x78, 0x2e, 0x78, + 0x28, 0x65, 0x30, 0x2e, 0x79, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x79, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x79, - 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x7a, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x7a, + 0x2c, 0x20, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, - 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x65, 0x30, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x65, 0x31, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, + 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x65, 0x30, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x65, 0x31, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x78, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x78, 0x2c, 0x20, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x79, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x7a, 0x2c, 0x20, - 0x65, 0x31, 0x2e, 0x7a, 0x2c, 0x20, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, - 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, - 0x20, 0x65, 0x30, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x65, - 0x31, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, - 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x78, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x78, 0x2c, 0x20, - 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, - 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x79, 0x2c, 0x20, 0x65, - 0x31, 0x2e, 0x79, 0x2c, 0x20, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x6d, - 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, 0x30, - 0x2e, 0x7a, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x7a, 0x2c, 0x20, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x65, 0x30, 0x2e, 0x77, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x77, 0x2c, 0x20, 0x78, - 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, - 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2c, 0x20, 0x79, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, - 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, - 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, - 0x66, 0x33, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, - 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, - 0x66, 0x34, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, - 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, - 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x2c, 0x20, 0x79, 0x2e, 0x77, 0x29, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x65, 0x31, 0x2e, 0x7a, 0x2c, 0x20, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, + 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x65, + 0x30, 0x2e, 0x77, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x77, 0x2c, 0x20, 0x78, 0x2e, 0x77, 0x29, 0x29, + 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2c, 0x20, 0x79, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x78, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x79, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, - 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, - 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2c, 0x20, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, - 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, + 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, + 0x20, 0x79, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x33, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x79, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, + 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x2c, + 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x34, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x79, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, + 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x2c, + 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, + 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x2c, 0x20, 0x79, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, + 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, + 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2c, 0x20, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, + 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x6d, + 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, + 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x33, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, + 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, + 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, + 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, + 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x78, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, - 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x79, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, - 0x28, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, - 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, - 0x79, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, - 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x2c, 0x20, 0x79, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, - 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2c, 0x20, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x28, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x32, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, - 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, - 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, + 0x77, 0x2c, 0x20, 0x79, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, + 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x78, 0x2c, 0x20, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x33, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, + 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, - 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x28, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x34, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, - 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, - 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x77, - 0x2c, 0x20, 0x79, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, + 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, + 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x79, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, + 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, + 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, + 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x78, 0x2c, 0x20, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x32, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, - 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, - 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x33, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, - 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, - 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, - 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, - 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x79, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, - 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, - 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, - 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x2c, 0x20, 0x79, 0x2e, 0x77, 0x29, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, - 0x66, 0x72, 0x61, 0x63, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, + 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, + 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, + 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x2c, 0x20, 0x79, 0x2e, + 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, - 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, - 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, - 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, + 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x79, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, + 0x2c, 0x20, 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x32, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, + 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, + 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x33, 0x20, 0x78, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, + 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, + 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, - 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x6c, 0x63, - 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, + 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, + 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x78, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x79, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, + 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x2c, 0x20, 0x79, + 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x2c, 0x20, 0x79, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x2c, 0x20, 0x79, + 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6d, 0x6f, 0x64, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x2c, 0x20, 0x79, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, + 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x29, 0x3b, + 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, + 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x66, + 0x72, 0x61, 0x63, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x78, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, + 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, + 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, + 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x28, 0x6c, 0x63, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, + 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, - 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x28, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x72, - 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, + 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, + 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x28, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x66, - 0x72, 0x61, 0x63, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x78, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, + 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, - 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, + 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x28, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x72, + 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x28, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x72, + 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, + 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, + 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x6c, 0x63, + 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, + 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, + 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, + 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, + 0x74, 0x32, 0x28, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, + 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, - 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6c, - 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, - 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x72, - 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, - 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, - 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, - 0x6e, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, - 0x6e, 0x74, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, - 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x28, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x78, 0x2e, 0x78, - 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, - 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x5f, 0x5f, - 0x63, 0x6c, 0x7a, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x28, - 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x78, 0x2e, 0x7a, 0x29, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, - 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x78, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, - 0x28, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, - 0x6c, 0x7a, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x78, - 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x63, - 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x78, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x6c, 0x6c, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, + 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x6c, 0x63, + 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x28, + 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x78, 0x2e, 0x79, 0x29, + 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, - 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x28, - 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, - 0x63, 0x6c, 0x7a, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x7a, 0x28, - 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x7a, + 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x28, 0x5f, 0x5f, - 0x63, 0x6c, 0x7a, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, - 0x7a, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x6c, - 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x5f, 0x5f, 0x63, + 0x6c, 0x7a, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x78, + 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, + 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x7a, + 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, + 0x5f, 0x63, 0x6c, 0x7a, 0x6c, 0x6c, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, + 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x6c, 0x63, + 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x28, 0x5f, 0x5f, 0x63, 0x6c, + 0x7a, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x6c, + 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, - 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, - 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, + 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x28, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x6c, + 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x28, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x6c, 0x6c, 0x28, 0x78, 0x2e, - 0x7a, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x29, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x63, - 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, - 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, - 0x70, 0x6f, 0x70, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, - 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, + 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, + 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x6c, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, + 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, - 0x69, 0x6e, 0x74, 0x32, 0x28, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, 0x2e, 0x78, 0x29, - 0x2c, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x70, 0x6f, - 0x70, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, - 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, - 0x74, 0x33, 0x28, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, - 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x70, - 0x6f, 0x70, 0x63, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, - 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x5f, 0x5f, - 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, - 0x63, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, - 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, 0x2e, 0x77, 0x29, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, - 0x63, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, - 0x6f, 0x6e, 0x67, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6c, - 0x6c, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, - 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, - 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, - 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x28, 0x6c, 0x63, - 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x28, 0x5f, 0x5f, 0x70, 0x6f, - 0x70, 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, - 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, - 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x78, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, - 0x28, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, - 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, - 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, - 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x70, 0x6f, - 0x70, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, - 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, - 0x6f, 0x6e, 0x67, 0x34, 0x28, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, - 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x79, - 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, - 0x2c, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, - 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x63, 0x5f, - 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, - 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x28, 0x78, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x28, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x6c, 0x6c, 0x28, 0x78, 0x2e, + 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, + 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, + 0x5f, 0x5f, 0x63, 0x6c, 0x7a, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, - 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x78, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, - 0x32, 0x28, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, - 0x5f, 0x62, 0x72, 0x65, 0x76, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x72, - 0x73, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, + 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x70, 0x6f, 0x70, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x78, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x70, 0x6f, 0x70, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x78, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, + 0x28, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, + 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, + 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x5f, - 0x5f, 0x62, 0x72, 0x65, 0x76, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, - 0x65, 0x76, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x28, + 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x70, 0x6f, + 0x70, 0x63, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, - 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x6c, 0x63, 0x5f, - 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x28, - 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x28, 0x78, 0x2e, 0x79, - 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, - 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x76, - 0x65, 0x72, 0x73, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x78, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, 0x6c, 0x28, 0x78, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x28, 0x6c, 0x63, + 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, + 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, 0x2e, + 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, + 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x72, - 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, - 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, - 0x6f, 0x6e, 0x67, 0x32, 0x28, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, 0x6c, 0x28, 0x78, 0x2e, - 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x79, - 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, - 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, - 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, - 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x28, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, - 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, 0x6c, - 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, 0x6c, 0x28, - 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x63, 0x5f, 0x70, 0x6f, + 0x70, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, + 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x29, + 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, + 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x63, + 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, + 0x6e, 0x67, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x28, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6c, 0x6c, + 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6c, 0x6c, 0x28, + 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, - 0x67, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x6c, 0x63, - 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x28, 0x5f, 0x5f, 0x62, 0x72, - 0x65, 0x76, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, - 0x76, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, - 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, - 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, - 0x75, 0x69, 0x6e, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x5f, 0x5f, 0x66, 0x66, 0x73, - 0x28, 0x78, 0x29, 0x20, 0x2d, 0x20, 0x31, 0x75, 0x29, 0x20, 0x25, 0x20, 0x33, 0x32, 0x75, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x78, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x28, 0x5f, 0x5f, 0x66, 0x66, 0x73, 0x6c, 0x6c, 0x28, 0x78, 0x29, 0x20, 0x2d, 0x20, - 0x31, 0x75, 0x29, 0x20, 0x25, 0x20, 0x36, 0x34, 0x75, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, + 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x28, 0x6c, + 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x28, 0x5f, 0x5f, 0x70, + 0x6f, 0x70, 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x70, 0x6f, + 0x70, 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x70, 0x6f, 0x70, + 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, - 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, - 0x69, 0x6e, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, - 0x6e, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, - 0x6e, 0x74, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, - 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x78, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, + 0x28, 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, + 0x5f, 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, + 0x5f, 0x70, 0x6f, 0x70, 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x5f, 0x5f, + 0x70, 0x6f, 0x70, 0x63, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x76, 0x65, + 0x72, 0x73, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x78, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, - 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x28, 0x6c, 0x63, - 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, - 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, - 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, - 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, - 0x74, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x6c, - 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, - 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, - 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, - 0x6e, 0x67, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, - 0x6e, 0x67, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, - 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, - 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, - 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, - 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, - 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, + 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, + 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x28, 0x6c, - 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, - 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, - 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, - 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, - 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, - 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, - 0x67, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, - 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, - 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, - 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, - 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x33, 0x20, 0x75, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x75, 0x2e, 0x79, 0x20, 0x2a, 0x20, - 0x76, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x76, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x75, 0x2e, 0x7a, 0x2c, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x75, 0x2e, 0x7a, 0x20, 0x2a, - 0x20, 0x76, 0x2e, 0x78, 0x20, 0x2d, 0x20, 0x76, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x75, 0x2e, 0x78, - 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x75, 0x2e, 0x78, 0x20, - 0x2a, 0x20, 0x76, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x76, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x75, 0x2e, - 0x79, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, - 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, - 0x6f, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x61, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x61, - 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x79, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x62, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x62, 0x2e, - 0x78, 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x79, 0x20, 0x2b, 0x20, - 0x61, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x7a, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, - 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x62, - 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x79, 0x20, 0x2b, - 0x20, 0x61, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x7a, 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x77, - 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x77, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x28, 0x5f, 0x5f, + 0x62, 0x72, 0x65, 0x76, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, + 0x76, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x71, 0x72, 0x74, - 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6c, 0x63, 0x5f, 0x73, 0x71, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, - 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, - 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x71, 0x72, 0x74, 0x28, 0x6c, - 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, - 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, - 0x20, 0x76, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, - 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, + 0x6e, 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x6c, + 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, - 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x61, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, + 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x5f, 0x5f, 0x62, 0x72, 0x65, + 0x76, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x28, 0x78, + 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, - 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, - 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, + 0x5f, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, + 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, + 0x69, 0x6e, 0x74, 0x34, 0x28, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x28, 0x78, 0x2e, 0x78, 0x29, + 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, + 0x5f, 0x62, 0x72, 0x65, 0x76, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, + 0x65, 0x76, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, + 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, + 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, + 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, 0x6c, 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, + 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x72, + 0x73, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x61, 0x20, 0x2d, 0x20, - 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, - 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x62, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x61, 0x20, 0x2d, - 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, + 0x28, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, + 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x72, + 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, + 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, + 0x6f, 0x6e, 0x67, 0x33, 0x28, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, 0x6c, 0x28, 0x78, 0x2e, + 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x79, + 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, + 0x63, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, + 0x6e, 0x67, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x28, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, 0x6c, + 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, 0x6c, 0x28, + 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, 0x6c, 0x28, 0x78, + 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x5f, 0x5f, 0x62, 0x72, 0x65, 0x76, 0x6c, 0x6c, 0x28, 0x78, 0x2e, + 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, - 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, - 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x61, - 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, + 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x5f, 0x5f, 0x66, 0x66, 0x73, 0x28, 0x78, 0x29, 0x20, + 0x2d, 0x20, 0x31, 0x75, 0x29, 0x20, 0x25, 0x20, 0x33, 0x32, 0x75, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x5f, + 0x5f, 0x66, 0x66, 0x73, 0x6c, 0x6c, 0x28, 0x78, 0x29, 0x20, 0x2d, 0x20, 0x31, 0x75, 0x29, 0x20, + 0x25, 0x20, 0x36, 0x34, 0x75, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, - 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, - 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, - 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, - 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, - 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, - 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x28, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6e, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x69, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x33, 0x20, 0x6e, 0x5f, 0x72, 0x65, 0x66, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, + 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, + 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, + 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, + 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, + 0x74, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, + 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, + 0x74, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, + 0x74, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, + 0x75, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, + 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, + 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, + 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x28, 0x6c, + 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, - 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x2d, 0x6e, 0x2c, 0x20, 0x6e, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x6e, 0x5f, 0x72, 0x65, 0x66, 0x2c, 0x20, 0x69, 0x29, 0x20, 0x3c, - 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x30, 0x2e, 0x66, 0x29, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, + 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x74, + 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x77, + 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, + 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x78, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, + 0x78, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, + 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, + 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, + 0x6f, 0x6e, 0x67, 0x32, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, + 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, + 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x28, 0x6c, 0x63, 0x5f, + 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, + 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x74, + 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x29, + 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, - 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x73, 0x71, 0x72, - 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, - 0x6c, 0x69, 0x7a, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, + 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x6c, 0x63, + 0x5f, 0x63, 0x74, 0x7a, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x78, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x76, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x73, 0x71, 0x72, 0x74, - 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, - 0x69, 0x7a, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x76, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x73, 0x71, 0x72, 0x74, 0x28, - 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, - 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, - 0x66, 0x33, 0x20, 0x75, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x33, 0x28, 0x75, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x76, 0x2e, 0x7a, 0x20, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, + 0x67, 0x34, 0x28, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, + 0x2e, 0x78, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, 0x70, 0x6c, + 0x28, 0x78, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, 0x69, 0x6d, + 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x63, 0x74, 0x7a, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x28, 0x78, 0x2e, 0x77, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, + 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, + 0x20, 0x75, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x75, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x76, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x76, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x75, 0x2e, 0x7a, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x75, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x76, 0x2e, 0x78, @@ -35489,1397 +35333,1551 @@ extern "C" const char luisa_cuda_builtin_cuda_device_math[499474] = { 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x2e, 0x78, - 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x62, - 0x2e, 0x79, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, - 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, - 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x61, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x79, 0x20, - 0x2a, 0x20, 0x62, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x62, 0x2e, - 0x7a, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, - 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x79, 0x20, 0x2a, - 0x20, 0x62, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x7a, - 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x77, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x77, 0x3b, 0x0a, 0x7d, 0x0a, - 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x73, 0x71, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, - 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x20, 0x62, 0x2e, 0x79, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, + 0x64, 0x6f, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x61, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x61, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x78, 0x20, 0x2b, 0x20, + 0x61, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x7a, 0x20, + 0x2a, 0x20, 0x62, 0x2e, 0x7a, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, + 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x61, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x78, 0x20, 0x2b, + 0x20, 0x61, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x7a, + 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x7a, 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x77, 0x20, 0x2a, 0x20, 0x62, + 0x2e, 0x77, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x71, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x64, - 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, + 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x71, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, + 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, + 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, + 0x71, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, + 0x67, 0x74, 0x68, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x71, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x6f, + 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x71, 0x72, - 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, + 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x76, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x3b, + 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, + 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, + 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, - 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x76, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x61, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x61, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, 0x20, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, - 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, - 0x6c, 0x66, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, - 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, - 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, - 0x65, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, - 0x66, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x62, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, - 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, - 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x62, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, - 0x61, 0x72, 0x65, 0x64, 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x66, 0x6f, 0x72, 0x77, - 0x61, 0x72, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6e, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x69, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6e, 0x5f, 0x72, 0x65, 0x66, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, - 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x2d, 0x6e, 0x2c, 0x20, 0x6e, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x6e, 0x5f, 0x72, 0x65, 0x66, 0x2c, 0x20, 0x69, 0x29, 0x20, - 0x3c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x30, 0x2e, 0x66, 0x29, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x76, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x76, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x73, 0x71, 0x72, 0x74, - 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, + 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, - 0x69, 0x7a, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x76, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x73, 0x71, 0x72, 0x74, 0x28, 0x6c, - 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, + 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, + 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, + 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, + 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, + 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, + 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x61, 0x20, 0x2d, 0x20, + 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x61, 0x20, 0x2d, + 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, + 0x66, 0x61, 0x63, 0x65, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6e, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x33, 0x20, 0x69, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, + 0x6e, 0x5f, 0x72, 0x65, 0x66, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, + 0x63, 0x74, 0x28, 0x2d, 0x6e, 0x2c, 0x20, 0x6e, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, + 0x28, 0x6e, 0x5f, 0x72, 0x65, 0x66, 0x2c, 0x20, 0x69, 0x29, 0x20, 0x3c, 0x20, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, 0x30, 0x2e, 0x66, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, - 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x76, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x73, 0x71, 0x72, 0x74, 0x28, 0x6c, 0x63, + 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, + 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x73, 0x71, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, - 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, + 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, + 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x28, + 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, + 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x73, 0x71, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x64, + 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, + 0x63, 0x72, 0x6f, 0x73, 0x73, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x75, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x33, 0x28, 0x75, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x76, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x76, 0x2e, + 0x79, 0x20, 0x2a, 0x20, 0x75, 0x2e, 0x7a, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x75, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x76, 0x2e, 0x78, 0x20, 0x2d, 0x20, 0x76, + 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x75, 0x2e, 0x78, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x75, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x76, 0x2e, 0x79, 0x20, 0x2d, 0x20, + 0x76, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x75, 0x2e, 0x79, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, - 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, - 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x73, 0x65, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, - 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x78, 0x32, 0x20, 0x6d, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, - 0x78, 0x32, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, - 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, - 0x79, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x73, - 0x65, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x33, 0x78, 0x33, 0x20, 0x6d, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x78, 0x33, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, - 0x2c, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, - 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, - 0x2c, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, - 0x2c, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, + 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x62, + 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x79, 0x3b, 0x0a, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x6c, 0x63, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x2e, 0x78, 0x20, + 0x2a, 0x20, 0x62, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x62, 0x2e, + 0x79, 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x7a, 0x3b, 0x0a, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x2e, 0x78, 0x20, 0x2a, + 0x20, 0x62, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x79, + 0x20, 0x2b, 0x20, 0x61, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x7a, 0x20, 0x2b, 0x20, 0x61, + 0x2e, 0x77, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x77, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, + 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x71, 0x72, + 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, + 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, + 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, + 0x68, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x73, 0x71, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, + 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, + 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, + 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x71, 0x72, 0x74, 0x28, 0x6c, 0x63, + 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, + 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, + 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, - 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x73, 0x65, - 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, - 0x78, 0x34, 0x20, 0x6d, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x2c, - 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x2c, - 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x2c, - 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x2c, - 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x2c, - 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x2c, - 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x77, 0x2c, - 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x2c, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x2c, - 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, + 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, + 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, + 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, + 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, + 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, + 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, + 0x67, 0x74, 0x68, 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, + 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x6c, + 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, + 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, + 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, + 0x61, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x62, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, + 0x65, 0x64, 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, - 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, - 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, - 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x78, 0x32, 0x20, 0x6d, 0x29, 0x20, - 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, - 0x6d, 0x5b, 0x31, 0x5d, 0x5b, 0x31, 0x5d, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x5b, 0x30, - 0x5d, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x5b, 0x31, 0x5d, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, + 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x71, + 0x75, 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x61, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6c, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, + 0x64, 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, + 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x71, 0x75, + 0x61, 0x72, 0x65, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x61, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x62, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, + 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64, + 0x28, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, + 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x28, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x6e, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x33, 0x20, 0x69, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, + 0x20, 0x6e, 0x5f, 0x72, 0x65, 0x66, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, + 0x65, 0x63, 0x74, 0x28, 0x2d, 0x6e, 0x2c, 0x20, 0x6e, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, + 0x74, 0x28, 0x6e, 0x5f, 0x72, 0x65, 0x66, 0x2c, 0x20, 0x69, 0x29, 0x20, 0x3c, 0x20, 0x6c, 0x63, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x30, 0x2e, 0x66, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, + 0x65, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x76, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x73, 0x71, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, + 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, + 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x28, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x20, + 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x73, 0x71, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x6f, + 0x74, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, + 0x20, 0x6c, 0x63, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x28, 0x6c, 0x63, + 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x20, 0x2a, 0x20, + 0x6c, 0x63, 0x5f, 0x72, 0x73, 0x71, 0x72, 0x74, 0x28, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, + 0x76, 0x2c, 0x20, 0x76, 0x29, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, + 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x70, 0x6f, 0x73, 0x65, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x78, 0x32, 0x20, 0x6d, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x78, 0x32, 0x28, 0x6d, + 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, + 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x29, 0x3b, 0x20, + 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, + 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, + 0x20, 0x6c, 0x63, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x73, 0x65, 0x28, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x78, 0x33, 0x20, + 0x6d, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x33, 0x78, 0x33, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, + 0x31, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, + 0x30, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, + 0x32, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, + 0x31, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, + 0x6c, 0x63, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x73, 0x65, 0x28, 0x63, 0x6f, 0x6e, + 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x20, 0x6d, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x34, 0x78, 0x34, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x31, + 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x33, + 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x31, + 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x33, + 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x31, + 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x33, + 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x77, 0x2c, 0x20, 0x6d, 0x5b, 0x31, + 0x5d, 0x2e, 0x77, 0x2c, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x2c, 0x20, 0x6d, 0x5b, 0x33, + 0x5d, 0x2e, 0x77, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x78, 0x33, 0x20, 0x6d, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x2f, 0x2f, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x47, 0x4c, - 0x4d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6d, 0x5b, 0x30, - 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, - 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, - 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x28, 0x6d, - 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, - 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, - 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x6d, 0x5b, 0x32, - 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, - 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, - 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, - 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, - 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, - 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x28, 0x63, 0x6f, 0x6e, 0x73, - 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x20, 0x6d, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x2f, 0x2f, 0x20, 0x66, 0x72, - 0x6f, 0x6d, 0x20, 0x47, 0x4c, 0x4d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x30, 0x20, 0x3d, 0x20, 0x6d, - 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, - 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x32, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, - 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, - 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, - 0x30, 0x33, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, - 0x32, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, - 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, - 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x34, 0x20, 0x3d, 0x20, - 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, - 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, - 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x36, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, - 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, - 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x78, 0x32, 0x20, 0x6d, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, + 0x5b, 0x31, 0x5d, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, + 0x6d, 0x5b, 0x30, 0x5d, 0x5b, 0x31, 0x5d, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, + 0x6e, 0x74, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x33, 0x78, 0x33, 0x20, 0x6d, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x2f, 0x2f, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x47, 0x4c, 0x4d, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x20, + 0x2a, 0x20, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, + 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, + 0x31, 0x5d, 0x2e, 0x7a, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, + 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, + 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, + 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x29, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, + 0x2a, 0x20, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, + 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, + 0x30, 0x5d, 0x2e, 0x7a, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, + 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x65, 0x74, 0x65, + 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x63, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x20, 0x6d, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x2f, 0x2f, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x47, + 0x4c, 0x4d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, + 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x30, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, + 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, + 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, - 0x66, 0x30, 0x37, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, - 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, + 0x66, 0x30, 0x32, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, + 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, - 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x38, 0x20, 0x3d, - 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, - 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, - 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x30, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, - 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, - 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, + 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x33, 0x20, 0x3d, + 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, + 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, + 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, + 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x34, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, + 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, + 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, - 0x65, 0x66, 0x31, 0x31, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, - 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, - 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, - 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x32, 0x20, - 0x3d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, - 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, + 0x65, 0x66, 0x30, 0x36, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, + 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, + 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x37, 0x20, + 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, + 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, - 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x34, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, - 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, - 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, + 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x38, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, + 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, + 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, - 0x6f, 0x65, 0x66, 0x31, 0x35, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, - 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, - 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, - 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x36, - 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, - 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, - 0x32, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x38, 0x20, 0x3d, 0x20, 0x6d, 0x5b, - 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, - 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x3b, + 0x6f, 0x65, 0x66, 0x31, 0x30, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, + 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, + 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x31, + 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, + 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, + 0x31, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x32, 0x20, 0x3d, 0x20, 0x6d, 0x5b, + 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, + 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x63, 0x6f, 0x65, 0x66, 0x31, 0x39, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, - 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, - 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, - 0x30, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, - 0x5d, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, - 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x32, 0x20, 0x3d, 0x20, 0x6d, - 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2d, - 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, + 0x63, 0x6f, 0x65, 0x66, 0x31, 0x34, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, + 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, + 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, + 0x35, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, + 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, + 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x36, 0x20, 0x3d, 0x20, 0x6d, + 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, + 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x33, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, - 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, - 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x63, 0x30, - 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x30, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x30, - 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x32, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x33, - 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x66, 0x61, 0x63, 0x31, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x34, 0x2c, 0x20, - 0x63, 0x6f, 0x65, 0x66, 0x30, 0x34, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x36, 0x2c, 0x20, - 0x63, 0x6f, 0x65, 0x66, 0x30, 0x37, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, - 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x63, 0x32, 0x20, 0x3d, 0x20, 0x6c, + 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x38, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, + 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, + 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, + 0x31, 0x39, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, + 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, + 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, + 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x30, 0x20, 0x3d, 0x20, + 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, + 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, + 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, + 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x32, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, + 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, + 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x3b, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, + 0x66, 0x32, 0x33, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, + 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, + 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, + 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x63, 0x30, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, - 0x65, 0x66, 0x30, 0x38, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x38, 0x2c, 0x20, 0x63, 0x6f, - 0x65, 0x66, 0x31, 0x30, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x31, 0x29, 0x3b, 0x0a, 0x20, + 0x65, 0x66, 0x30, 0x30, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x30, 0x2c, 0x20, 0x63, 0x6f, + 0x65, 0x66, 0x30, 0x32, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x33, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, - 0x63, 0x33, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x32, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, - 0x31, 0x32, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x34, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, - 0x31, 0x35, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, - 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x63, 0x34, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x36, - 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x36, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x38, - 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x39, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, - 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x63, 0x35, 0x20, 0x3d, + 0x63, 0x31, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x34, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, + 0x30, 0x34, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x36, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, + 0x30, 0x37, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x63, 0x32, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x38, + 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x38, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x30, + 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x63, 0x33, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, - 0x63, 0x6f, 0x65, 0x66, 0x32, 0x30, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x30, 0x2c, 0x20, - 0x63, 0x6f, 0x65, 0x66, 0x32, 0x32, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x33, 0x29, 0x3b, + 0x63, 0x6f, 0x65, 0x66, 0x31, 0x32, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x32, 0x2c, 0x20, + 0x63, 0x6f, 0x65, 0x66, 0x31, 0x34, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x35, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x56, 0x65, 0x63, 0x30, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, - 0x30, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, - 0x30, 0x5d, 0x2e, 0x78, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x56, 0x65, 0x63, 0x31, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6d, 0x5b, 0x31, 0x5d, - 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, - 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x56, 0x65, 0x63, 0x32, + 0x66, 0x61, 0x63, 0x34, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x36, 0x2c, 0x20, 0x63, 0x6f, + 0x65, 0x66, 0x31, 0x36, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x38, 0x2c, 0x20, 0x63, 0x6f, + 0x65, 0x66, 0x31, 0x39, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x63, 0x35, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, + 0x32, 0x30, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x30, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, + 0x32, 0x32, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x33, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x56, 0x65, 0x63, 0x30, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x34, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, - 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, + 0x34, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, + 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x56, 0x65, 0x63, 0x33, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x2c, 0x20, - 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x77, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x77, 0x2c, 0x20, - 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x77, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, - 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x30, 0x20, 0x3d, 0x20, 0x56, - 0x65, 0x63, 0x31, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x30, 0x20, 0x2d, 0x20, 0x56, 0x65, 0x63, - 0x32, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x31, 0x20, 0x2b, 0x20, 0x56, 0x65, 0x63, 0x33, 0x20, - 0x2a, 0x20, 0x66, 0x61, 0x63, 0x32, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, - 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x31, 0x20, 0x3d, 0x20, 0x56, 0x65, - 0x63, 0x30, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x30, 0x20, 0x2d, 0x20, 0x56, 0x65, 0x63, 0x32, - 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x33, 0x20, 0x2b, 0x20, 0x56, 0x65, 0x63, 0x33, 0x20, 0x2a, - 0x20, 0x66, 0x61, 0x63, 0x34, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x32, 0x20, 0x3d, 0x20, 0x56, 0x65, 0x63, - 0x30, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x31, 0x20, 0x2d, 0x20, 0x56, 0x65, 0x63, 0x31, 0x20, - 0x2a, 0x20, 0x66, 0x61, 0x63, 0x33, 0x20, 0x2b, 0x20, 0x56, 0x65, 0x63, 0x33, 0x20, 0x2a, 0x20, - 0x66, 0x61, 0x63, 0x35, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x33, 0x20, 0x3d, 0x20, 0x56, 0x65, 0x63, 0x30, - 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x32, 0x20, 0x2d, 0x20, 0x56, 0x65, 0x63, 0x31, 0x20, 0x2a, - 0x20, 0x66, 0x61, 0x63, 0x34, 0x20, 0x2b, 0x20, 0x56, 0x65, 0x63, 0x32, 0x20, 0x2a, 0x20, 0x66, - 0x61, 0x63, 0x35, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, - 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x61, 0x20, 0x3d, - 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, - 0x2b, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2d, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2b, 0x31, - 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2d, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x62, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x2d, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2b, - 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2d, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2b, 0x31, 0x2e, - 0x30, 0x66, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, - 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x30, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x76, 0x30, - 0x20, 0x2a, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x61, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, - 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x31, 0x20, - 0x3d, 0x20, 0x69, 0x6e, 0x76, 0x31, 0x20, 0x2a, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x62, 0x3b, + 0x6f, 0x20, 0x56, 0x65, 0x63, 0x31, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x2c, 0x20, + 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x2c, 0x20, + 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, + 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x56, 0x65, 0x63, 0x32, 0x20, 0x3d, 0x20, 0x6c, + 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6d, 0x5b, + 0x31, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, + 0x30, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x29, 0x3b, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x56, 0x65, + 0x63, 0x33, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x34, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, + 0x2e, 0x77, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x77, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, + 0x2e, 0x77, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x30, 0x20, 0x3d, 0x20, 0x56, 0x65, 0x63, 0x31, 0x20, + 0x2a, 0x20, 0x66, 0x61, 0x63, 0x30, 0x20, 0x2d, 0x20, 0x56, 0x65, 0x63, 0x32, 0x20, 0x2a, 0x20, + 0x66, 0x61, 0x63, 0x31, 0x20, 0x2b, 0x20, 0x56, 0x65, 0x63, 0x33, 0x20, 0x2a, 0x20, 0x66, 0x61, + 0x63, 0x32, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, + 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x31, 0x20, 0x3d, 0x20, 0x56, 0x65, 0x63, 0x30, 0x20, 0x2a, + 0x20, 0x66, 0x61, 0x63, 0x30, 0x20, 0x2d, 0x20, 0x56, 0x65, 0x63, 0x32, 0x20, 0x2a, 0x20, 0x66, + 0x61, 0x63, 0x33, 0x20, 0x2b, 0x20, 0x56, 0x65, 0x63, 0x33, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, + 0x34, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, + 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x32, 0x20, 0x3d, 0x20, 0x56, 0x65, 0x63, 0x30, 0x20, 0x2a, 0x20, + 0x66, 0x61, 0x63, 0x31, 0x20, 0x2d, 0x20, 0x56, 0x65, 0x63, 0x31, 0x20, 0x2a, 0x20, 0x66, 0x61, + 0x63, 0x33, 0x20, 0x2b, 0x20, 0x56, 0x65, 0x63, 0x33, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x35, + 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, + 0x20, 0x69, 0x6e, 0x76, 0x33, 0x20, 0x3d, 0x20, 0x56, 0x65, 0x63, 0x30, 0x20, 0x2a, 0x20, 0x66, + 0x61, 0x63, 0x32, 0x20, 0x2d, 0x20, 0x56, 0x65, 0x63, 0x31, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, + 0x34, 0x20, 0x2b, 0x20, 0x56, 0x65, 0x63, 0x32, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x35, 0x3b, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x61, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, + 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x2b, 0x31, 0x2e, 0x30, + 0x66, 0x2c, 0x20, 0x2d, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2b, 0x31, 0x2e, 0x30, 0x66, 0x2c, + 0x20, 0x2d, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, + 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x73, 0x69, 0x67, 0x6e, + 0x5f, 0x62, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x34, 0x28, 0x2d, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2b, 0x31, 0x2e, 0x30, 0x66, + 0x2c, 0x20, 0x2d, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2b, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x69, 0x6e, 0x76, 0x5f, 0x32, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x76, 0x32, 0x20, 0x2a, 0x20, 0x73, + 0x69, 0x6e, 0x76, 0x5f, 0x30, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x76, 0x30, 0x20, 0x2a, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x61, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x33, 0x20, 0x3d, 0x20, 0x69, 0x6e, - 0x76, 0x33, 0x20, 0x2a, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x62, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x74, 0x30, - 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, - 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x69, 0x6e, 0x76, 0x5f, 0x30, 0x2e, 0x78, - 0x2c, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x31, 0x2e, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x32, - 0x2e, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x33, 0x2e, 0x78, 0x29, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x6f, 0x74, 0x30, 0x2e, 0x78, 0x20, - 0x2b, 0x20, 0x64, 0x6f, 0x74, 0x30, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x64, 0x6f, 0x74, 0x30, 0x2e, - 0x7a, 0x20, 0x2b, 0x20, 0x64, 0x6f, 0x74, 0x30, 0x2e, 0x77, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, - 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, - 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, - 0x5f, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x78, 0x32, 0x20, 0x6d, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, - 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, - 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x31, - 0x2e, 0x30, 0x66, 0x20, 0x2f, 0x20, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x5b, 0x30, 0x5d, 0x20, 0x2a, - 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x5b, 0x31, 0x5d, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x5b, - 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x5b, 0x31, 0x5d, 0x29, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, - 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x78, 0x32, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x5b, - 0x31, 0x5d, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, - 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x5b, 0x31, 0x5d, 0x20, 0x2a, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x31, 0x20, 0x3d, 0x20, 0x69, 0x6e, + 0x76, 0x31, 0x20, 0x2a, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x62, 0x3b, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x5f, + 0x32, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x76, 0x32, 0x20, 0x2a, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, + 0x61, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, + 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x33, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x76, 0x33, 0x20, 0x2a, + 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x62, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, + 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x74, 0x30, 0x20, 0x3d, 0x20, 0x6d, + 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x34, 0x28, 0x69, 0x6e, 0x76, 0x5f, 0x30, 0x2e, 0x78, 0x2c, 0x20, 0x69, 0x6e, + 0x76, 0x5f, 0x31, 0x2e, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x32, 0x2e, 0x78, 0x2c, 0x20, + 0x69, 0x6e, 0x76, 0x5f, 0x33, 0x2e, 0x78, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x6f, 0x74, 0x30, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x64, 0x6f, + 0x74, 0x30, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x64, 0x6f, 0x74, 0x30, 0x2e, 0x7a, 0x20, 0x2b, 0x20, + 0x64, 0x6f, 0x74, 0x30, 0x2e, 0x77, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, + 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x76, + 0x65, 0x72, 0x73, 0x65, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x32, 0x78, 0x32, 0x20, 0x6d, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, + 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x66, 0x20, + 0x2f, 0x20, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, + 0x5d, 0x5b, 0x31, 0x5d, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x5b, 0x30, 0x5d, 0x20, 0x2a, + 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x5b, 0x31, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x32, 0x78, 0x32, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x5b, 0x31, 0x5d, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, + 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x5b, 0x31, 0x5d, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x6d, - 0x5b, 0x30, 0x5d, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, - 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x29, 0x3b, 0x0a, - 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x63, 0x6f, 0x6e, - 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x78, 0x33, 0x20, 0x6d, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x2f, 0x2f, 0x20, 0x66, - 0x72, 0x6f, 0x6d, 0x20, 0x47, 0x4c, 0x4d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, - 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, - 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x31, 0x2e, - 0x30, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x20, 0x28, 0x6d, 0x5b, 0x30, 0x5d, - 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, - 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, - 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x6d, + 0x5b, 0x31, 0x5d, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, + 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x2d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x28, 0x6d, 0x5b, 0x30, 0x5d, - 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, - 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x29, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, - 0x20, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, - 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, - 0x5d, 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, - 0x78, 0x33, 0x28, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x6d, 0x5b, 0x31, - 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, - 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x5b, + 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, + 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, + 0x5f, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x78, 0x33, 0x20, 0x6d, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x2f, 0x2f, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, + 0x47, 0x4c, 0x4d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, + 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, + 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x66, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x20, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x20, 0x2a, + 0x20, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, + 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, + 0x5d, 0x2e, 0x7a, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x6d, 0x5b, + 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x20, 0x2a, + 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, + 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x2b, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x28, 0x6d, 0x5b, + 0x30, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, + 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x29, + 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x78, 0x33, 0x28, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, + 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, + 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x29, 0x20, 0x2a, 0x20, 0x6f, 0x6e, + 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, + 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x6d, 0x5b, 0x32, + 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, + 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x29, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x28, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, - 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, + 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, + 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x29, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, - 0x31, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, - 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x29, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, + 0x20, 0x20, 0x20, 0x20, 0x28, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, + 0x31, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, + 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x29, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, - 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, - 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x29, 0x20, 0x2a, 0x20, 0x6f, 0x6e, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x20, + 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, + 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x29, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, - 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x6d, 0x5b, 0x30, - 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, - 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x29, 0x20, + 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x6d, 0x5b, 0x31, + 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, + 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x29, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, - 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, - 0x2e, 0x7a, 0x29, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, + 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, + 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, + 0x2e, 0x79, 0x29, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, - 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, - 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x29, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, + 0x20, 0x20, 0x20, 0x20, 0x28, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, + 0x30, 0x5d, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, + 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x29, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, - 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, - 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x29, 0x20, 0x2a, 0x20, 0x6f, 0x6e, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x20, + 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, + 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x29, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, - 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x6d, 0x5b, 0x30, - 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x6d, - 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x29, 0x20, - 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, - 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, - 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x20, 0x6d, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x2f, 0x2f, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x47, 0x4c, 0x4d, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x63, 0x6f, 0x65, 0x66, 0x30, 0x30, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, - 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, - 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, - 0x32, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, - 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, - 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x33, 0x20, 0x3d, 0x20, 0x6d, - 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x20, 0x2d, - 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x34, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, - 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, - 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, + 0x6e, 0x74, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, + 0x65, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x34, 0x78, 0x34, 0x20, 0x6d, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x2f, 0x2f, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x47, 0x4c, 0x4d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, - 0x30, 0x36, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, - 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, - 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, - 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x37, 0x20, 0x3d, 0x20, - 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x20, - 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, + 0x30, 0x30, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, + 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, + 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, + 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x32, 0x20, 0x3d, 0x20, + 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, + 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x38, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, - 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, - 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, + 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x33, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, + 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, + 0x5d, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, - 0x66, 0x31, 0x30, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, - 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2a, - 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, - 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x31, 0x20, 0x3d, - 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, - 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, - 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x32, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, - 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, - 0x33, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, + 0x66, 0x30, 0x34, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, + 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2a, + 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, + 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x36, 0x20, 0x3d, + 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, + 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, + 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, + 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x37, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, + 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, + 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, - 0x65, 0x66, 0x31, 0x34, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, - 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x20, - 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, - 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x35, 0x20, - 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, - 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, - 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, - 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x36, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, - 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, - 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, + 0x65, 0x66, 0x30, 0x38, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, + 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, + 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x30, 0x20, + 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, + 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, + 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x31, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, + 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, + 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, - 0x6f, 0x65, 0x66, 0x31, 0x38, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, - 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, - 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, - 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x39, - 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, - 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, - 0x31, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x30, 0x20, 0x3d, 0x20, 0x6d, 0x5b, - 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2d, 0x20, - 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x3b, + 0x6f, 0x65, 0x66, 0x31, 0x32, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, + 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, + 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x34, + 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, + 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, + 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x35, 0x20, 0x3d, 0x20, 0x6d, 0x5b, + 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x20, 0x2d, 0x20, + 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x63, 0x6f, 0x65, 0x66, 0x32, 0x32, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, - 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, - 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, - 0x33, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, - 0x5d, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, - 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x63, 0x30, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, - 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, - 0x30, 0x30, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x30, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, - 0x30, 0x32, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x33, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x63, 0x31, - 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x34, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x34, - 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x36, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x37, - 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x66, 0x61, 0x63, 0x32, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, - 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x38, 0x2c, 0x20, - 0x63, 0x6f, 0x65, 0x66, 0x30, 0x38, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x30, 0x2c, 0x20, - 0x63, 0x6f, 0x65, 0x66, 0x31, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, - 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x63, 0x33, 0x20, 0x3d, 0x20, 0x6c, + 0x63, 0x6f, 0x65, 0x66, 0x31, 0x36, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, + 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, + 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, + 0x38, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, + 0x5d, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, + 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x39, 0x20, 0x3d, 0x20, 0x6d, + 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x7a, 0x20, 0x2d, + 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, + 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, + 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x30, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, + 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, + 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, + 0x32, 0x32, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, + 0x33, 0x5d, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x6d, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, + 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, + 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x33, 0x20, 0x3d, 0x20, + 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x79, 0x20, + 0x2d, 0x20, 0x6d, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, + 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, + 0x6f, 0x20, 0x66, 0x61, 0x63, 0x30, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x30, 0x2c, 0x20, + 0x63, 0x6f, 0x65, 0x66, 0x30, 0x30, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x32, 0x2c, 0x20, + 0x63, 0x6f, 0x65, 0x66, 0x30, 0x33, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, + 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x63, 0x31, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, - 0x65, 0x66, 0x31, 0x32, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x32, 0x2c, 0x20, 0x63, 0x6f, - 0x65, 0x66, 0x31, 0x34, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x35, 0x29, 0x3b, 0x0a, 0x20, + 0x65, 0x66, 0x30, 0x34, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x34, 0x2c, 0x20, 0x63, 0x6f, + 0x65, 0x66, 0x30, 0x36, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x37, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, - 0x63, 0x34, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x36, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, - 0x31, 0x36, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x38, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, - 0x31, 0x39, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, - 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x63, 0x35, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x30, - 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x30, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x32, - 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x33, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, - 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x56, 0x65, 0x63, 0x30, 0x20, 0x3d, + 0x63, 0x32, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, 0x30, 0x38, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, + 0x30, 0x38, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x30, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, + 0x31, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x63, 0x33, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x32, + 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x32, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x34, + 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x35, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x63, 0x34, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, - 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x2c, 0x20, - 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x29, 0x3b, + 0x63, 0x6f, 0x65, 0x66, 0x31, 0x36, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x36, 0x2c, 0x20, + 0x63, 0x6f, 0x65, 0x66, 0x31, 0x38, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x31, 0x39, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x56, 0x65, 0x63, 0x31, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, - 0x30, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, - 0x30, 0x5d, 0x2e, 0x79, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x56, 0x65, 0x63, 0x32, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, + 0x66, 0x61, 0x63, 0x35, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x30, 0x2c, 0x20, 0x63, 0x6f, + 0x65, 0x66, 0x32, 0x30, 0x2c, 0x20, 0x63, 0x6f, 0x65, 0x66, 0x32, 0x32, 0x2c, 0x20, 0x63, 0x6f, + 0x65, 0x66, 0x32, 0x33, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x56, 0x65, 0x63, 0x30, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6d, 0x5b, 0x31, 0x5d, - 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, - 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x56, 0x65, 0x63, 0x33, + 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, + 0x2e, 0x78, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x56, 0x65, 0x63, 0x31, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x34, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x77, - 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x77, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x77, + 0x34, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, + 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x79, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x30, 0x20, 0x3d, 0x20, 0x56, 0x65, 0x63, 0x31, 0x20, 0x2a, 0x20, - 0x66, 0x61, 0x63, 0x30, 0x20, 0x2d, 0x20, 0x56, 0x65, 0x63, 0x32, 0x20, 0x2a, 0x20, 0x66, 0x61, - 0x63, 0x31, 0x20, 0x2b, 0x20, 0x56, 0x65, 0x63, 0x33, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x32, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x69, 0x6e, 0x76, 0x31, 0x20, 0x3d, 0x20, 0x56, 0x65, 0x63, 0x30, 0x20, 0x2a, 0x20, 0x66, - 0x61, 0x63, 0x30, 0x20, 0x2d, 0x20, 0x56, 0x65, 0x63, 0x32, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, - 0x33, 0x20, 0x2b, 0x20, 0x56, 0x65, 0x63, 0x33, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x34, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x69, 0x6e, 0x76, 0x32, 0x20, 0x3d, 0x20, 0x56, 0x65, 0x63, 0x30, 0x20, 0x2a, 0x20, 0x66, 0x61, - 0x63, 0x31, 0x20, 0x2d, 0x20, 0x56, 0x65, 0x63, 0x31, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x33, - 0x20, 0x2b, 0x20, 0x56, 0x65, 0x63, 0x33, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x35, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, - 0x6e, 0x76, 0x33, 0x20, 0x3d, 0x20, 0x56, 0x65, 0x63, 0x30, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, - 0x32, 0x20, 0x2d, 0x20, 0x56, 0x65, 0x63, 0x31, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x34, 0x20, - 0x2b, 0x20, 0x56, 0x65, 0x63, 0x32, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x35, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x61, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, - 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x2b, 0x31, 0x2e, 0x30, 0x66, 0x2c, - 0x20, 0x2d, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2b, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2d, - 0x31, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, - 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x62, - 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x34, 0x28, 0x2d, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2b, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, - 0x2d, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2b, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0a, 0x20, + 0x6f, 0x20, 0x56, 0x65, 0x63, 0x32, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6d, 0x5b, 0x31, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, + 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x2c, 0x20, + 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x7a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, + 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x56, 0x65, 0x63, 0x33, 0x20, 0x3d, 0x20, 0x6c, + 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x6d, 0x5b, + 0x31, 0x5d, 0x2e, 0x77, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x77, 0x2c, 0x20, 0x6d, 0x5b, + 0x30, 0x5d, 0x2e, 0x77, 0x2c, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x2e, 0x77, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, - 0x76, 0x5f, 0x30, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x76, 0x30, 0x20, 0x2a, 0x20, 0x73, 0x69, 0x67, - 0x6e, 0x5f, 0x61, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, - 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x31, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x76, 0x31, - 0x20, 0x2a, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x62, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, - 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x32, 0x20, - 0x3d, 0x20, 0x69, 0x6e, 0x76, 0x32, 0x20, 0x2a, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x61, 0x3b, + 0x76, 0x30, 0x20, 0x3d, 0x20, 0x56, 0x65, 0x63, 0x31, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x30, + 0x20, 0x2d, 0x20, 0x56, 0x65, 0x63, 0x32, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x31, 0x20, 0x2b, + 0x20, 0x56, 0x65, 0x63, 0x33, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x32, 0x3b, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, + 0x31, 0x20, 0x3d, 0x20, 0x56, 0x65, 0x63, 0x30, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x30, 0x20, + 0x2d, 0x20, 0x56, 0x65, 0x63, 0x32, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x33, 0x20, 0x2b, 0x20, + 0x56, 0x65, 0x63, 0x33, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x34, 0x3b, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x32, + 0x20, 0x3d, 0x20, 0x56, 0x65, 0x63, 0x30, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x31, 0x20, 0x2d, + 0x20, 0x56, 0x65, 0x63, 0x31, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x33, 0x20, 0x2b, 0x20, 0x56, + 0x65, 0x63, 0x33, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x35, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x33, 0x20, + 0x3d, 0x20, 0x56, 0x65, 0x63, 0x30, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x32, 0x20, 0x2d, 0x20, + 0x56, 0x65, 0x63, 0x31, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x34, 0x20, 0x2b, 0x20, 0x56, 0x65, + 0x63, 0x32, 0x20, 0x2a, 0x20, 0x66, 0x61, 0x63, 0x35, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x73, 0x69, + 0x67, 0x6e, 0x5f, 0x61, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x2b, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2d, 0x31, 0x2e, + 0x30, 0x66, 0x2c, 0x20, 0x2b, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2d, 0x31, 0x2e, 0x30, 0x66, + 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x62, 0x20, 0x3d, 0x20, 0x6c, + 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x2d, 0x31, + 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2b, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x2d, 0x31, 0x2e, 0x30, + 0x66, 0x2c, 0x20, 0x2b, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x30, 0x20, + 0x3d, 0x20, 0x69, 0x6e, 0x76, 0x30, 0x20, 0x2a, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x61, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x69, 0x6e, 0x76, 0x5f, 0x33, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x76, 0x33, 0x20, 0x2a, 0x20, 0x73, + 0x69, 0x6e, 0x76, 0x5f, 0x31, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x76, 0x31, 0x20, 0x2a, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x62, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x74, 0x30, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x30, - 0x5d, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x34, 0x28, 0x69, 0x6e, 0x76, 0x5f, 0x30, 0x2e, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x76, 0x5f, - 0x31, 0x2e, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x32, 0x2e, 0x78, 0x2c, 0x20, 0x69, 0x6e, - 0x76, 0x5f, 0x33, 0x2e, 0x78, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, - 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x74, 0x31, 0x20, 0x3d, 0x20, 0x64, 0x6f, - 0x74, 0x30, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x64, 0x6f, 0x74, 0x30, 0x2e, 0x79, 0x20, 0x2b, 0x20, - 0x64, 0x6f, 0x74, 0x30, 0x2e, 0x7a, 0x20, 0x2b, 0x20, 0x64, 0x6f, 0x74, 0x30, 0x2e, 0x77, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, - 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x66, 0x20, 0x2f, 0x20, 0x64, 0x6f, - 0x74, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x28, - 0x69, 0x6e, 0x76, 0x5f, 0x30, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x32, 0x20, 0x3d, 0x20, 0x69, 0x6e, + 0x76, 0x32, 0x20, 0x2a, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x61, 0x3b, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x76, 0x5f, + 0x33, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x76, 0x33, 0x20, 0x2a, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x5f, + 0x62, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, + 0x6f, 0x20, 0x64, 0x6f, 0x74, 0x30, 0x20, 0x3d, 0x20, 0x6d, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x69, + 0x6e, 0x76, 0x5f, 0x30, 0x2e, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x31, 0x2e, 0x78, 0x2c, + 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x32, 0x2e, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x33, 0x2e, + 0x78, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, + 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x74, 0x31, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x74, 0x30, 0x2e, 0x78, + 0x20, 0x2b, 0x20, 0x64, 0x6f, 0x74, 0x30, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x64, 0x6f, 0x74, 0x30, + 0x2e, 0x7a, 0x20, 0x2b, 0x20, 0x64, 0x6f, 0x74, 0x30, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x5f, + 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, + 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x66, 0x20, 0x2f, 0x20, 0x64, 0x6f, 0x74, 0x31, 0x3b, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x28, 0x69, 0x6e, 0x76, 0x5f, + 0x30, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, + 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x31, 0x20, 0x2a, 0x20, 0x6f, 0x6e, + 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, + 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x69, 0x6e, 0x76, 0x5f, 0x32, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x31, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x33, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x76, 0x5f, 0x32, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, - 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, - 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, - 0x76, 0x5f, 0x33, 0x20, 0x2a, 0x20, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, - 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, - 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x28, - 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, - 0x76, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x33, 0x20, 0x6e, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x20, 0x2d, 0x20, - 0x32, 0x2e, 0x30, 0x66, 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, - 0x20, 0x6e, 0x29, 0x20, 0x2a, 0x20, 0x6e, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, - 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x74, 0x79, 0x70, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x44, 0x2c, - 0x20, 0x74, 0x79, 0x70, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x53, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x69, 0x74, 0x5f, 0x63, 0x61, 0x73, 0x74, 0x28, 0x53, 0x20, - 0x73, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, - 0x73, 0x69, 0x7a, 0x65, 0x6f, 0x66, 0x28, 0x44, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x73, 0x69, 0x7a, - 0x65, 0x6f, 0x66, 0x28, 0x53, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x5f, - 0x63, 0x61, 0x73, 0x74, 0x3c, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x44, 0x20, 0x26, 0x3e, 0x28, - 0x73, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x63, - 0x6c, 0x61, 0x73, 0x73, 0x20, 0x54, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, - 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, - 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, - 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x28, 0x29, + 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, + 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x63, 0x6f, 0x6e, 0x73, + 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, 0x2c, 0x20, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6e, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x20, 0x2d, 0x20, 0x32, 0x2e, 0x30, 0x66, + 0x20, 0x2a, 0x20, 0x6c, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x6e, 0x29, 0x20, + 0x2a, 0x20, 0x6e, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, + 0x3c, 0x74, 0x79, 0x70, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x44, 0x2c, 0x20, 0x74, 0x79, 0x70, + 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x53, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, + 0x5f, 0x62, 0x69, 0x74, 0x5f, 0x63, 0x61, 0x73, 0x74, 0x28, 0x53, 0x20, 0x73, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, + 0x61, 0x74, 0x69, 0x63, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x73, 0x69, 0x7a, 0x65, + 0x6f, 0x66, 0x28, 0x44, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x6f, 0x66, 0x28, + 0x53, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x72, 0x65, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x5f, 0x63, 0x61, 0x73, 0x74, + 0x3c, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x44, 0x20, 0x26, 0x3e, 0x28, 0x73, 0x29, 0x3b, 0x0a, + 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x63, 0x6c, 0x61, 0x73, 0x73, + 0x20, 0x54, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, + 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, + 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x54, 0x7b, 0x7d, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, + 0x74, 0x65, 0x3c, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x54, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, + 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, + 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, + 0x65, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x54, 0x3a, 0x3a, 0x6f, 0x6e, 0x65, + 0x28, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, + 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x3e, 0x28, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x28, 0x31, 0x29, + 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x0a, 0x5b, + 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, + 0x5f, 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x54, 0x7b, 0x7d, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, - 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x54, 0x3e, 0x0a, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x28, + 0x31, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, + 0x65, 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, + 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, + 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0a, + 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, + 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6f, + 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x31, 0x75, 0x29, 0x3b, + 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, + 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x3e, 0x28, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x31, 0x29, 0x3b, + 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, + 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x3e, 0x28, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x28, 0x31, + 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, - 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x54, 0x3a, - 0x3a, 0x6f, 0x6e, 0x65, 0x28, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, - 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x69, 0x6e, - 0x74, 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, - 0x74, 0x28, 0x31, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, - 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, - 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x28, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, - 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, - 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, - 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, - 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x3e, 0x28, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x28, 0x31, 0x2e, 0x30, - 0x66, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, - 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, - 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x3e, 0x28, + 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x28, - 0x31, 0x75, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, - 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x3e, - 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x31, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, - 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, - 0x6e, 0x67, 0x28, 0x31, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, - 0x65, 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, - 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, - 0x72, 0x74, 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, + 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, + 0x74, 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x31, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x62, + 0x79, 0x74, 0x65, 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, + 0x62, 0x79, 0x74, 0x65, 0x28, 0x31, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x75, - 0x73, 0x68, 0x6f, 0x72, 0x74, 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x28, 0x31, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, - 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, - 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, - 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x28, 0x31, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, - 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, - 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, - 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x28, 0x31, 0x29, 0x3b, 0x0a, 0x7d, - 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, - 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, - 0x65, 0x3c, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x74, 0x72, 0x75, 0x65, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, - 0x61, 0x74, 0x65, 0x3c, 0x74, 0x79, 0x70, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x54, 0x2c, 0x20, - 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x74, 0x20, 0x4e, 0x3e, 0x0a, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, - 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x7b, 0x0a, 0x0a, 0x70, 0x72, 0x69, 0x76, - 0x61, 0x74, 0x65, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x54, 0x20, 0x5f, 0x64, 0x61, 0x74, 0x61, - 0x5b, 0x4e, 0x5d, 0x3b, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x3a, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x74, 0x79, 0x70, 0x65, 0x6e, - 0x61, 0x6d, 0x65, 0x2e, 0x2e, 0x2e, 0x20, 0x45, 0x6c, 0x65, 0x6d, 0x3e, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x63, 0x6f, 0x6e, 0x73, - 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x28, 0x45, - 0x6c, 0x65, 0x6d, 0x2e, 0x2e, 0x2e, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x3a, 0x20, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x7b, 0x65, 0x6c, - 0x65, 0x6d, 0x2e, 0x2e, 0x2e, 0x7d, 0x20, 0x7b, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, - 0x70, 0x72, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x28, 0x6c, 0x63, 0x5f, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x26, 0x26, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x3d, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x63, 0x6f, 0x6e, 0x73, - 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x28, 0x63, - 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x26, 0x29, - 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x6c, 0x63, - 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x26, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, - 0x3d, 0x28, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x26, 0x26, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x6c, 0x63, 0x5f, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x26, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x3d, 0x28, - 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x26, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x65, 0x66, - 0x61, 0x75, 0x6c, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, + 0x62, 0x79, 0x74, 0x65, 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x28, 0x31, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, + 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, 0x6c, 0x63, + 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x3e, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, + 0x72, 0x75, 0x65, 0x3b, 0x0a, 0x7d, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, + 0x74, 0x79, 0x70, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x54, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, + 0x5f, 0x74, 0x20, 0x4e, 0x3e, 0x0a, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6c, 0x63, 0x5f, 0x61, + 0x72, 0x72, 0x61, 0x79, 0x20, 0x7b, 0x0a, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x3a, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x54, 0x20, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5b, 0x4e, 0x5d, 0x3b, + 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, + 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x74, 0x79, 0x70, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x2e, + 0x2e, 0x2e, 0x20, 0x45, 0x6c, 0x65, 0x6d, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, + 0x72, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x28, 0x45, 0x6c, 0x65, 0x6d, 0x2e, + 0x2e, 0x2e, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x3a, 0x20, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x7b, 0x65, 0x6c, 0x65, 0x6d, 0x2e, 0x2e, + 0x2e, 0x7d, 0x20, 0x7b, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x6c, + 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x28, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, + 0x20, 0x26, 0x26, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x3d, 0x20, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, + 0x72, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, + 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x26, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x3b, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, + 0x61, 0x79, 0x20, 0x26, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x3d, 0x28, 0x6c, 0x63, + 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x26, 0x26, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x3b, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, + 0x20, 0x26, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x3d, 0x28, 0x63, 0x6f, 0x6e, 0x73, + 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x26, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, + 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x54, + 0x20, 0x26, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5b, 0x5d, 0x28, 0x73, 0x69, 0x7a, + 0x65, 0x5f, 0x74, 0x20, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5b, 0x69, + 0x5d, 0x3b, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x54, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5b, 0x5d, 0x28, 0x73, + 0x69, 0x7a, 0x65, 0x5f, 0x74, 0x20, 0x69, 0x29, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5b, 0x69, 0x5d, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x54, 0x20, 0x26, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5b, 0x5d, - 0x28, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x74, 0x20, 0x69, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x64, 0x61, - 0x74, 0x61, 0x5b, 0x69, 0x5d, 0x3b, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x54, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, - 0x5b, 0x5d, 0x28, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x74, 0x20, 0x69, 0x29, 0x20, 0x63, 0x6f, 0x6e, - 0x73, 0x74, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5b, 0x69, 0x5d, 0x3b, 0x20, 0x7d, - 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5b, + 0x5f, 0x5f, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6f, + 0x6e, 0x65, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, + 0x3c, 0x54, 0x2c, 0x20, 0x4e, 0x3e, 0x20, 0x72, 0x65, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x23, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x20, 0x75, 0x6e, 0x72, 0x6f, + 0x6c, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, 0x75, 0x3b, 0x20, 0x69, 0x20, 0x3c, + 0x20, 0x4e, 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x5b, 0x69, + 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, 0x54, 0x3e, 0x28, 0x29, 0x3b, + 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x72, 0x65, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x7d, 0x3b, 0x0a, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x6d, + 0x70, 0x5f, 0x6d, 0x75, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x78, + 0x32, 0x20, 0x6c, 0x68, 0x73, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, + 0x78, 0x32, 0x20, 0x72, 0x68, 0x73, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x78, 0x32, 0x28, 0x6c, + 0x68, 0x73, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, 0x30, 0x5d, 0x2c, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x68, 0x73, 0x5b, + 0x31, 0x5d, 0x20, 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, 0x31, 0x5d, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, + 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, + 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x6d, + 0x70, 0x5f, 0x6d, 0x75, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x78, + 0x33, 0x20, 0x6c, 0x68, 0x73, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, + 0x78, 0x33, 0x20, 0x72, 0x68, 0x73, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, + 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, + 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x78, 0x33, 0x28, 0x6c, + 0x68, 0x73, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, 0x30, 0x5d, 0x2c, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x68, 0x73, 0x5b, + 0x31, 0x5d, 0x20, 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, 0x31, 0x5d, 0x2c, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x68, 0x73, 0x5b, 0x32, 0x5d, 0x20, + 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, 0x32, 0x5d, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x28, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x63, 0x5f, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x3c, 0x54, 0x2c, 0x20, 0x4e, 0x3e, 0x20, 0x72, 0x65, 0x74, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x20, - 0x75, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, - 0x6f, 0x72, 0x20, 0x28, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, 0x75, 0x3b, - 0x20, 0x69, 0x20, 0x3c, 0x20, 0x4e, 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x5b, 0x69, 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6f, 0x6e, 0x65, 0x3c, 0x54, - 0x3e, 0x28, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, - 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x74, - 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x5f, 0x6d, 0x75, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x32, 0x78, 0x32, 0x20, 0x6c, 0x68, 0x73, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x32, 0x78, 0x32, 0x20, 0x72, 0x68, 0x73, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, - 0x78, 0x32, 0x28, 0x6c, 0x68, 0x73, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, - 0x30, 0x5d, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6c, 0x68, 0x73, 0x5b, 0x31, 0x5d, 0x20, 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, 0x31, 0x5d, 0x29, - 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x74, - 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x5f, 0x6d, 0x75, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x33, 0x78, 0x33, 0x20, 0x6c, 0x68, 0x73, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x33, 0x78, 0x33, 0x20, 0x72, 0x68, 0x73, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, - 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, - 0x78, 0x33, 0x28, 0x6c, 0x68, 0x73, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, - 0x30, 0x5d, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, + 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x5f, 0x6d, + 0x75, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x20, 0x6c, + 0x68, 0x73, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x20, + 0x72, 0x68, 0x73, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, + 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x28, 0x6c, 0x68, 0x73, 0x5b, + 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, 0x30, 0x5d, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6c, 0x68, 0x73, 0x5b, 0x31, 0x5d, 0x20, 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, 0x31, 0x5d, 0x2c, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x68, 0x73, - 0x5b, 0x32, 0x5d, 0x20, 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, 0x32, 0x5d, 0x29, 0x3b, 0x0a, 0x7d, - 0x0a, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x74, 0x5f, 0x63, 0x6f, - 0x6d, 0x70, 0x5f, 0x6d, 0x75, 0x6c, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, - 0x78, 0x34, 0x20, 0x6c, 0x68, 0x73, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x34, 0x78, 0x34, 0x20, 0x72, 0x68, 0x73, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, - 0x63, 0x5f, 0x6d, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x28, - 0x6c, 0x68, 0x73, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, 0x30, 0x5d, 0x2c, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x68, 0x73, - 0x5b, 0x31, 0x5d, 0x20, 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, 0x31, 0x5d, 0x2c, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x68, 0x73, 0x5b, 0x31, 0x5d, 0x20, + 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, 0x31, 0x5d, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x68, 0x73, 0x5b, 0x32, 0x5d, - 0x20, 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, 0x32, 0x5d, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x68, 0x73, 0x5b, 0x32, 0x5d, 0x20, 0x2a, 0x20, 0x72, + 0x68, 0x73, 0x5b, 0x32, 0x5d, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x68, 0x73, 0x5b, 0x33, 0x5d, 0x20, 0x2a, 0x20, - 0x72, 0x68, 0x73, 0x5b, 0x33, 0x5d, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, - 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x3c, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, - 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x29, 0x20, 0x7c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, - 0x6e, 0x66, 0x28, 0x76, 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, - 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, - 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x3c, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x29, 0x20, 0x7c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, - 0x69, 0x6e, 0x66, 0x28, 0x76, 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, - 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, - 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x3c, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x29, 0x20, 0x7c, 0x20, 0x6c, 0x63, 0x5f, 0x69, - 0x73, 0x69, 0x6e, 0x66, 0x28, 0x76, 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, - 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, - 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, - 0x3c, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x29, 0x20, 0x7c, 0x20, 0x6c, 0x63, 0x5f, - 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x76, 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, - 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, - 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, - 0x66, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x3c, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, - 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x29, 0x20, 0x7c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, - 0x6e, 0x66, 0x28, 0x76, 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, - 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, - 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x3c, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, - 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x29, 0x20, 0x7c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, - 0x66, 0x28, 0x76, 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, - 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, - 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x3c, 0x6c, 0x63, 0x5f, - 0x68, 0x61, 0x6c, 0x66, 0x33, 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, + 0x20, 0x20, 0x20, 0x6c, 0x68, 0x73, 0x5b, 0x33, 0x5d, 0x20, 0x2a, 0x20, 0x72, 0x68, 0x73, 0x5b, + 0x33, 0x5d, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, + 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x76, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x28, + 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x3c, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, + 0x28, 0x76, 0x29, 0x20, 0x7c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x76, + 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, + 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x76, 0x29, 0x20, + 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x28, + 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x3c, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x32, 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, + 0x6e, 0x28, 0x76, 0x29, 0x20, 0x7c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, + 0x76, 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, + 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, + 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x76, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, + 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x3c, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x29, 0x20, 0x7c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x76, 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x76, 0x29, + 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, + 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x3c, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, + 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x29, 0x20, 0x7c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, + 0x66, 0x28, 0x76, 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, + 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x76, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x3c, 0x6c, 0x63, 0x5f, 0x68, - 0x61, 0x6c, 0x66, 0x34, 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, - 0x6e, 0x28, 0x76, 0x29, 0x20, 0x7c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, - 0x76, 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, - 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, - 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x78, 0x32, 0x20, - 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x30, 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, + 0x61, 0x6c, 0x66, 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, + 0x28, 0x76, 0x29, 0x20, 0x7c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x76, + 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, + 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x76, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x3c, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x32, 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, + 0x76, 0x29, 0x20, 0x7c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x76, 0x29, + 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, + 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, + 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, + 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, + 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x76, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x3c, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, + 0x33, 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x76, + 0x29, 0x20, 0x7c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x76, 0x29, 0x29, + 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, + 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, + 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, + 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x76, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x3c, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, + 0x3e, 0x28, 0x29, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x29, + 0x20, 0x7c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x73, 0x69, 0x6e, 0x66, 0x28, 0x76, 0x29, 0x29, 0x3b, + 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, + 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, + 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, + 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x78, 0x32, 0x20, 0x76, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x2e, + 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x30, 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x30, + 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x31, + 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, + 0x6e, 0x28, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x31, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, + 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, + 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x33, 0x78, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, + 0x30, 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, + 0x61, 0x6e, 0x28, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x30, 0x5d, 0x29, 0x3b, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x31, 0x5d, 0x20, 0x3d, 0x20, 0x6c, + 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x2e, 0x63, + 0x6f, 0x6c, 0x73, 0x5b, 0x31, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x2e, 0x63, + 0x6f, 0x6c, 0x73, 0x5b, 0x32, 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x32, 0x5d, + 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x3b, + 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, + 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, + 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, + 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x20, 0x76, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x2e, + 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x30, 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x30, + 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x31, + 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, + 0x6e, 0x28, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x31, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x32, 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x2e, 0x63, 0x6f, - 0x6c, 0x73, 0x5b, 0x30, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x2e, 0x63, 0x6f, - 0x6c, 0x73, 0x5b, 0x31, 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x31, 0x5d, 0x29, + 0x6c, 0x73, 0x5b, 0x32, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x2e, 0x63, 0x6f, + 0x6c, 0x73, 0x5b, 0x33, 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x33, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x3b, 0x0a, - 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5d, 0x5d, 0x20, - 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x61, 0x75, 0x74, 0x6f, - 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x6c, - 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x78, 0x33, 0x20, 0x76, 0x29, 0x20, 0x6e, 0x6f, - 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x2e, 0x63, - 0x6f, 0x6c, 0x73, 0x5b, 0x30, 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x30, 0x5d, - 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x31, 0x5d, - 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, - 0x28, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x31, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x32, 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, - 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x2e, 0x63, 0x6f, 0x6c, - 0x73, 0x5b, 0x32, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x76, 0x3b, 0x0a, 0x7d, 0x0a, 0x5b, 0x5b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x63, 0x61, - 0x72, 0x64, 0x5d, 0x5d, 0x20, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, 0x72, - 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, - 0x6e, 0x61, 0x6e, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x20, - 0x76, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x30, 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, - 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x2e, 0x63, 0x6f, - 0x6c, 0x73, 0x5b, 0x30, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x2e, 0x63, 0x6f, - 0x6c, 0x73, 0x5b, 0x31, 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x31, 0x5d, 0x29, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x32, 0x5d, 0x20, - 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, - 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x32, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, 0x5b, 0x33, 0x5d, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x72, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x76, 0x2e, 0x63, 0x6f, 0x6c, 0x73, - 0x5b, 0x33, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x76, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, - 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, - 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x3d, - 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, - 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x32, 0x78, 0x32, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x32, 0x78, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x2a, - 0x64, 0x73, 0x74, 0x20, 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, - 0x6e, 0x61, 0x6e, 0x28, 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, - 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, - 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, - 0x78, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x33, 0x78, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x7d, 0x0a, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, + 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, - 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, - 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, - 0x78, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x78, 0x32, + 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, + 0x78, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, - 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x2a, 0x64, 0x73, - 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x67, 0x72, 0x61, - 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, - 0x73, 0x74, 0x20, 0x3d, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, - 0x20, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, - 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x2a, - 0x64, 0x73, 0x74, 0x20, 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, - 0x6e, 0x61, 0x6e, 0x28, 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, - 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, - 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, - 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, + 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x78, 0x33, 0x20, 0x2a, + 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x78, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, - 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x2a, - 0x64, 0x73, 0x74, 0x20, 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, - 0x6e, 0x61, 0x6e, 0x28, 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, - 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, - 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, - 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x67, - 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, - 0x2a, 0x64, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x2b, 0x20, 0x6c, 0x63, - 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x67, 0x72, 0x61, 0x64, - 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, - 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, - 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x2a, - 0x64, 0x73, 0x74, 0x20, 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, - 0x6e, 0x61, 0x6e, 0x28, 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, - 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, - 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, - 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x67, + 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x20, 0x2a, 0x64, 0x73, + 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, - 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, - 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, - 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x2a, 0x64, 0x73, - 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x67, 0x72, 0x61, - 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x3d, + 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, - 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, - 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x67, 0x72, 0x61, + 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, + 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, + 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, + 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, + 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x2a, 0x64, 0x73, + 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x67, 0x72, 0x61, + 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, + 0x73, 0x74, 0x20, 0x3d, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, + 0x20, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, + 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, + 0x68, 0x61, 0x6c, 0x66, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, + 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, + 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, + 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, + 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x2a, 0x64, 0x73, 0x74, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, 0x73, 0x74, + 0x20, 0x3d, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, + 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, + 0x6c, 0x66, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, + 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, + 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, + 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, + 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x2a, 0x64, 0x73, 0x74, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x20, 0x2a, 0x64, 0x73, 0x74, + 0x20, 0x3d, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x20, 0x2b, 0x20, 0x6c, 0x63, 0x5f, 0x72, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x28, 0x67, 0x72, 0x61, 0x64, 0x29, 0x3b, 0x20, 0x7d, + 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, + 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, + 0x72, 0x74, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, + 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, + 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, + 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, + 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x2a, 0x64, 0x73, 0x74, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, + 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, + 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x2a, 0x64, 0x73, + 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, + 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, + 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x2a, + 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, - 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, - 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x67, - 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, - 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, - 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, - 0x6e, 0x67, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, + 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, + 0x67, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, - 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, - 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, + 0x6f, 0x6c, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, + 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, + 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x62, 0x79, 0x74, 0x65, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, - 0x28, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, - 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, - 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, - 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, + 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, - 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x20, 0x2a, 0x64, - 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x20, 0x67, 0x72, 0x61, + 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x32, 0x20, 0x2a, 0x64, + 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, - 0x32, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x32, + 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, - 0x62, 0x79, 0x74, 0x65, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x62, - 0x79, 0x74, 0x65, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, - 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, - 0x28, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x34, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, - 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, - 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x32, 0x20, 0x2a, - 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x32, 0x20, 0x67, - 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, - 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, - 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x62, - 0x79, 0x74, 0x65, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x62, - 0x79, 0x74, 0x65, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x62, 0x79, 0x74, 0x65, 0x34, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x62, + 0x79, 0x74, 0x65, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, - 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x34, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, + 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x32, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, - 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, - 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, + 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x33, + 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, - 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, - 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x75, 0x62, 0x79, 0x74, 0x65, 0x34, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x75, 0x62, 0x79, 0x74, 0x65, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, - 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x2a, 0x64, 0x73, - 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x67, 0x72, 0x61, - 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, - 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, - 0x72, 0x74, 0x32, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, - 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, - 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, - 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x67, 0x72, 0x61, + 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x2a, 0x64, 0x73, + 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, - 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, - 0x72, 0x74, 0x34, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, + 0x74, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, + 0x74, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, + 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, + 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, + 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, + 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x20, + 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, + 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, + 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, + 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, + 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, + 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x20, + 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, + 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, + 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, + 0x69, 0x6e, 0x74, 0x32, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, + 0x74, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, + 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, + 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, + 0x69, 0x6e, 0x74, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, - 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, + 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, - 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, - 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, - 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, - 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x2a, 0x64, 0x73, - 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, + 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x2a, 0x64, 0x73, 0x74, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, - 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, - 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x20, 0x67, + 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, + 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x69, - 0x6e, 0x74, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, - 0x74, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, + 0x6e, 0x74, 0x34, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, + 0x74, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, - 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, + 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, + 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, - 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x2a, 0x64, 0x73, 0x74, - 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, + 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, + 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, - 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, - 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x67, - 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, - 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, - 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, - 0x6e, 0x67, 0x34, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, - 0x67, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, - 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, - 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, - 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, - 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, - 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, - 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x2a, - 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x67, + 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, + 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, - 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, - 0x6f, 0x6e, 0x67, 0x34, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, + 0x6f, 0x6e, 0x67, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, + 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, + 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, + 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, + 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, + 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, + 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, + 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, + 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, + 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, + 0x62, 0x6f, 0x6f, 0x6c, 0x32, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x62, + 0x6f, 0x6f, 0x6c, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, - 0x28, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x32, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, - 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x32, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, + 0x28, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, + 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, - 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, 0x20, 0x2a, 0x64, - 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x33, 0x20, 0x67, 0x72, 0x61, - 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, - 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, - 0x34, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x34, - 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, - 0x7b, 0x7d, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x65, - 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x74, 0x7b, 0x7d, 0x3b, 0x20, 0x63, 0x6f, 0x6e, 0x73, - 0x74, 0x65, 0x78, 0x70, 0x72, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x61, - 0x74, 0x61, 0x5f, 0x74, 0x20, 0x5f, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x61, - 0x74, 0x61, 0x7b, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x63, - 0x6c, 0x61, 0x73, 0x73, 0x20, 0x54, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x7b, 0x75, 0x73, 0x69, - 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x3b, 0x7d, + 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x34, 0x20, 0x2a, 0x64, + 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x34, 0x20, 0x67, 0x72, 0x61, + 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x7d, 0x0a, 0x73, + 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x61, + 0x74, 0x61, 0x5f, 0x74, 0x7b, 0x7d, 0x3b, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x78, 0x70, + 0x72, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x74, + 0x20, 0x5f, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x7b, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x63, 0x6c, 0x61, 0x73, 0x73, - 0x20, 0x54, 0x3e, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x74, 0x79, 0x70, 0x65, 0x6e, 0x61, 0x6d, - 0x65, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, - 0x54, 0x3e, 0x3a, 0x3a, 0x74, 0x79, 0x70, 0x65, 0x3b, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, - 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, - 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x20, 0x7d, - 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, - 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x3e, 0x20, 0x7b, 0x20, 0x75, - 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, - 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x34, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, - 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, - 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, - 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, - 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, - 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, - 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x3e, 0x20, 0x7b, - 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, - 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, - 0x66, 0x34, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, - 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, - 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, - 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, - 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, - 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, - 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x3e, - 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, - 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, - 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, - 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, - 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x3b, - 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x3e, 0x20, - 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, - 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, - 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, - 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, - 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, - 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, + 0x20, 0x54, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x7b, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, + 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x3b, 0x7d, 0x3b, 0x0a, 0x74, 0x65, + 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x54, 0x3e, 0x20, + 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x20, 0x3d, 0x20, 0x74, 0x79, 0x70, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x65, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x54, 0x3e, 0x3a, 0x3a, + 0x74, 0x79, 0x70, 0x65, 0x3b, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, + 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, - 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, - 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, - 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, - 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x3b, - 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x33, 0x3e, 0x20, 0x7b, 0x20, - 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, - 0x62, 0x79, 0x74, 0x65, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, - 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, - 0x34, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, - 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, + 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, - 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, - 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, + 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, + 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x33, 0x3e, 0x20, + 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, + 0x63, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, - 0x62, 0x79, 0x74, 0x65, 0x34, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, - 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x3b, 0x20, - 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, - 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, - 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, - 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, - 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x3e, 0x20, 0x7b, - 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, - 0x5f, 0x69, 0x6e, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, - 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, - 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, - 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, - 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, - 0x69, 0x6e, 0x74, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, - 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x3b, 0x20, 0x7d, 0x3b, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x68, + 0x61, 0x6c, 0x66, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, + 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, - 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, - 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, - 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, + 0x3c, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x33, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, + 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, + 0x66, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x3e, 0x20, + 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, - 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, + 0x63, 0x5f, 0x68, 0x61, 0x6c, 0x66, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, + 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x3b, 0x20, 0x7d, + 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x33, 0x3e, 0x20, 0x7b, 0x20, 0x75, + 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, + 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, + 0x74, 0x34, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, + 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, + 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, + 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, + 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, + 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, + 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, + 0x72, 0x74, 0x33, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, + 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x3b, 0x20, 0x7d, + 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x34, 0x3e, 0x20, 0x7b, 0x20, + 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, + 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, - 0x6e, 0x67, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, - 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, + 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x62, 0x79, + 0x74, 0x65, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, + 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, - 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, - 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, + 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x33, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, + 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x3e, 0x20, 0x7b, + 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x34, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, - 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, + 0x5f, 0x62, 0x79, 0x74, 0x65, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, - 0x6e, 0x67, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, - 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x3b, 0x20, 0x7d, 0x3b, + 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, + 0x74, 0x65, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, + 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, - 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, - 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, - 0x6f, 0x6e, 0x67, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, + 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x33, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, + 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x62, + 0x79, 0x74, 0x65, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, + 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x34, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, - 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, - 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x74, 0x79, 0x70, 0x65, 0x6e, 0x61, 0x6d, - 0x65, 0x20, 0x54, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x74, 0x20, 0x4e, 0x3e, 0x0a, 0x5f, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, - 0x61, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, - 0x79, 0x3c, 0x54, 0x2c, 0x20, 0x4e, 0x3e, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, - 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x3c, 0x54, 0x2c, 0x20, 0x4e, 0x3e, 0x20, 0x67, 0x72, 0x61, - 0x64, 0x29, 0x20, 0x6e, 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x23, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x20, 0x75, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, - 0x20, 0x3d, 0x20, 0x30, 0x75, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x4e, 0x3b, 0x20, 0x69, 0x2b, - 0x2b, 0x29, 0x20, 0x7b, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, - 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x64, 0x28, 0x26, 0x28, 0x2a, 0x64, 0x73, 0x74, 0x29, 0x5b, - 0x69, 0x5d, 0x2c, 0x20, 0x67, 0x72, 0x61, 0x64, 0x5b, 0x69, 0x5d, 0x29, 0x3b, 0x20, 0x7d, 0x0a, - 0x7d, 0x0a + 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x62, 0x79, 0x74, 0x65, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, + 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, + 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, + 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x32, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, + 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x3b, 0x20, 0x7d, + 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, + 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, + 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, + 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x3e, 0x20, 0x7b, 0x20, + 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, + 0x69, 0x6e, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, + 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x32, + 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, + 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, + 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, + 0x75, 0x69, 0x6e, 0x74, 0x33, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, + 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x3b, 0x20, 0x7d, + 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x34, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, + 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x69, + 0x6e, 0x74, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, + 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x3e, + 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, + 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, + 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x6c, + 0x6f, 0x6e, 0x67, 0x33, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, + 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x3b, 0x20, 0x7d, 0x3b, + 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, + 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, + 0x3c, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, + 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x6c, 0x6f, 0x6e, + 0x67, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, + 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x32, 0x3e, + 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, + 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, + 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, + 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x33, 0x3e, 0x20, 0x7b, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, + 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x3b, + 0x20, 0x7d, 0x3b, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x3e, 0x20, 0x73, + 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x5f, 0x3c, 0x6c, 0x63, 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x34, 0x3e, 0x20, 0x7b, + 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x63, + 0x5f, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, + 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x74, 0x79, 0x70, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x54, 0x2c, + 0x20, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x74, 0x20, 0x4e, 0x3e, 0x0a, 0x5f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x5f, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x69, + 0x64, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, + 0x67, 0x72, 0x61, 0x64, 0x28, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x3c, 0x54, 0x2c, + 0x20, 0x4e, 0x3e, 0x20, 0x2a, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x72, 0x72, + 0x61, 0x79, 0x3c, 0x54, 0x2c, 0x20, 0x4e, 0x3e, 0x20, 0x67, 0x72, 0x61, 0x64, 0x29, 0x20, 0x6e, + 0x6f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x23, 0x70, + 0x72, 0x61, 0x67, 0x6d, 0x61, 0x20, 0x75, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, + 0x75, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x4e, 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, + 0x20, 0x6c, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x67, + 0x72, 0x61, 0x64, 0x28, 0x26, 0x28, 0x2a, 0x64, 0x73, 0x74, 0x29, 0x5b, 0x69, 0x5d, 0x2c, 0x20, + 0x67, 0x72, 0x61, 0x64, 0x5b, 0x69, 0x5d, 0x29, 0x3b, 0x20, 0x7d, 0x0a, 0x7d, 0x0a }; extern "C" const char luisa_cuda_builtin_cuda_device_resource[118104] = { diff --git a/src/backends/cuda/cuda_builtin_embedded.h b/src/backends/cuda/cuda_builtin_embedded.h index 7ce3c3c0d..d2564a3b5 100644 --- a/src/backends/cuda/cuda_builtin_embedded.h +++ b/src/backends/cuda/cuda_builtin_embedded.h @@ -2,5 +2,5 @@ extern "C" const char luisa_cuda_builtin_cuda_builtin_kernels[6094]; extern "C" const char luisa_cuda_builtin_cuda_device_half[84397]; -extern "C" const char luisa_cuda_builtin_cuda_device_math[499474]; +extern "C" const char luisa_cuda_builtin_cuda_device_math[499454]; extern "C" const char luisa_cuda_builtin_cuda_device_resource[118104]; diff --git a/src/backends/cuda/generate_device_library.py b/src/backends/cuda/generate_device_library.py index c358ec81d..33f259b49 100644 --- a/src/backends/cuda/generate_device_library.py +++ b/src/backends/cuda/generate_device_library.py @@ -1,976 +1,976 @@ -from os.path import realpath, dirname -from sys import argv - -HALF_IMPL = ''' -struct lc_half { -private: - union U { __fp16 h; lc_ushort bits; }; -public: - lc_ushort bits; - inline constexpr lc_half() noexcept : bits{0} {} - [[nodiscard]] static inline constexpr auto from_bits(lc_ushort bits) noexcept { - lc_half h; - h.bits = bits; - return h; - } - inline constexpr lc_half(float x) noexcept { - U u; - u.h = x; - bits = u.bits; - } - template - inline constexpr operator T() const noexcept { - U u; - u.bits = bits; - return static_cast(static_cast(u.h)); - } - inline constexpr auto operator-() const noexcept { return from_bits(bits ^ 0x8000u); } - inline constexpr auto operator+() const noexcept { return *this; } - inline constexpr auto operator!() const noexcept { return bits == 0u || bits == 0x8000u; } -#define IMPL_HALF_BINOP(op) \ - inline constexpr auto operator op(lc_half rhs) const noexcept { \ - U u_lhs; u_lhs.bits = bits; \ - U u_rhs; u_rhs.bits = rhs.bits; \ - return lc_half{lc_float(u_lhs.h op u_rhs.h)}; \ - } - IMPL_HALF_BINOP(+) - IMPL_HALF_BINOP(-) - IMPL_HALF_BINOP(*) - IMPL_HALF_BINOP(/) -#undef IMPL_HALF_BINOP -#define IMPL_HALF_CMP(op) inline constexpr auto operator op(lc_half rhs) const noexcept { return float(*this) op float(rhs); } - IMPL_HALF_CMP(==) - IMPL_HALF_CMP(!=) - IMPL_HALF_CMP(<) - IMPL_HALF_CMP(<=) - IMPL_HALF_CMP(>) - IMPL_HALF_CMP(>=) - -}; -static_assert(sizeof(lc_half) == 2); -[[nodiscard]] inline lc_short __half_as_short(lc_half x) noexcept { - return x.bits; -} -[[nodiscard]] inline lc_half __short_as_half(lc_short x) noexcept { - return lc_half::from_bits(x); -} -[[nodiscard]] inline lc_half __hmax(lc_half x, lc_half y) noexcept { return lc_half{lc_float(x) > lc_float(y) ? x : y}; } -[[nodiscard]] inline lc_half __hmin(lc_half x, lc_half y) noexcept { return lc_half{lc_float(x) < lc_float(y) ? x : y}; } -[[nodiscard]] inline lc_half __habs(lc_half x) noexcept { return lc_half{lc_float(x) < 0.0f ? -x : x}; } -[[nodiscard]] inline lc_half hexp2(lc_half x) noexcept { return lc_half{exp2f(lc_float(x))}; } -[[nodiscard]] inline lc_half hceil(lc_half x) noexcept { return lc_half{ceilf(lc_float(x))}; } -[[nodiscard]] inline lc_half hfloor(lc_half x) noexcept { return lc_half{floorf(lc_float(x))}; } -[[nodiscard]] inline lc_half htrunc(lc_half x) noexcept { return lc_half{truncf(lc_float(x))}; } -[[nodiscard]] inline lc_half hround(lc_half x) noexcept { return lc_half{roundf(lc_float(x))}; } -[[nodiscard]] inline lc_half hsqrt(lc_half x) noexcept { return lc_half{sqrtf(lc_float(x))}; } -[[nodiscard]] inline lc_half hrsqrt(lc_half x) noexcept { return lc_half{rsqrtf(lc_float(x))}; } -[[nodiscard]] inline lc_half __hfma(lc_half x, lc_half y, lc_half z) noexcept { return lc_half{fmaf(lc_float(x), lc_float(y), lc_float(z))}; } -[[nodiscard]] inline bool __hisnan(lc_half x) noexcept { return isnan_impl(lc_float(x)); } -[[nodiscard]] inline bool __hisinf(lc_half x) noexcept { return isinf_impl(lc_float(x)); } -''' - -if __name__ == "__main__": - if len(argv) < 2: - print("usage: python generate_device_library.py ") - exit(1) - output_file_name = argv[1] - is_cpu = 'cpu' in output_file_name - with open(f"{output_file_name}", "w") as file: - # scalar types - scalar_types = ["byte", "ubyte", "short", "ushort", "int", - "uint", "half", "float", "bool", "long", "ulong"] - native_types = ["char", "unsigned char", "short", "unsigned short", "int", "unsigned int", - "half", "float", "bool", "long long", "unsigned long long"] - scalar_alignments = { - "byte": 1, - "ubyte": 1, - "short": 2, - "ushort": 2, - "int": 4, - "uint": 4, - "half": 2, - "float": 4, - "bool": 1, - "long": 8, - "ulong": 8, - } - for t, native_t in zip(scalar_types, native_types): - if t == 'half' and is_cpu: - continue - print(f"using lc_{t} = {native_t};", file=file) - print(file=file) - print('''[[nodiscard]] __device__ inline bool isinf_impl(lc_float x) noexcept { - auto u = __float_as_int(x); - return u == 0x7f800000u | u == 0xff800000u; -} -[[nodiscard]] __device__ inline bool isnan_impl(lc_float x) noexcept { - auto u = __float_as_int(x); - return ((u & 0x7F800000u) == 0x7F800000u) & ((u & 0x7FFFFFu) != 0u); -} -[[nodiscard]] __device__ inline lc_float powi_impl(lc_float x, lc_int y) noexcept { - lc_float r = 1.0f; - auto is_y_neg = y < 0; - auto y_abs = is_y_neg ? -y : y; - - while (y_abs) { - if (y_abs & 1) r *= x; - x *= x; - y_abs >>= 1; - } - return is_y_neg ? 1.0f / r : r; -} -[[nodiscard]] __device__ inline lc_float powf_impl(lc_float x, lc_float y) noexcept { - auto y_int = static_cast(y); - return y_int == y ? powi_impl(x, y_int) : powf(x, y); -} -''', file=file) - if is_cpu: - print(HALF_IMPL, file=file) - # vector types - for type in scalar_types: - for i in range(2, 5): - align = min(16, scalar_alignments[type] * (i if i != 3 else 4)) - elements = ["x", "y", "z", "w"][:i] - print( - f"""struct alignas({align}) lc_{type}{i} {{ - lc_{type} {', '.join(elements[:i + 1])}; - __device__ inline constexpr lc_{type}{i}() noexcept - : {', '.join(f"{m}{{}}" for m in elements)} {{}} - __device__ inline constexpr static auto zero() noexcept {{ return lc_{type}{i}{{}}; }} - __device__ inline constexpr static auto one() noexcept {{ return lc_{type}{i}{{{', '.join('1' for _ in elements)}}}; }} - __device__ inline explicit constexpr lc_{type}{i}(lc_{type} s) noexcept - : {', '.join(f"{m}{{s}}" for m in elements)} {{}} - __device__ inline constexpr lc_{type}{i}({', '.join(f"lc_{type} {m}" for m in elements)}) noexcept - : {', '.join(f"{m}{{{m}}}" for m in elements)} {{}} - __device__ inline constexpr auto &operator[](lc_uint i) noexcept {{ return (&x)[i]; }} - __device__ inline constexpr auto operator[](lc_uint i) const noexcept {{ return (&x)[i]; }} -}}; -""", file=file) - - # make type[n] - for type in scalar_types: - # make type2 - print( - f"""[[nodiscard]] __device__ inline constexpr auto lc_make_{type}2(lc_{type} s = 0) noexcept {{ return lc_{type}2{{s, s}}; }} -[[nodiscard]] __device__ inline constexpr auto lc_make_{type}2(lc_{type} x, lc_{type} y) noexcept {{ return lc_{type}2{{x, y}}; }}""", - file=file) - for t in scalar_types: - for l in range(2, 5): - print( - f"[[nodiscard]] __device__ inline constexpr auto lc_make_{type}2(lc_{t}{l} v) noexcept {{ return lc_{type}2{{static_cast(v.x), static_cast(v.y)}}; }}", - file=file) - # make type3 - print( - f"""[[nodiscard]] inline __device__ constexpr auto lc_make_{type}3(lc_{type} s = 0) noexcept {{ return lc_{type}3{{s, s, s}}; }} -[[nodiscard]] __device__ inline constexpr auto lc_make_{type}3(lc_{type} x, lc_{type} y, lc_{type} z) noexcept {{ return lc_{type}3{{x, y, z}}; }} -[[nodiscard]] __device__ inline constexpr auto lc_make_{type}3(lc_{type} x, lc_{type}2 yz) noexcept {{ return lc_{type}3{{x, yz.x, yz.y}}; }} -[[nodiscard]] __device__ inline constexpr auto lc_make_{type}3(lc_{type}2 xy, lc_{type} z) noexcept {{ return lc_{type}3{{xy.x, xy.y, z}}; }}""", - file=file) - for t in scalar_types: - for l in range(3, 5): - print( - f"[[nodiscard]] __device__ constexpr auto lc_make_{type}3(lc_{t}{l} v) noexcept {{ return lc_{type}3{{static_cast(v.x), static_cast(v.y), static_cast(v.z)}}; }}", - file=file) - # make type4 - print( - f"""[[nodiscard]] inline __device__ constexpr auto lc_make_{type}4(lc_{type} s = 0) noexcept {{ return lc_{type}4{{s, s, s, s}}; }} -[[nodiscard]] __device__ inline constexpr auto lc_make_{type}4(lc_{type} x, lc_{type} y, lc_{type} z, lc_{type} w) noexcept {{ return lc_{type}4{{x, y, z, w}}; }} -[[nodiscard]] __device__ inline constexpr auto lc_make_{type}4(lc_{type} x, lc_{type} y, lc_{type}2 zw) noexcept {{ return lc_{type}4{{x, y, zw.x, zw.y}}; }} -[[nodiscard]] __device__ inline constexpr auto lc_make_{type}4(lc_{type} x, lc_{type}2 yz, lc_{type} w) noexcept {{ return lc_{type}4{{x, yz.x, yz.y, w}}; }} -[[nodiscard]] __device__ inline constexpr auto lc_make_{type}4(lc_{type}2 xy, lc_{type} z, lc_{type} w) noexcept {{ return lc_{type}4{{xy.x, xy.y, z, w}}; }} -[[nodiscard]] __device__ inline constexpr auto lc_make_{type}4(lc_{type}2 xy, lc_{type}2 zw) noexcept {{ return lc_{type}4{{xy.x, xy.y, zw.x, zw.y}}; }} -[[nodiscard]] __device__ inline constexpr auto lc_make_{type}4(lc_{type} x, lc_{type}3 yzw) noexcept {{ return lc_{type}4{{x, yzw.x, yzw.y, yzw.z}}; }} -[[nodiscard]] __device__ inline constexpr auto lc_make_{type}4(lc_{type}3 xyz, lc_{type} w) noexcept {{ return lc_{type}4{{xyz.x, xyz.y, xyz.z, w}}; }}""", - file=file) - for t in scalar_types: - print( - f"[[nodiscard]] inline __device__ constexpr auto lc_make_{type}4(lc_{t}4 v) noexcept {{ return lc_{type}4{{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}}; }}", - file=file) - print(file=file) - - # unary operators - for type in scalar_types: - for i in range(2, 5): - elements = ["x", "y", "z", "w"][:i] - print( - f"[[nodiscard]] inline __device__ constexpr auto operator!(lc_{type}{i} v) noexcept {{ return lc_make_bool{i}({', '.join(f'!v.{m}' for m in elements)}); }}", - file=file) - if type != "bool": - print( - f"[[nodiscard]] inline __device__ constexpr auto operator+(lc_{type}{i} v) noexcept {{ return lc_make_{type}{i}({', '.join(f'+v.{m}' for m in elements)}); }}", - file=file) - print( - f"[[nodiscard]] inline __device__ constexpr auto operator-(lc_{type}{i} v) noexcept {{ return lc_make_{type}{i}({', '.join(f'-v.{m}' for m in elements)}); }}", - file=file) - if type != "float" and type != "half": - print( - f"[[nodiscard]] inline __device__ constexpr auto operator~(lc_{type}{i} v) noexcept {{ return lc_make_{type}{i}({', '.join(f'~v.{m}' for m in elements)}); }}", - file=file) - print(file=file) - - - def gen_binary_op(arg_t, ret_t, op): - for i in range(2, 5): - elements = ["x", "y", "z", "w"][:i] - # vector-vector - print( - f"[[nodiscard]] inline __device__ constexpr auto operator{op}(lc_{arg_t}{i} lhs, lc_{arg_t}{i} rhs) noexcept {{ return lc_make_{ret_t}{i}({', '.join(f'lhs.{m} {op} rhs.{m}' for m in elements)}); }}", - file=file) - # vector-scalar - operation = ", ".join(f"lhs.{e} {op} rhs" for e in "xyzw"[:i]) - print( - f"[[nodiscard]] inline __device__ constexpr auto operator{op}(lc_{arg_t}{i} lhs, lc_{arg_t} rhs) noexcept {{ return lc_make_{ret_t}{i}({operation}); }}", - file=file) - # scalar-vector - operation = ", ".join(f"lhs {op} rhs.{e}" for e in "xyzw"[:i]) - print( - f"[[nodiscard]] inline __device__ constexpr auto operator{op}(lc_{arg_t} lhs, lc_{arg_t}{i} rhs) noexcept {{ return lc_make_{ret_t}{i}({operation}); }}", - file=file) - - - # binary operators - for op in ["==", "!="]: - for type in scalar_types: - gen_binary_op(type, "bool", op) - print(file=file) - for op in ["<", ">", "<=", ">="]: - for type in ["short", "ushort", "int", "uint", "half", "float", "long", "ulong"]: - gen_binary_op(type, "bool", op) - print(file=file) - for op in ["+", "-", "*", "/"]: - for type in ["short", "ushort", "int", "uint", "half", "float", "long", "ulong"]: - gen_binary_op(type, type, op) - print(file=file) - for op in ["%", "<<", ">>"]: - for type in ["short", "ushort", "int", "uint", "long", "ulong"]: - gen_binary_op(type, type, op) - print(file=file) - for op in ["|", "&", "^"]: - for type in ["short", "ushort", "int", "uint", "bool", "long", "ulong"]: - gen_binary_op(type, type, op) - print(file=file) - for op in ["||", "&&"]: - gen_binary_op("bool", "bool", op) - print(file=file) - - # any, all, none - for f, uop, bop in [("any", "", "||"), ("all", "", "&&"), ("none", "!", "&&")]: - for i in range(2, 5): - elements = ["x", "y", "z", "w"][:i] - print( - f"[[nodiscard]] __device__ inline constexpr auto lc_{f}(lc_bool{i} v) noexcept {{ return {f' {bop} '.join(f'{uop}v.{m}' for m in elements)}; }}", - file=file) - - # matrix types - for i in range(2, 5): - def init(j): - return ', '.join(["0.0f", "0.0f", "0.0f", "s", "0.0f", "0.0f", "0.0f"][3 - j:3 + i - j]) - - - print(f""" -struct lc_float{i}x{i} {{ - lc_float{i} cols[{i}]; - __device__ inline constexpr lc_float{i}x{i}() noexcept : cols{{}} {{}} - __device__ inline explicit constexpr lc_float{i}x{i}(lc_float s) noexcept - : cols{{{", ".join(f"lc_make_float{i}({init(j)})" for j in range(i))}}} {{}} - __device__ inline constexpr static auto full(lc_float s) noexcept {{ return lc_float{i}x{i}{{{", ".join(f"lc_float{i}(s)" for j in range(i))}}}; }} - __device__ inline constexpr static auto zero() noexcept {{ return lc_float{i}x{i}{{{", ".join(f"lc_float{i}::zero()" for j in range(i))}}}; }} - __device__ inline constexpr static auto one() noexcept {{ return lc_float{i}x{i}{{{", ".join(f"lc_float{i}::one()" for j in range(i))}}}; }} - __device__ inline constexpr lc_float{i}x{i}({", ".join(f"lc_float{i} c{j}" for j in range(i))}) noexcept - : cols{{{", ".join(f"c{j}" for j in range(i))}}} {{}} - [[nodiscard]] __device__ inline constexpr auto &operator[](lc_uint i) noexcept {{ return cols[i]; }} - [[nodiscard]] __device__ inline constexpr auto operator[](lc_uint i) const noexcept {{ return cols[i]; }} - [[nodiscard]] __device__ inline constexpr auto comp_mul(const lc_float{i}x{i} &rhs) const noexcept {{ return lc_float{i}x{i}{{{", ".join(f"cols[{j}] * rhs[{j}]" for j in range(i))}}}; }} -}};""", file=file) - - for i in range(2, 5): - elements = ["x", "y", "z", "w"][:i] - print(f""" -[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float{i}x{i} m, lc_float s) noexcept {{ return lc_float{i}x{i}{{{", ".join(f"m[{j}] * s" for j in range(i))}}}; }} -[[nodiscard]] __device__ inline constexpr auto operator*(lc_float s, const lc_float{i}x{i} m) noexcept {{ return m * s; }} -[[nodiscard]] __device__ inline constexpr auto operator/(const lc_float{i}x{i} m, lc_float s) noexcept {{ return m * (1.0f / s); }} -[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float{i}x{i} m, const lc_float{i} v) noexcept {{ return {' + '.join(f"v.{e} * m[{j}]" for j, e in enumerate(elements))}; }} -[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float{i}x{i} lhs, const lc_float{i}x{i} rhs) noexcept {{ return lc_float{i}x{i}{{{', '.join(f"lhs * rhs[{j}]" for j in range(i))}}}; }} -[[nodiscard]] __device__ inline constexpr auto operator+(const lc_float{i}x{i} lhs, const lc_float{i}x{i} rhs) noexcept {{ return lc_float{i}x{i}{{{", ".join(f"lhs[{j}] + rhs[{j}]" for j in range(i))}}}; }} -[[nodiscard]] __device__ inline constexpr auto operator-(const lc_float{i}x{i} lhs, const lc_float{i}x{i} rhs) noexcept {{ return lc_float{i}x{i}{{{", ".join(f"lhs[{j}] - rhs[{j}]" for j in range(i))}}}; }}""", - file=file) - - for i in range(2, 5): - def init(j): - return ', '.join(["0.0f", "0.0f", "0.0f", "s", "0.0f", "0.0f", "0.0f"][3 - j:3 + i - j]) - - - print(f""" -[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}(lc_float s = 1.0f) noexcept {{ return lc_float{i}x{i}{{{", ".join(f"lc_make_float{i}({init(j)})" for j in range(i))}}}; }} -[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}({', '.join(', '.join(f"lc_float m{j}{k}" for k in range(i)) for j in range(i))}) noexcept {{ return lc_float{i}x{i}{{{", ".join(f"lc_make_float{i}({', '.join(f'm{j}{k}' for k in range(i))})" for j in range(i))}}}; }} -[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}({", ".join(f"lc_float{i} c{j}" for j in range(i))}) noexcept {{ return lc_float{i}x{i}{{{", ".join(f"c{j}" for j in range(i))}}}; }}""", - file=file) - if i == 3: - print( - f"[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}(lc_float2x2 m) noexcept {{ return lc_float3x3{{lc_make_float3(m[0], 0.0f), lc_make_float3(m[1], 0.0f), lc_make_float3(0.0f, 0.0f, 1.0f)}}; }}", - file=file) - if i == 4: - print( - f"[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}(lc_float2x2 m) noexcept {{ return lc_float4x4{{lc_make_float4(m[0], 0.0f, 0.0f), lc_make_float4(m[1], 0.0f, 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, 1.0f)}}; }}", - file=file) - print( - f"[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}(lc_float3x3 m) noexcept {{ return lc_float4x4{{lc_make_float4(m[0], 0.0f), lc_make_float4(m[1], 0.0f), lc_make_float4(m[2], 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, 1.0f)}}; }}", - file=file) - print( - f"[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}(lc_float{i}x{i} m) noexcept {{ return m; }}", - file=file) - for t in range(i + 1, 5): - print( - f"[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}(lc_float{t}x{t} m) noexcept {{ return lc_float{i}x{i}{{{', '.join(f'lc_make_float{i}(m[{j}])' for j in range(i))}}}; }}", - file=file) - print(file=file) - - - def generate_vector_call(name, c, types, args): - types = [{ - "s": "short", - "r": "ushort", - "i": "int", - "u": "uint", - "h": "half", - "f": "float", - "b": "bool", - "l": "long", - "z": "ulong"}[t] for t in types] - - def call(i): - e = "xyzw"[i] - return f"{c}(" + ", ".join(f"{a}.{e}" for a in args) + ")" - - for t in types: - ret = t if name not in ['isnan', 'isinf'] else 'bool' - print( - f"[[nodiscard]] __device__ inline lc_{ret} lc_{name}({', '.join(f'lc_{t} {a}' for a in args)}) noexcept {{ return {c}({', '.join(args)}); }}", - file=file) - for n in range(2, 5): - print( - f"[[nodiscard]] __device__ inline lc_{ret}{n} lc_{name}({', '.join(f'lc_{t}{n} {a}' for a in args)}) noexcept {{ return lc_make_{ret}{n}({', '.join(call(i) for i in range(n))}); }}", - file=file) - print(file=file) - - - # select - print( - "template\n[[nodiscard]] __device__ inline auto lc_select(T f, T t, bool p) noexcept { return p ? t : f; }", - file=file) - for t in ["short", "ushort", "int", "uint", "half", "float", "bool", "long", "ulong"]: - for n in range(2, 5): - print( - f"[[nodiscard]] __device__ inline auto lc_select(lc_{t}{n} f, lc_{t}{n} t, lc_bool{n} p) noexcept {{ return lc_make_{t}{n}({', '.join(f'lc_select(f.{e}, t.{e}, p.{e})' for e in 'xyzw'[:n])}); }}", - file=file) - print(file=file) - - # outer product - for t in ["float"]: - for n in range(2, 5): - print( - f"[[nodiscard]] __device__ inline auto lc_outer_product(lc_{t}{n} a, lc_{t}{n} b) noexcept {{ return lc_{t}{n}x{n}({', '.join(f'a * b.{f}' for f in 'xyzw'[:n])}); }}", - file=file) - # min/max/abs/acos/asin/asinh/acosh/atan/atanh/atan2/ - # cos/cosh/sin/sinh/tan/tanh/exp/exp2/exp10/log/log2/ - # log10/sqrt/rsqrt/ceil/floor/trunc/round/fma/copysignf/ - # isinf/isnan - generate_vector_call("min", "fminf", "f", ["a", "b"]) - generate_vector_call("min", "__hmin", "h", ["a", "b"]) - generate_vector_call("max", "fmaxf", "f", ["a", "b"]) - generate_vector_call("max", "__hmax", "h", ["a", "b"]) - generate_vector_call("abs", "fabsf", "f", ["x"]) - generate_vector_call("abs", "abs", "i", ["x"]) - generate_vector_call("abs", "llabs", "l", ["x"]) - generate_vector_call("abs", "__habs", "h", ["x"]) - - generate_vector_call("acos", "acosf", "hf", ["x"]) - generate_vector_call("asin", "asinf", "hf", ["x"]) - generate_vector_call("atan", "atanf", "hf", ["x"]) - generate_vector_call("acosh", "acoshf", "hf", ["x"]) - generate_vector_call("asinh", "asinhf", "hf", ["x"]) - generate_vector_call("atanh", "atanhf", "hf", ["x"]) - generate_vector_call("atan2", "atan2f", "hf", ["y", "x"]) - - generate_vector_call("cosh", "coshf", "hf", ["x"]) - generate_vector_call("sinh", "sinhf", "hf", ["x"]) - generate_vector_call("tanh", "tanhf", "hf", ["x"]) - - generate_vector_call("cos", "cosf", "hf", ["x"]) - generate_vector_call("sin", "sinf", "hf", ["x"]) - generate_vector_call("tan", "tanf", "hf", ["x"]) - generate_vector_call("exp", "expf", "hf", ["x"]) - generate_vector_call("exp2", "exp2f", "f", ["x"]) - generate_vector_call("exp2", "hexp2", "h", ["x"]) - generate_vector_call("exp10", "exp10f", "hf", ["x"]) - generate_vector_call("log", "logf", "hf", ["x"]) - generate_vector_call("log2", "log2f", "hf", ["x"]) - generate_vector_call("log10", "log10f", "hf", ["x"]) - generate_vector_call("pow", "powf_impl", "hf", ["x", "a"]) - generate_vector_call("powi", "powi_impl", "hf", ["x", "a"]) - - generate_vector_call("sqrt", "sqrtf", "f", ["x"]) - generate_vector_call("sqrt", "hsqrt", "h", ["x"]) - - generate_vector_call("rsqrt", "rsqrtf", "f", ["x"]) - generate_vector_call("rsqrt", "hrsqrt", "h", ["x"]) - - generate_vector_call("ceil", "ceilf", "f", ["x"]) - generate_vector_call("ceil", "hceil", "h", ["x"]) - - generate_vector_call("floor", "floorf", "f", ["x"]) - generate_vector_call("floor", "hfloor", "h", ["x"]) - - generate_vector_call("trunc", "truncf", "f", ["x"]) - generate_vector_call("trunc", "htrunc", "h", ["x"]) - - generate_vector_call("round", "roundf", "hf", ["x"]) - - generate_vector_call("fma", "fmaf", "f", ["x", "y", "z"]) - generate_vector_call("fma", "__hfma", "h", ["x", "y", "z"]) - - print(""" -[[nodiscard]] __device__ inline auto lc_copysign_impl(lc_half x, lc_half y) noexcept { - auto ux = __half_as_short(x); - auto uy = __half_as_short(y); - return __short_as_half((ux & 0x7fffu) | (uy & 0x8000u)); -}""", file=file) - - generate_vector_call("copysign", "copysignf", "f", ["x", "y"]) - generate_vector_call("copysign", "lc_copysign_impl", "h", ["x", "y"]) - - generate_vector_call("isinf", "isinf_impl", "f", ["x"]) - generate_vector_call("isnan", "isnan_impl", "f", ["x"]) - generate_vector_call("isinf", "__hisinf", "h", ["x"]) - generate_vector_call("isnan", "__hisnan", "h", ["x"]) - # TODO: half - - # reduce operations - for t in ["short", "ushort", "int", "uint", "half", "float", "long", "ulong"]: - for n in range(2, 5): - print( - f"[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_{t}{n} v) noexcept {{ return lc_{t}({'+'.join(f'v.{e}' for e in 'xyzw'[:n])}); }}", - file=file) - print( - f"[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_{t}{n} v) noexcept {{ return lc_{t}({'*'.join(f'v.{e}' for e in 'xyzw'[:n])}); }}", - file=file) - print( - f"[[nodiscard]] __device__ inline auto lc_reduce_min(lc_{t}{n} v) noexcept {{ return lc_{t}({', '.join(f'lc_min(v.{e}' for e in 'xyzw'[:n - 1])}, v.{'xyzw'[n - 1]}{')' * (n)}; }}", - file=file) - print( - f"[[nodiscard]] __device__ inline auto lc_reduce_max(lc_{t}{n} v) noexcept {{ return lc_{t}({', '.join(f'lc_max(v.{e}' for e in 'xyzw'[:n - 1])}, v.{'xyzw'[n - 1]}{')' * (n)}; }}", - file=file) - - # min/max for int - for t in ["short", "ushort", "int", "uint", "long", "ulong"]: - # lc_min_impl/lc_max_impl - print( - f"[[nodiscard]] __device__ inline auto lc_min_impl(lc_{t} a, lc_{t} b) noexcept {{ return a < b ? a : b; }}", - file=file) - print( - f"[[nodiscard]] __device__ inline auto lc_max_impl(lc_{t} a, lc_{t} b) noexcept {{ return a > b ? a : b; }}", - file=file) - generate_vector_call("min", "lc_min_impl", "sriulz", ["a", "b"]) - generate_vector_call("max", "lc_max_impl", "sriulz", ["a", "b"]) - - # clamp - for t in ["short", "ushort", "int", "uint", "half", "float", "long", "ulong"]: - print( - f"[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_{t} v, lc_{t} lo, lc_{t} hi) noexcept {{ return lc_min(lc_max(v, lo), hi); }}", - file=file) - generate_vector_call("clamp", "lc_clamp_impl", - "sriulzhf", ["v", "lo", "hi"]) - - for t in ["half", "float"]: - # lerp - print( - f"[[nodiscard]] __device__ inline auto lc_lerp_impl(lc_{t} a, lc_{t} b, lc_{t} t) noexcept {{ return t * (b - a) + a; }}", - file=file) - - # saturate - print( - f"[[nodiscard]] __device__ inline auto lc_saturate(lc_{t} x) noexcept {{ return lc_clamp(x, lc_{t}(0.0f), lc_{t}(1.0f)); }}", - file=file) - for n in range(2, 5): - print( - f"[[nodiscard]] __device__ inline auto lc_saturate(lc_{t}{n} x) noexcept {{ return lc_clamp(x, lc_make_{t}{n}(0.0f), lc_make_{t}{n}(1.0f)); }}", - file=file) - print(file=file) - - # degrees/radians - print( - f"[[nodiscard]] __device__ inline auto lc_degrees_impl(lc_{t} rad) noexcept {{ return rad * (lc_{t})(180.0f * 0.318309886183790671537767526745028724f); }}", - file=file) - print( - f"[[nodiscard]] __device__ inline auto lc_radians_impl(lc_{t} deg) noexcept {{ return deg * (lc_{t})(3.14159265358979323846264338327950288f / 180.0f); }}", - file=file) - - # step - print( - f"[[nodiscard]] __device__ inline auto lc_step_impl(lc_{t} edge, lc_{t} x) noexcept {{ return lc_select(lc_{t}(1.f), lc_{t}(0.f), x < edge); }}", - file=file) - - # smoothstep - print( - f"""[[nodiscard]] __device__ inline auto lc_smoothstep_impl(lc_{t} edge0, lc_{t} edge1, lc_{t} x) noexcept {{ - auto t = lc_clamp((x - edge0) / (edge1 - edge0), lc_{t}(0.0f), lc_{t}(1.0f)); - return t * t * (lc_{t}(3.f) - lc_{t}(2.f) * t); -}}""", - file=file) - - # mod - print( - f"[[nodiscard]] __device__ inline auto lc_mod_impl(lc_{t} x, lc_{t} y) noexcept {{ return x - y * lc_floor(x / y); }}", - file=file) - - # fmod - if t == "half": - print( - f"[[nodiscard]] __device__ inline auto lc_fmod_impl(lc_{t} x, lc_{t} y) noexcept {{ return x - y * lc_trunc(x / y); }}", - file=file) - else: - print( - f"[[nodiscard]] __device__ inline auto lc_fmod_impl(lc_{t} x, lc_{t} y) noexcept {{ return fmodf(x, y); }}", - file=file) - - # fract - print( - f"[[nodiscard]] __device__ inline auto lc_fract_impl(lc_{t} x) noexcept {{ return x - lc_floor(x); }}", - file=file) - - generate_vector_call("lerp", "lc_lerp_impl", "hf", ["a", "b", "t"]) - generate_vector_call("degrees", "lc_degrees_impl", "hf", ["rad"]) - generate_vector_call("radians", "lc_radians_impl", "hf", ["deg"]) - generate_vector_call("step", "lc_step_impl", "hf", ["edge", "x"]) - generate_vector_call("smoothstep", "lc_smoothstep_impl", "hf", ["e0", "e1", "x"]) - generate_vector_call("mod", "lc_mod_impl", "hf", ["x", "y"]) - generate_vector_call("fmod", "lc_fmod_impl", "hf", ["x", "y"]) - generate_vector_call("fract", "lc_fract_impl", "hf", ["x"]) - - # clz/popcount/reverse - generate_vector_call("clz", "__clz", "u", ["x"]) - generate_vector_call("clz", "__clzll", "z", ["x"]) - generate_vector_call("popcount", "__popc", "u", ["x"]) - generate_vector_call("popcount", "__popcll", "z", ["x"]) - generate_vector_call("reverse", "__brev", "u", ["x"]) - generate_vector_call("reverse", "__brevll", "z", ["x"]) - - # ctz - print( - f"[[nodiscard]] __device__ inline auto lc_ctz_impl(lc_uint x) noexcept {{ return (__ffs(x) - 1u) % 32u; }}", - file=file) - print( - f"[[nodiscard]] __device__ inline auto lc_ctz_impl(lc_ulong x) noexcept {{ return (__ffsll(x) - 1u) % 64u; }}", - file=file) - generate_vector_call("ctz", "lc_ctz_impl", "uz", ["x"]) - - for t in ["float", "half"]: - # cross - print(f"""[[nodiscard]] __device__ inline constexpr auto lc_cross(lc_{t}3 u, lc_{t}3 v) noexcept {{ - return lc_make_{t}3(u.y * v.z - v.y * u.z, - u.z * v.x - v.z * u.x, - u.x * v.y - v.x * u.y); -}}""", file=file) - print(file=file) - - # dot - print(f"""[[nodiscard]] __device__ inline auto lc_dot(lc_{t}2 a, lc_{t}2 b) noexcept {{ - return a.x * b.x + a.y * b.y; -}}""", file=file) - print(f"""[[nodiscard]] __device__ inline auto lc_dot(lc_{t}3 a, lc_{t}3 b) noexcept {{ - return a.x * b.x + a.y * b.y + a.z * b.z; -}}""", file=file) - print(f"""[[nodiscard]] __device__ inline auto lc_dot(lc_{t}4 a, lc_{t}4 b) noexcept {{ - return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; -}}""", file=file) - print(file=file) - - # length - print( - f"[[nodiscard]] __device__ inline auto lc_length(lc_{t}2 v) noexcept {{ return lc_sqrt(lc_dot(v, v)); }}", - file=file) - print( - f"[[nodiscard]] __device__ inline auto lc_length(lc_{t}3 v) noexcept {{ return lc_sqrt(lc_dot(v, v)); }}", - file=file) - print( - f"[[nodiscard]] __device__ inline auto lc_length(lc_{t}4 v) noexcept {{ return lc_sqrt(lc_dot(v, v)); }}", - file=file) - print(file=file) - - # length_squared - for n in range(2, 5): - print( - f"[[nodiscard]] __device__ inline auto lc_length_squared(lc_{t}{n} v) noexcept {{ return lc_dot(v, v); }}", - file=file) - print(file=file) - - # distance - for n in range(2, 5): - print( - f"[[nodiscard]] __device__ inline auto lc_distance(lc_{t}{n} a, lc_{t}{n} b) noexcept {{ return lc_length(a - b); }}", - file=file) - print(file=file) - - # distance_squared - for n in range(2, 5): - print( - f"[[nodiscard]] __device__ inline auto lc_distance_squared(lc_{t}{n} a, lc_{t}{n} b) noexcept {{ return lc_length_squared(a - b); }}", - file=file) - print(file=file) - - # faceforward - print( - f"[[nodiscard]] __device__ inline auto lc_faceforward(lc_{t}3 n, lc_{t}3 i, lc_{t}3 n_ref) noexcept {{ return lc_select(-n, n, lc_dot(n_ref, i) < lc_{t}(0.f)); }}", - file=file) - print(file=file) - - # normalize - for n in range(2, 5): - print( - f"[[nodiscard]] __device__ inline auto lc_normalize(lc_{t}{n} v) noexcept {{ return v * lc_rsqrt(lc_dot(v, v)); }}", - file=file) - print(file=file) - - # transpose - print("""[[nodiscard]] __device__ inline constexpr auto lc_transpose(const lc_float2x2 m) noexcept { return lc_make_float2x2(m[0].x, m[1].x, m[0].y, m[1].y); } -[[nodiscard]] __device__ inline constexpr auto lc_transpose(const lc_float3x3 m) noexcept { return lc_make_float3x3(m[0].x, m[1].x, m[2].x, m[0].y, m[1].y, m[2].y, m[0].z, m[1].z, m[2].z); } -[[nodiscard]] __device__ inline constexpr auto lc_transpose(const lc_float4x4 m) noexcept { return lc_make_float4x4(m[0].x, m[1].x, m[2].x, m[3].x, m[0].y, m[1].y, m[2].y, m[3].y, m[0].z, m[1].z, m[2].z, m[3].z, m[0].w, m[1].w, m[2].w, m[3].w); } -""", file=file) - - # determinant/inverse - print("""[[nodiscard]] __device__ inline constexpr auto lc_determinant(const lc_float2x2 m) noexcept { - return m[0][0] * m[1][1] - m[1][0] * m[0][1]; -} - -[[nodiscard]] __device__ constexpr auto lc_determinant(const lc_float3x3 m) noexcept {// from GLM - return m[0].x * (m[1].y * m[2].z - m[2].y * m[1].z) - - m[1].x * (m[0].y * m[2].z - m[2].y * m[0].z) - + m[2].x * (m[0].y * m[1].z - m[1].y * m[0].z); -} - -[[nodiscard]] __device__ inline constexpr auto lc_determinant(const lc_float4x4 m) noexcept {// from GLM - const auto coef00 = m[2].z * m[3].w - m[3].z * m[2].w; - const auto coef02 = m[1].z * m[3].w - m[3].z * m[1].w; - const auto coef03 = m[1].z * m[2].w - m[2].z * m[1].w; - const auto coef04 = m[2].y * m[3].w - m[3].y * m[2].w; - const auto coef06 = m[1].y * m[3].w - m[3].y * m[1].w; - const auto coef07 = m[1].y * m[2].w - m[2].y * m[1].w; - const auto coef08 = m[2].y * m[3].z - m[3].y * m[2].z; - const auto coef10 = m[1].y * m[3].z - m[3].y * m[1].z; - const auto coef11 = m[1].y * m[2].z - m[2].y * m[1].z; - const auto coef12 = m[2].x * m[3].w - m[3].x * m[2].w; - const auto coef14 = m[1].x * m[3].w - m[3].x * m[1].w; - const auto coef15 = m[1].x * m[2].w - m[2].x * m[1].w; - const auto coef16 = m[2].x * m[3].z - m[3].x * m[2].z; - const auto coef18 = m[1].x * m[3].z - m[3].x * m[1].z; - const auto coef19 = m[1].x * m[2].z - m[2].x * m[1].z; - const auto coef20 = m[2].x * m[3].y - m[3].x * m[2].y; - const auto coef22 = m[1].x * m[3].y - m[3].x * m[1].y; - const auto coef23 = m[1].x * m[2].y - m[2].x * m[1].y; - const auto fac0 = lc_make_float4(coef00, coef00, coef02, coef03); - const auto fac1 = lc_make_float4(coef04, coef04, coef06, coef07); - const auto fac2 = lc_make_float4(coef08, coef08, coef10, coef11); - const auto fac3 = lc_make_float4(coef12, coef12, coef14, coef15); - const auto fac4 = lc_make_float4(coef16, coef16, coef18, coef19); - const auto fac5 = lc_make_float4(coef20, coef20, coef22, coef23); - const auto Vec0 = lc_make_float4(m[1].x, m[0].x, m[0].x, m[0].x); - const auto Vec1 = lc_make_float4(m[1].y, m[0].y, m[0].y, m[0].y); - const auto Vec2 = lc_make_float4(m[1].z, m[0].z, m[0].z, m[0].z); - const auto Vec3 = lc_make_float4(m[1].w, m[0].w, m[0].w, m[0].w); - const auto inv0 = Vec1 * fac0 - Vec2 * fac1 + Vec3 * fac2; - const auto inv1 = Vec0 * fac0 - Vec2 * fac3 + Vec3 * fac4; - const auto inv2 = Vec0 * fac1 - Vec1 * fac3 + Vec3 * fac5; - const auto inv3 = Vec0 * fac2 - Vec1 * fac4 + Vec2 * fac5; - constexpr auto sign_a = lc_make_float4(+1.0f, -1.0f, +1.0f, -1.0f); - constexpr auto sign_b = lc_make_float4(-1.0f, +1.0f, -1.0f, +1.0f); - const auto inv_0 = inv0 * sign_a; - const auto inv_1 = inv1 * sign_b; - const auto inv_2 = inv2 * sign_a; - const auto inv_3 = inv3 * sign_b; - const auto dot0 = m[0] * lc_make_float4(inv_0.x, inv_1.x, inv_2.x, inv_3.x); - return dot0.x + dot0.y + dot0.z + dot0.w; -} - -[[nodiscard]] __device__ inline constexpr auto lc_inverse(const lc_float2x2 m) noexcept { - const auto one_over_determinant = 1.0f / (m[0][0] * m[1][1] - m[1][0] * m[0][1]); - return lc_make_float2x2(m[1][1] * one_over_determinant, - - m[0][1] * one_over_determinant, - - m[1][0] * one_over_determinant, - + m[0][0] * one_over_determinant); -} - -[[nodiscard]] __device__ inline constexpr auto lc_inverse(const lc_float3x3 m) noexcept {// from GLM - const auto one_over_determinant = 1.0f - / (m[0].x * (m[1].y * m[2].z - m[2].y * m[1].z) - - m[1].x * (m[0].y * m[2].z - m[2].y * m[0].z) - + m[2].x * (m[0].y * m[1].z - m[1].y * m[0].z)); - return lc_make_float3x3( - (m[1].y * m[2].z - m[2].y * m[1].z) * one_over_determinant, - (m[2].y * m[0].z - m[0].y * m[2].z) * one_over_determinant, - (m[0].y * m[1].z - m[1].y * m[0].z) * one_over_determinant, - (m[2].x * m[1].z - m[1].x * m[2].z) * one_over_determinant, - (m[0].x * m[2].z - m[2].x * m[0].z) * one_over_determinant, - (m[1].x * m[0].z - m[0].x * m[1].z) * one_over_determinant, - (m[1].x * m[2].y - m[2].x * m[1].y) * one_over_determinant, - (m[2].x * m[0].y - m[0].x * m[2].y) * one_over_determinant, - (m[0].x * m[1].y - m[1].x * m[0].y) * one_over_determinant); -} - -[[nodiscard]] __device__ inline constexpr auto lc_inverse(const lc_float4x4 m) noexcept {// from GLM - const auto coef00 = m[2].z * m[3].w - m[3].z * m[2].w; - const auto coef02 = m[1].z * m[3].w - m[3].z * m[1].w; - const auto coef03 = m[1].z * m[2].w - m[2].z * m[1].w; - const auto coef04 = m[2].y * m[3].w - m[3].y * m[2].w; - const auto coef06 = m[1].y * m[3].w - m[3].y * m[1].w; - const auto coef07 = m[1].y * m[2].w - m[2].y * m[1].w; - const auto coef08 = m[2].y * m[3].z - m[3].y * m[2].z; - const auto coef10 = m[1].y * m[3].z - m[3].y * m[1].z; - const auto coef11 = m[1].y * m[2].z - m[2].y * m[1].z; - const auto coef12 = m[2].x * m[3].w - m[3].x * m[2].w; - const auto coef14 = m[1].x * m[3].w - m[3].x * m[1].w; - const auto coef15 = m[1].x * m[2].w - m[2].x * m[1].w; - const auto coef16 = m[2].x * m[3].z - m[3].x * m[2].z; - const auto coef18 = m[1].x * m[3].z - m[3].x * m[1].z; - const auto coef19 = m[1].x * m[2].z - m[2].x * m[1].z; - const auto coef20 = m[2].x * m[3].y - m[3].x * m[2].y; - const auto coef22 = m[1].x * m[3].y - m[3].x * m[1].y; - const auto coef23 = m[1].x * m[2].y - m[2].x * m[1].y; - const auto fac0 = lc_make_float4(coef00, coef00, coef02, coef03); - const auto fac1 = lc_make_float4(coef04, coef04, coef06, coef07); - const auto fac2 = lc_make_float4(coef08, coef08, coef10, coef11); - const auto fac3 = lc_make_float4(coef12, coef12, coef14, coef15); - const auto fac4 = lc_make_float4(coef16, coef16, coef18, coef19); - const auto fac5 = lc_make_float4(coef20, coef20, coef22, coef23); - const auto Vec0 = lc_make_float4(m[1].x, m[0].x, m[0].x, m[0].x); - const auto Vec1 = lc_make_float4(m[1].y, m[0].y, m[0].y, m[0].y); - const auto Vec2 = lc_make_float4(m[1].z, m[0].z, m[0].z, m[0].z); - const auto Vec3 = lc_make_float4(m[1].w, m[0].w, m[0].w, m[0].w); - const auto inv0 = Vec1 * fac0 - Vec2 * fac1 + Vec3 * fac2; - const auto inv1 = Vec0 * fac0 - Vec2 * fac3 + Vec3 * fac4; - const auto inv2 = Vec0 * fac1 - Vec1 * fac3 + Vec3 * fac5; - const auto inv3 = Vec0 * fac2 - Vec1 * fac4 + Vec2 * fac5; - constexpr auto sign_a = lc_make_float4(+1.0f, -1.0f, +1.0f, -1.0f); - constexpr auto sign_b = lc_make_float4(-1.0f, +1.0f, -1.0f, +1.0f); - const auto inv_0 = inv0 * sign_a; - const auto inv_1 = inv1 * sign_b; - const auto inv_2 = inv2 * sign_a; - const auto inv_3 = inv3 * sign_b; - const auto dot0 = m[0] * lc_make_float4(inv_0.x, inv_1.x, inv_2.x, inv_3.x); - const auto dot1 = dot0.x + dot0.y + dot0.z + dot0.w; - const auto one_over_determinant = 1.0f / dot1; - return lc_make_float4x4(inv_0 * one_over_determinant, - inv_1 * one_over_determinant, - inv_2 * one_over_determinant, - inv_3 * one_over_determinant); -} - -[[nodiscard]] __device__ inline auto lc_reflect(const lc_float3 v, const lc_float3 n) noexcept { - return v - 2.0f * lc_dot(v, n) * n; -} - -template -[[nodiscard]] __device__ inline auto lc_bit_cast(S s) noexcept { - static_assert(sizeof(D) == sizeof(S)); - return reinterpret_cast(s); -} -template -[[nodiscard]] __device__ inline constexpr auto lc_zero() noexcept { - return T{}; -} -template -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return T::one(); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_int(1); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_float(1.0f); -} -template<> -[[nodiscard]] __device__ inline auto lc_one() noexcept { - return lc_half(1.0f); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_uint(1u); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_long(1); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_ulong(1); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_short(1); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_ushort(1); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_byte(1); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return lc_ubyte(1); -} -template<> -[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { - return true; -} -template -class lc_array { - -private: - T _data[N]; - -public: - template - __device__ constexpr lc_array(Elem... elem) noexcept : _data{elem...} {} - __device__ constexpr lc_array(lc_array &&) noexcept = default; - __device__ constexpr lc_array(const lc_array &) noexcept = default; - __device__ constexpr lc_array &operator=(lc_array &&) noexcept = default; - __device__ constexpr lc_array &operator=(const lc_array &) noexcept = default; - [[nodiscard]] __device__ T &operator[](size_t i) noexcept { return _data[i]; } - [[nodiscard]] __device__ T operator[](size_t i) const noexcept { return _data[i]; } - -public: - [[nodiscard]] __device__ static auto one() noexcept { - lc_array ret; - #pragma unroll - for (auto i = 0u; i < N; i++) { ret[i] = lc_one(); } - return ret; - } -}; - -[[nodiscard]] __device__ inline auto lc_mat_comp_mul(lc_float2x2 lhs, lc_float2x2 rhs) noexcept { - return lc_make_float2x2(lhs[0] * rhs[0], - lhs[1] * rhs[1]); -} - -[[nodiscard]] __device__ inline auto lc_mat_comp_mul(lc_float3x3 lhs, lc_float3x3 rhs) noexcept { - return lc_make_float3x3(lhs[0] * rhs[0], - lhs[1] * rhs[1], - lhs[2] * rhs[2]); -} - -[[nodiscard]] __device__ inline auto lc_mat_comp_mul(lc_float4x4 lhs, lc_float4x4 rhs) noexcept { - return lc_make_float4x4(lhs[0] * rhs[0], - lhs[1] * rhs[1], - lhs[2] * rhs[2], - lhs[3] * rhs[3]); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float2 v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float3 v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float4 v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half2 v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half3 v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half4 v) noexcept { - return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float2x2 v) noexcept { - v.cols[0] = lc_remove_nan(v.cols[0]); - v.cols[1] = lc_remove_nan(v.cols[1]); - return v; -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float3x3 v) noexcept { - v.cols[0] = lc_remove_nan(v.cols[0]); - v.cols[1] = lc_remove_nan(v.cols[1]); - v.cols[2] = lc_remove_nan(v.cols[2]); - return v; -} -[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float4x4 v) noexcept { - v.cols[0] = lc_remove_nan(v.cols[0]); - v.cols[1] = lc_remove_nan(v.cols[1]); - v.cols[2] = lc_remove_nan(v.cols[2]); - v.cols[3] = lc_remove_nan(v.cols[3]); - return v; -} -""", file=file) - # accumlate_grad(T*, const T) for all types - float_types = [ - "lc_float", - "lc_float2x2", "lc_float3x3", "lc_float4x4", - "lc_float2", "lc_float3", "lc_float4", - "lc_half", "lc_half2", "lc_half3", "lc_half4", - ] - for t in float_types: - print( - f"__device__ inline void lc_accumulate_grad({t} *dst, {t} grad) noexcept {{ *dst = *dst + lc_remove_nan(grad); }}", - file=file) - non_differentiable_types = [ - "lc_short", "lc_ushort", "lc_int", "lc_uint", "lc_long", "lc_ulong", "lc_bool",'lc_byte', 'lc_ubyte', - 'lc_byte2', 'lc_byte3', 'lc_byte4', - 'lc_ubyte2', 'lc_ubyte3', 'lc_ubyte4', - "lc_short2", "lc_short3", "lc_short4", - "lc_ushort2", "lc_ushort3", "lc_ushort4", - "lc_int2", "lc_int3", "lc_int4", - "lc_uint2", "lc_uint3", "lc_uint4", - "lc_long2", "lc_long3", "lc_long4", - "lc_ulong2", "lc_ulong3", "lc_ulong4", - "lc_bool2", "lc_bool3", "lc_bool4", - ] - for t in non_differentiable_types: - print( - f"__device__ inline void lc_accumulate_grad({t} *dst, {t} grad) noexcept {{}}", file=file) - print( - "struct lc_user_data_t{}; constexpr lc_user_data_t _lc_user_data{};", file=file) - print('''template struct element_type_{using type = void;}; -template using element_type = typename element_type_::type; -''', file=file) - - - def gen_element_type(vt, et): - print(f'''template<> struct element_type_<{vt}> {{ using type = {et}; }};''', file=file) - - - for vt in ['lc_float2', 'lc_float3', 'lc_float4']: - gen_element_type(vt, "lc_float") - for vt in ['lc_half2', 'lc_half3', 'lc_half4']: - gen_element_type(vt, "lc_half") - for vt in ['lc_short2', 'lc_short3', 'lc_short4']: - gen_element_type(vt, 'lc_short') - for vt in ['lc_ushort2', 'lc_ushort3', 'lc_ushort4']: - gen_element_type(vt, 'lc_ushort') - for vt in ['lc_byte2', 'lc_byte3', 'lc_byte4']: - gen_element_type(vt, 'lc_byte') - for vt in ['lc_ubyte2', 'lc_ubyte3', 'lc_ubyte4']: - gen_element_type(vt, 'lc_ubyte') - for vt in ['lc_int2', 'lc_int3', 'lc_int4']: - gen_element_type(vt, 'lc_int') - for vt in ['lc_uint2', 'lc_uint3', 'lc_uint4']: - gen_element_type(vt, 'lc_uint') - for vt in ['lc_long2', 'lc_long3', 'lc_long4']: - gen_element_type(vt, 'lc_long') - for vt in ['lc_ulong2', 'lc_ulong3', 'lc_ulong4']: - gen_element_type(vt, 'lc_ulong') - - print(''' -template -__device__ inline void lc_accumulate_grad(lc_array *dst, lc_array grad) noexcept { - #pragma unroll - for (auto i = 0u; i < N; i++) { lc_accumulate_grad(&(*dst)[i], grad[i]); } -}''', file=file) +from os.path import realpath, dirname +from sys import argv + +HALF_IMPL = ''' +struct lc_half { +private: + union U { __fp16 h; lc_ushort bits; }; +public: + lc_ushort bits; + inline constexpr lc_half() noexcept : bits{0} {} + [[nodiscard]] static inline constexpr auto from_bits(lc_ushort bits) noexcept { + lc_half h; + h.bits = bits; + return h; + } + inline constexpr lc_half(float x) noexcept { + U u; + u.h = x; + bits = u.bits; + } + template + inline constexpr operator T() const noexcept { + U u; + u.bits = bits; + return static_cast(static_cast(u.h)); + } + inline constexpr auto operator-() const noexcept { return from_bits(bits ^ 0x8000u); } + inline constexpr auto operator+() const noexcept { return *this; } + inline constexpr auto operator!() const noexcept { return bits == 0u || bits == 0x8000u; } +#define IMPL_HALF_BINOP(op) \ + inline constexpr auto operator op(lc_half rhs) const noexcept { \ + U u_lhs; u_lhs.bits = bits; \ + U u_rhs; u_rhs.bits = rhs.bits; \ + return lc_half{lc_float(u_lhs.h op u_rhs.h)}; \ + } + IMPL_HALF_BINOP(+) + IMPL_HALF_BINOP(-) + IMPL_HALF_BINOP(*) + IMPL_HALF_BINOP(/) +#undef IMPL_HALF_BINOP +#define IMPL_HALF_CMP(op) inline constexpr auto operator op(lc_half rhs) const noexcept { return float(*this) op float(rhs); } + IMPL_HALF_CMP(==) + IMPL_HALF_CMP(!=) + IMPL_HALF_CMP(<) + IMPL_HALF_CMP(<=) + IMPL_HALF_CMP(>) + IMPL_HALF_CMP(>=) + +}; +static_assert(sizeof(lc_half) == 2); +[[nodiscard]] inline lc_short __half_as_short(lc_half x) noexcept { + return x.bits; +} +[[nodiscard]] inline lc_half __short_as_half(lc_short x) noexcept { + return lc_half::from_bits(x); +} +[[nodiscard]] inline lc_half __hmax(lc_half x, lc_half y) noexcept { return lc_half{lc_float(x) > lc_float(y) ? x : y}; } +[[nodiscard]] inline lc_half __hmin(lc_half x, lc_half y) noexcept { return lc_half{lc_float(x) < lc_float(y) ? x : y}; } +[[nodiscard]] inline lc_half __habs(lc_half x) noexcept { return lc_half{lc_float(x) < 0.0f ? -x : x}; } +[[nodiscard]] inline lc_half hexp2(lc_half x) noexcept { return lc_half{exp2f(lc_float(x))}; } +[[nodiscard]] inline lc_half hceil(lc_half x) noexcept { return lc_half{ceilf(lc_float(x))}; } +[[nodiscard]] inline lc_half hfloor(lc_half x) noexcept { return lc_half{floorf(lc_float(x))}; } +[[nodiscard]] inline lc_half htrunc(lc_half x) noexcept { return lc_half{truncf(lc_float(x))}; } +[[nodiscard]] inline lc_half hround(lc_half x) noexcept { return lc_half{rintf(lc_float(x))}; } +[[nodiscard]] inline lc_half hsqrt(lc_half x) noexcept { return lc_half{sqrtf(lc_float(x))}; } +[[nodiscard]] inline lc_half hrsqrt(lc_half x) noexcept { return lc_half{rsqrtf(lc_float(x))}; } +[[nodiscard]] inline lc_half __hfma(lc_half x, lc_half y, lc_half z) noexcept { return lc_half{fmaf(lc_float(x), lc_float(y), lc_float(z))}; } +[[nodiscard]] inline bool __hisnan(lc_half x) noexcept { return isnan_impl(lc_float(x)); } +[[nodiscard]] inline bool __hisinf(lc_half x) noexcept { return isinf_impl(lc_float(x)); } +''' + +if __name__ == "__main__": + if len(argv) < 2: + print("usage: python generate_device_library.py ") + exit(1) + output_file_name = argv[1] + is_cpu = 'cpu' in output_file_name + with open(f"{output_file_name}", "w") as file: + # scalar types + scalar_types = ["byte", "ubyte", "short", "ushort", "int", + "uint", "half", "float", "bool", "long", "ulong"] + native_types = ["char", "unsigned char", "short", "unsigned short", "int", "unsigned int", + "half", "float", "bool", "long long", "unsigned long long"] + scalar_alignments = { + "byte": 1, + "ubyte": 1, + "short": 2, + "ushort": 2, + "int": 4, + "uint": 4, + "half": 2, + "float": 4, + "bool": 1, + "long": 8, + "ulong": 8, + } + for t, native_t in zip(scalar_types, native_types): + if t == 'half' and is_cpu: + continue + print(f"using lc_{t} = {native_t};", file=file) + print(file=file) + print('''[[nodiscard]] __device__ inline bool isinf_impl(lc_float x) noexcept { + auto u = __float_as_int(x); + return u == 0x7f800000u | u == 0xff800000u; +} +[[nodiscard]] __device__ inline bool isnan_impl(lc_float x) noexcept { + auto u = __float_as_int(x); + return ((u & 0x7F800000u) == 0x7F800000u) & ((u & 0x7FFFFFu) != 0u); +} +[[nodiscard]] __device__ inline lc_float powi_impl(lc_float x, lc_int y) noexcept { + lc_float r = 1.0f; + auto is_y_neg = y < 0; + auto y_abs = is_y_neg ? -y : y; + + while (y_abs) { + if (y_abs & 1) r *= x; + x *= x; + y_abs >>= 1; + } + return is_y_neg ? 1.0f / r : r; +} +[[nodiscard]] __device__ inline lc_float powf_impl(lc_float x, lc_float y) noexcept { + auto y_int = static_cast(y); + return y_int == y ? powi_impl(x, y_int) : powf(x, y); +} +''', file=file) + if is_cpu: + print(HALF_IMPL, file=file) + # vector types + for type in scalar_types: + for i in range(2, 5): + align = min(16, scalar_alignments[type] * (i if i != 3 else 4)) + elements = ["x", "y", "z", "w"][:i] + print( + f"""struct alignas({align}) lc_{type}{i} {{ + lc_{type} {', '.join(elements[:i + 1])}; + __device__ inline constexpr lc_{type}{i}() noexcept + : {', '.join(f"{m}{{}}" for m in elements)} {{}} + __device__ inline constexpr static auto zero() noexcept {{ return lc_{type}{i}{{}}; }} + __device__ inline constexpr static auto one() noexcept {{ return lc_{type}{i}{{{', '.join('1' for _ in elements)}}}; }} + __device__ inline explicit constexpr lc_{type}{i}(lc_{type} s) noexcept + : {', '.join(f"{m}{{s}}" for m in elements)} {{}} + __device__ inline constexpr lc_{type}{i}({', '.join(f"lc_{type} {m}" for m in elements)}) noexcept + : {', '.join(f"{m}{{{m}}}" for m in elements)} {{}} + __device__ inline constexpr auto &operator[](lc_uint i) noexcept {{ return (&x)[i]; }} + __device__ inline constexpr auto operator[](lc_uint i) const noexcept {{ return (&x)[i]; }} +}}; +""", file=file) + + # make type[n] + for type in scalar_types: + # make type2 + print( + f"""[[nodiscard]] __device__ inline constexpr auto lc_make_{type}2(lc_{type} s = 0) noexcept {{ return lc_{type}2{{s, s}}; }} +[[nodiscard]] __device__ inline constexpr auto lc_make_{type}2(lc_{type} x, lc_{type} y) noexcept {{ return lc_{type}2{{x, y}}; }}""", + file=file) + for t in scalar_types: + for l in range(2, 5): + print( + f"[[nodiscard]] __device__ inline constexpr auto lc_make_{type}2(lc_{t}{l} v) noexcept {{ return lc_{type}2{{static_cast(v.x), static_cast(v.y)}}; }}", + file=file) + # make type3 + print( + f"""[[nodiscard]] inline __device__ constexpr auto lc_make_{type}3(lc_{type} s = 0) noexcept {{ return lc_{type}3{{s, s, s}}; }} +[[nodiscard]] __device__ inline constexpr auto lc_make_{type}3(lc_{type} x, lc_{type} y, lc_{type} z) noexcept {{ return lc_{type}3{{x, y, z}}; }} +[[nodiscard]] __device__ inline constexpr auto lc_make_{type}3(lc_{type} x, lc_{type}2 yz) noexcept {{ return lc_{type}3{{x, yz.x, yz.y}}; }} +[[nodiscard]] __device__ inline constexpr auto lc_make_{type}3(lc_{type}2 xy, lc_{type} z) noexcept {{ return lc_{type}3{{xy.x, xy.y, z}}; }}""", + file=file) + for t in scalar_types: + for l in range(3, 5): + print( + f"[[nodiscard]] __device__ constexpr auto lc_make_{type}3(lc_{t}{l} v) noexcept {{ return lc_{type}3{{static_cast(v.x), static_cast(v.y), static_cast(v.z)}}; }}", + file=file) + # make type4 + print( + f"""[[nodiscard]] inline __device__ constexpr auto lc_make_{type}4(lc_{type} s = 0) noexcept {{ return lc_{type}4{{s, s, s, s}}; }} +[[nodiscard]] __device__ inline constexpr auto lc_make_{type}4(lc_{type} x, lc_{type} y, lc_{type} z, lc_{type} w) noexcept {{ return lc_{type}4{{x, y, z, w}}; }} +[[nodiscard]] __device__ inline constexpr auto lc_make_{type}4(lc_{type} x, lc_{type} y, lc_{type}2 zw) noexcept {{ return lc_{type}4{{x, y, zw.x, zw.y}}; }} +[[nodiscard]] __device__ inline constexpr auto lc_make_{type}4(lc_{type} x, lc_{type}2 yz, lc_{type} w) noexcept {{ return lc_{type}4{{x, yz.x, yz.y, w}}; }} +[[nodiscard]] __device__ inline constexpr auto lc_make_{type}4(lc_{type}2 xy, lc_{type} z, lc_{type} w) noexcept {{ return lc_{type}4{{xy.x, xy.y, z, w}}; }} +[[nodiscard]] __device__ inline constexpr auto lc_make_{type}4(lc_{type}2 xy, lc_{type}2 zw) noexcept {{ return lc_{type}4{{xy.x, xy.y, zw.x, zw.y}}; }} +[[nodiscard]] __device__ inline constexpr auto lc_make_{type}4(lc_{type} x, lc_{type}3 yzw) noexcept {{ return lc_{type}4{{x, yzw.x, yzw.y, yzw.z}}; }} +[[nodiscard]] __device__ inline constexpr auto lc_make_{type}4(lc_{type}3 xyz, lc_{type} w) noexcept {{ return lc_{type}4{{xyz.x, xyz.y, xyz.z, w}}; }}""", + file=file) + for t in scalar_types: + print( + f"[[nodiscard]] inline __device__ constexpr auto lc_make_{type}4(lc_{t}4 v) noexcept {{ return lc_{type}4{{static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)}}; }}", + file=file) + print(file=file) + + # unary operators + for type in scalar_types: + for i in range(2, 5): + elements = ["x", "y", "z", "w"][:i] + print( + f"[[nodiscard]] inline __device__ constexpr auto operator!(lc_{type}{i} v) noexcept {{ return lc_make_bool{i}({', '.join(f'!v.{m}' for m in elements)}); }}", + file=file) + if type != "bool": + print( + f"[[nodiscard]] inline __device__ constexpr auto operator+(lc_{type}{i} v) noexcept {{ return lc_make_{type}{i}({', '.join(f'+v.{m}' for m in elements)}); }}", + file=file) + print( + f"[[nodiscard]] inline __device__ constexpr auto operator-(lc_{type}{i} v) noexcept {{ return lc_make_{type}{i}({', '.join(f'-v.{m}' for m in elements)}); }}", + file=file) + if type != "float" and type != "half": + print( + f"[[nodiscard]] inline __device__ constexpr auto operator~(lc_{type}{i} v) noexcept {{ return lc_make_{type}{i}({', '.join(f'~v.{m}' for m in elements)}); }}", + file=file) + print(file=file) + + + def gen_binary_op(arg_t, ret_t, op): + for i in range(2, 5): + elements = ["x", "y", "z", "w"][:i] + # vector-vector + print( + f"[[nodiscard]] inline __device__ constexpr auto operator{op}(lc_{arg_t}{i} lhs, lc_{arg_t}{i} rhs) noexcept {{ return lc_make_{ret_t}{i}({', '.join(f'lhs.{m} {op} rhs.{m}' for m in elements)}); }}", + file=file) + # vector-scalar + operation = ", ".join(f"lhs.{e} {op} rhs" for e in "xyzw"[:i]) + print( + f"[[nodiscard]] inline __device__ constexpr auto operator{op}(lc_{arg_t}{i} lhs, lc_{arg_t} rhs) noexcept {{ return lc_make_{ret_t}{i}({operation}); }}", + file=file) + # scalar-vector + operation = ", ".join(f"lhs {op} rhs.{e}" for e in "xyzw"[:i]) + print( + f"[[nodiscard]] inline __device__ constexpr auto operator{op}(lc_{arg_t} lhs, lc_{arg_t}{i} rhs) noexcept {{ return lc_make_{ret_t}{i}({operation}); }}", + file=file) + + + # binary operators + for op in ["==", "!="]: + for type in scalar_types: + gen_binary_op(type, "bool", op) + print(file=file) + for op in ["<", ">", "<=", ">="]: + for type in ["short", "ushort", "int", "uint", "half", "float", "long", "ulong"]: + gen_binary_op(type, "bool", op) + print(file=file) + for op in ["+", "-", "*", "/"]: + for type in ["short", "ushort", "int", "uint", "half", "float", "long", "ulong"]: + gen_binary_op(type, type, op) + print(file=file) + for op in ["%", "<<", ">>"]: + for type in ["short", "ushort", "int", "uint", "long", "ulong"]: + gen_binary_op(type, type, op) + print(file=file) + for op in ["|", "&", "^"]: + for type in ["short", "ushort", "int", "uint", "bool", "long", "ulong"]: + gen_binary_op(type, type, op) + print(file=file) + for op in ["||", "&&"]: + gen_binary_op("bool", "bool", op) + print(file=file) + + # any, all, none + for f, uop, bop in [("any", "", "||"), ("all", "", "&&"), ("none", "!", "&&")]: + for i in range(2, 5): + elements = ["x", "y", "z", "w"][:i] + print( + f"[[nodiscard]] __device__ inline constexpr auto lc_{f}(lc_bool{i} v) noexcept {{ return {f' {bop} '.join(f'{uop}v.{m}' for m in elements)}; }}", + file=file) + + # matrix types + for i in range(2, 5): + def init(j): + return ', '.join(["0.0f", "0.0f", "0.0f", "s", "0.0f", "0.0f", "0.0f"][3 - j:3 + i - j]) + + + print(f""" +struct lc_float{i}x{i} {{ + lc_float{i} cols[{i}]; + __device__ inline constexpr lc_float{i}x{i}() noexcept : cols{{}} {{}} + __device__ inline explicit constexpr lc_float{i}x{i}(lc_float s) noexcept + : cols{{{", ".join(f"lc_make_float{i}({init(j)})" for j in range(i))}}} {{}} + __device__ inline constexpr static auto full(lc_float s) noexcept {{ return lc_float{i}x{i}{{{", ".join(f"lc_float{i}(s)" for j in range(i))}}}; }} + __device__ inline constexpr static auto zero() noexcept {{ return lc_float{i}x{i}{{{", ".join(f"lc_float{i}::zero()" for j in range(i))}}}; }} + __device__ inline constexpr static auto one() noexcept {{ return lc_float{i}x{i}{{{", ".join(f"lc_float{i}::one()" for j in range(i))}}}; }} + __device__ inline constexpr lc_float{i}x{i}({", ".join(f"lc_float{i} c{j}" for j in range(i))}) noexcept + : cols{{{", ".join(f"c{j}" for j in range(i))}}} {{}} + [[nodiscard]] __device__ inline constexpr auto &operator[](lc_uint i) noexcept {{ return cols[i]; }} + [[nodiscard]] __device__ inline constexpr auto operator[](lc_uint i) const noexcept {{ return cols[i]; }} + [[nodiscard]] __device__ inline constexpr auto comp_mul(const lc_float{i}x{i} &rhs) const noexcept {{ return lc_float{i}x{i}{{{", ".join(f"cols[{j}] * rhs[{j}]" for j in range(i))}}}; }} +}};""", file=file) + + for i in range(2, 5): + elements = ["x", "y", "z", "w"][:i] + print(f""" +[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float{i}x{i} m, lc_float s) noexcept {{ return lc_float{i}x{i}{{{", ".join(f"m[{j}] * s" for j in range(i))}}}; }} +[[nodiscard]] __device__ inline constexpr auto operator*(lc_float s, const lc_float{i}x{i} m) noexcept {{ return m * s; }} +[[nodiscard]] __device__ inline constexpr auto operator/(const lc_float{i}x{i} m, lc_float s) noexcept {{ return m * (1.0f / s); }} +[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float{i}x{i} m, const lc_float{i} v) noexcept {{ return {' + '.join(f"v.{e} * m[{j}]" for j, e in enumerate(elements))}; }} +[[nodiscard]] __device__ inline constexpr auto operator*(const lc_float{i}x{i} lhs, const lc_float{i}x{i} rhs) noexcept {{ return lc_float{i}x{i}{{{', '.join(f"lhs * rhs[{j}]" for j in range(i))}}}; }} +[[nodiscard]] __device__ inline constexpr auto operator+(const lc_float{i}x{i} lhs, const lc_float{i}x{i} rhs) noexcept {{ return lc_float{i}x{i}{{{", ".join(f"lhs[{j}] + rhs[{j}]" for j in range(i))}}}; }} +[[nodiscard]] __device__ inline constexpr auto operator-(const lc_float{i}x{i} lhs, const lc_float{i}x{i} rhs) noexcept {{ return lc_float{i}x{i}{{{", ".join(f"lhs[{j}] - rhs[{j}]" for j in range(i))}}}; }}""", + file=file) + + for i in range(2, 5): + def init(j): + return ', '.join(["0.0f", "0.0f", "0.0f", "s", "0.0f", "0.0f", "0.0f"][3 - j:3 + i - j]) + + + print(f""" +[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}(lc_float s = 1.0f) noexcept {{ return lc_float{i}x{i}{{{", ".join(f"lc_make_float{i}({init(j)})" for j in range(i))}}}; }} +[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}({', '.join(', '.join(f"lc_float m{j}{k}" for k in range(i)) for j in range(i))}) noexcept {{ return lc_float{i}x{i}{{{", ".join(f"lc_make_float{i}({', '.join(f'm{j}{k}' for k in range(i))})" for j in range(i))}}}; }} +[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}({", ".join(f"lc_float{i} c{j}" for j in range(i))}) noexcept {{ return lc_float{i}x{i}{{{", ".join(f"c{j}" for j in range(i))}}}; }}""", + file=file) + if i == 3: + print( + f"[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}(lc_float2x2 m) noexcept {{ return lc_float3x3{{lc_make_float3(m[0], 0.0f), lc_make_float3(m[1], 0.0f), lc_make_float3(0.0f, 0.0f, 1.0f)}}; }}", + file=file) + if i == 4: + print( + f"[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}(lc_float2x2 m) noexcept {{ return lc_float4x4{{lc_make_float4(m[0], 0.0f, 0.0f), lc_make_float4(m[1], 0.0f, 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, 1.0f)}}; }}", + file=file) + print( + f"[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}(lc_float3x3 m) noexcept {{ return lc_float4x4{{lc_make_float4(m[0], 0.0f), lc_make_float4(m[1], 0.0f), lc_make_float4(m[2], 0.0f), lc_make_float4(0.0f, 0.0f, 0.0f, 1.0f)}}; }}", + file=file) + print( + f"[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}(lc_float{i}x{i} m) noexcept {{ return m; }}", + file=file) + for t in range(i + 1, 5): + print( + f"[[nodiscard]] __device__ inline constexpr auto lc_make_float{i}x{i}(lc_float{t}x{t} m) noexcept {{ return lc_float{i}x{i}{{{', '.join(f'lc_make_float{i}(m[{j}])' for j in range(i))}}}; }}", + file=file) + print(file=file) + + + def generate_vector_call(name, c, types, args): + types = [{ + "s": "short", + "r": "ushort", + "i": "int", + "u": "uint", + "h": "half", + "f": "float", + "b": "bool", + "l": "long", + "z": "ulong"}[t] for t in types] + + def call(i): + e = "xyzw"[i] + return f"{c}(" + ", ".join(f"{a}.{e}" for a in args) + ")" + + for t in types: + ret = t if name not in ['isnan', 'isinf'] else 'bool' + print( + f"[[nodiscard]] __device__ inline lc_{ret} lc_{name}({', '.join(f'lc_{t} {a}' for a in args)}) noexcept {{ return {c}({', '.join(args)}); }}", + file=file) + for n in range(2, 5): + print( + f"[[nodiscard]] __device__ inline lc_{ret}{n} lc_{name}({', '.join(f'lc_{t}{n} {a}' for a in args)}) noexcept {{ return lc_make_{ret}{n}({', '.join(call(i) for i in range(n))}); }}", + file=file) + print(file=file) + + + # select + print( + "template\n[[nodiscard]] __device__ inline auto lc_select(T f, T t, bool p) noexcept { return p ? t : f; }", + file=file) + for t in ["short", "ushort", "int", "uint", "half", "float", "bool", "long", "ulong"]: + for n in range(2, 5): + print( + f"[[nodiscard]] __device__ inline auto lc_select(lc_{t}{n} f, lc_{t}{n} t, lc_bool{n} p) noexcept {{ return lc_make_{t}{n}({', '.join(f'lc_select(f.{e}, t.{e}, p.{e})' for e in 'xyzw'[:n])}); }}", + file=file) + print(file=file) + + # outer product + for t in ["float"]: + for n in range(2, 5): + print( + f"[[nodiscard]] __device__ inline auto lc_outer_product(lc_{t}{n} a, lc_{t}{n} b) noexcept {{ return lc_{t}{n}x{n}({', '.join(f'a * b.{f}' for f in 'xyzw'[:n])}); }}", + file=file) + # min/max/abs/acos/asin/asinh/acosh/atan/atanh/atan2/ + # cos/cosh/sin/sinh/tan/tanh/exp/exp2/exp10/log/log2/ + # log10/sqrt/rsqrt/ceil/floor/trunc/round/fma/copysignf/ + # isinf/isnan + generate_vector_call("min", "fminf", "f", ["a", "b"]) + generate_vector_call("min", "__hmin", "h", ["a", "b"]) + generate_vector_call("max", "fmaxf", "f", ["a", "b"]) + generate_vector_call("max", "__hmax", "h", ["a", "b"]) + generate_vector_call("abs", "fabsf", "f", ["x"]) + generate_vector_call("abs", "abs", "i", ["x"]) + generate_vector_call("abs", "llabs", "l", ["x"]) + generate_vector_call("abs", "__habs", "h", ["x"]) + + generate_vector_call("acos", "acosf", "hf", ["x"]) + generate_vector_call("asin", "asinf", "hf", ["x"]) + generate_vector_call("atan", "atanf", "hf", ["x"]) + generate_vector_call("acosh", "acoshf", "hf", ["x"]) + generate_vector_call("asinh", "asinhf", "hf", ["x"]) + generate_vector_call("atanh", "atanhf", "hf", ["x"]) + generate_vector_call("atan2", "atan2f", "hf", ["y", "x"]) + + generate_vector_call("cosh", "coshf", "hf", ["x"]) + generate_vector_call("sinh", "sinhf", "hf", ["x"]) + generate_vector_call("tanh", "tanhf", "hf", ["x"]) + + generate_vector_call("cos", "cosf", "hf", ["x"]) + generate_vector_call("sin", "sinf", "hf", ["x"]) + generate_vector_call("tan", "tanf", "hf", ["x"]) + generate_vector_call("exp", "expf", "hf", ["x"]) + generate_vector_call("exp2", "exp2f", "f", ["x"]) + generate_vector_call("exp2", "hexp2", "h", ["x"]) + generate_vector_call("exp10", "exp10f", "hf", ["x"]) + generate_vector_call("log", "logf", "hf", ["x"]) + generate_vector_call("log2", "log2f", "hf", ["x"]) + generate_vector_call("log10", "log10f", "hf", ["x"]) + generate_vector_call("pow", "powf_impl", "hf", ["x", "a"]) + generate_vector_call("powi", "powi_impl", "hf", ["x", "a"]) + + generate_vector_call("sqrt", "sqrtf", "f", ["x"]) + generate_vector_call("sqrt", "hsqrt", "h", ["x"]) + + generate_vector_call("rsqrt", "rsqrtf", "f", ["x"]) + generate_vector_call("rsqrt", "hrsqrt", "h", ["x"]) + + generate_vector_call("ceil", "ceilf", "f", ["x"]) + generate_vector_call("ceil", "hceil", "h", ["x"]) + + generate_vector_call("floor", "floorf", "f", ["x"]) + generate_vector_call("floor", "hfloor", "h", ["x"]) + + generate_vector_call("trunc", "truncf", "f", ["x"]) + generate_vector_call("trunc", "htrunc", "h", ["x"]) + + generate_vector_call("round", "rintf", "hf", ["x"]) + + generate_vector_call("fma", "fmaf", "f", ["x", "y", "z"]) + generate_vector_call("fma", "__hfma", "h", ["x", "y", "z"]) + + print(""" +[[nodiscard]] __device__ inline auto lc_copysign_impl(lc_half x, lc_half y) noexcept { + auto ux = __half_as_short(x); + auto uy = __half_as_short(y); + return __short_as_half((ux & 0x7fffu) | (uy & 0x8000u)); +}""", file=file) + + generate_vector_call("copysign", "copysignf", "f", ["x", "y"]) + generate_vector_call("copysign", "lc_copysign_impl", "h", ["x", "y"]) + + generate_vector_call("isinf", "isinf_impl", "f", ["x"]) + generate_vector_call("isnan", "isnan_impl", "f", ["x"]) + generate_vector_call("isinf", "__hisinf", "h", ["x"]) + generate_vector_call("isnan", "__hisnan", "h", ["x"]) + # TODO: half + + # reduce operations + for t in ["short", "ushort", "int", "uint", "half", "float", "long", "ulong"]: + for n in range(2, 5): + print( + f"[[nodiscard]] __device__ inline auto lc_reduce_sum(lc_{t}{n} v) noexcept {{ return lc_{t}({'+'.join(f'v.{e}' for e in 'xyzw'[:n])}); }}", + file=file) + print( + f"[[nodiscard]] __device__ inline auto lc_reduce_prod(lc_{t}{n} v) noexcept {{ return lc_{t}({'*'.join(f'v.{e}' for e in 'xyzw'[:n])}); }}", + file=file) + print( + f"[[nodiscard]] __device__ inline auto lc_reduce_min(lc_{t}{n} v) noexcept {{ return lc_{t}({', '.join(f'lc_min(v.{e}' for e in 'xyzw'[:n - 1])}, v.{'xyzw'[n - 1]}{')' * (n)}; }}", + file=file) + print( + f"[[nodiscard]] __device__ inline auto lc_reduce_max(lc_{t}{n} v) noexcept {{ return lc_{t}({', '.join(f'lc_max(v.{e}' for e in 'xyzw'[:n - 1])}, v.{'xyzw'[n - 1]}{')' * (n)}; }}", + file=file) + + # min/max for int + for t in ["short", "ushort", "int", "uint", "long", "ulong"]: + # lc_min_impl/lc_max_impl + print( + f"[[nodiscard]] __device__ inline auto lc_min_impl(lc_{t} a, lc_{t} b) noexcept {{ return a < b ? a : b; }}", + file=file) + print( + f"[[nodiscard]] __device__ inline auto lc_max_impl(lc_{t} a, lc_{t} b) noexcept {{ return a > b ? a : b; }}", + file=file) + generate_vector_call("min", "lc_min_impl", "sriulz", ["a", "b"]) + generate_vector_call("max", "lc_max_impl", "sriulz", ["a", "b"]) + + # clamp + for t in ["short", "ushort", "int", "uint", "half", "float", "long", "ulong"]: + print( + f"[[nodiscard]] __device__ inline auto lc_clamp_impl(lc_{t} v, lc_{t} lo, lc_{t} hi) noexcept {{ return lc_min(lc_max(v, lo), hi); }}", + file=file) + generate_vector_call("clamp", "lc_clamp_impl", + "sriulzhf", ["v", "lo", "hi"]) + + for t in ["half", "float"]: + # lerp + print( + f"[[nodiscard]] __device__ inline auto lc_lerp_impl(lc_{t} a, lc_{t} b, lc_{t} t) noexcept {{ return t * (b - a) + a; }}", + file=file) + + # saturate + print( + f"[[nodiscard]] __device__ inline auto lc_saturate(lc_{t} x) noexcept {{ return lc_clamp(x, lc_{t}(0.0f), lc_{t}(1.0f)); }}", + file=file) + for n in range(2, 5): + print( + f"[[nodiscard]] __device__ inline auto lc_saturate(lc_{t}{n} x) noexcept {{ return lc_clamp(x, lc_make_{t}{n}(0.0f), lc_make_{t}{n}(1.0f)); }}", + file=file) + print(file=file) + + # degrees/radians + print( + f"[[nodiscard]] __device__ inline auto lc_degrees_impl(lc_{t} rad) noexcept {{ return rad * (lc_{t})(180.0f * 0.318309886183790671537767526745028724f); }}", + file=file) + print( + f"[[nodiscard]] __device__ inline auto lc_radians_impl(lc_{t} deg) noexcept {{ return deg * (lc_{t})(3.14159265358979323846264338327950288f / 180.0f); }}", + file=file) + + # step + print( + f"[[nodiscard]] __device__ inline auto lc_step_impl(lc_{t} edge, lc_{t} x) noexcept {{ return lc_select(lc_{t}(1.f), lc_{t}(0.f), x < edge); }}", + file=file) + + # smoothstep + print( + f"""[[nodiscard]] __device__ inline auto lc_smoothstep_impl(lc_{t} edge0, lc_{t} edge1, lc_{t} x) noexcept {{ + auto t = lc_clamp((x - edge0) / (edge1 - edge0), lc_{t}(0.0f), lc_{t}(1.0f)); + return t * t * (lc_{t}(3.f) - lc_{t}(2.f) * t); +}}""", + file=file) + + # mod + print( + f"[[nodiscard]] __device__ inline auto lc_mod_impl(lc_{t} x, lc_{t} y) noexcept {{ return x - y * lc_floor(x / y); }}", + file=file) + + # fmod + if t == "half": + print( + f"[[nodiscard]] __device__ inline auto lc_fmod_impl(lc_{t} x, lc_{t} y) noexcept {{ return x - y * lc_trunc(x / y); }}", + file=file) + else: + print( + f"[[nodiscard]] __device__ inline auto lc_fmod_impl(lc_{t} x, lc_{t} y) noexcept {{ return fmodf(x, y); }}", + file=file) + + # fract + print( + f"[[nodiscard]] __device__ inline auto lc_fract_impl(lc_{t} x) noexcept {{ return x - lc_floor(x); }}", + file=file) + + generate_vector_call("lerp", "lc_lerp_impl", "hf", ["a", "b", "t"]) + generate_vector_call("degrees", "lc_degrees_impl", "hf", ["rad"]) + generate_vector_call("radians", "lc_radians_impl", "hf", ["deg"]) + generate_vector_call("step", "lc_step_impl", "hf", ["edge", "x"]) + generate_vector_call("smoothstep", "lc_smoothstep_impl", "hf", ["e0", "e1", "x"]) + generate_vector_call("mod", "lc_mod_impl", "hf", ["x", "y"]) + generate_vector_call("fmod", "lc_fmod_impl", "hf", ["x", "y"]) + generate_vector_call("fract", "lc_fract_impl", "hf", ["x"]) + + # clz/popcount/reverse + generate_vector_call("clz", "__clz", "u", ["x"]) + generate_vector_call("clz", "__clzll", "z", ["x"]) + generate_vector_call("popcount", "__popc", "u", ["x"]) + generate_vector_call("popcount", "__popcll", "z", ["x"]) + generate_vector_call("reverse", "__brev", "u", ["x"]) + generate_vector_call("reverse", "__brevll", "z", ["x"]) + + # ctz + print( + f"[[nodiscard]] __device__ inline auto lc_ctz_impl(lc_uint x) noexcept {{ return (__ffs(x) - 1u) % 32u; }}", + file=file) + print( + f"[[nodiscard]] __device__ inline auto lc_ctz_impl(lc_ulong x) noexcept {{ return (__ffsll(x) - 1u) % 64u; }}", + file=file) + generate_vector_call("ctz", "lc_ctz_impl", "uz", ["x"]) + + for t in ["float", "half"]: + # cross + print(f"""[[nodiscard]] __device__ inline constexpr auto lc_cross(lc_{t}3 u, lc_{t}3 v) noexcept {{ + return lc_make_{t}3(u.y * v.z - v.y * u.z, + u.z * v.x - v.z * u.x, + u.x * v.y - v.x * u.y); +}}""", file=file) + print(file=file) + + # dot + print(f"""[[nodiscard]] __device__ inline auto lc_dot(lc_{t}2 a, lc_{t}2 b) noexcept {{ + return a.x * b.x + a.y * b.y; +}}""", file=file) + print(f"""[[nodiscard]] __device__ inline auto lc_dot(lc_{t}3 a, lc_{t}3 b) noexcept {{ + return a.x * b.x + a.y * b.y + a.z * b.z; +}}""", file=file) + print(f"""[[nodiscard]] __device__ inline auto lc_dot(lc_{t}4 a, lc_{t}4 b) noexcept {{ + return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; +}}""", file=file) + print(file=file) + + # length + print( + f"[[nodiscard]] __device__ inline auto lc_length(lc_{t}2 v) noexcept {{ return lc_sqrt(lc_dot(v, v)); }}", + file=file) + print( + f"[[nodiscard]] __device__ inline auto lc_length(lc_{t}3 v) noexcept {{ return lc_sqrt(lc_dot(v, v)); }}", + file=file) + print( + f"[[nodiscard]] __device__ inline auto lc_length(lc_{t}4 v) noexcept {{ return lc_sqrt(lc_dot(v, v)); }}", + file=file) + print(file=file) + + # length_squared + for n in range(2, 5): + print( + f"[[nodiscard]] __device__ inline auto lc_length_squared(lc_{t}{n} v) noexcept {{ return lc_dot(v, v); }}", + file=file) + print(file=file) + + # distance + for n in range(2, 5): + print( + f"[[nodiscard]] __device__ inline auto lc_distance(lc_{t}{n} a, lc_{t}{n} b) noexcept {{ return lc_length(a - b); }}", + file=file) + print(file=file) + + # distance_squared + for n in range(2, 5): + print( + f"[[nodiscard]] __device__ inline auto lc_distance_squared(lc_{t}{n} a, lc_{t}{n} b) noexcept {{ return lc_length_squared(a - b); }}", + file=file) + print(file=file) + + # faceforward + print( + f"[[nodiscard]] __device__ inline auto lc_faceforward(lc_{t}3 n, lc_{t}3 i, lc_{t}3 n_ref) noexcept {{ return lc_select(-n, n, lc_dot(n_ref, i) < lc_{t}(0.f)); }}", + file=file) + print(file=file) + + # normalize + for n in range(2, 5): + print( + f"[[nodiscard]] __device__ inline auto lc_normalize(lc_{t}{n} v) noexcept {{ return v * lc_rsqrt(lc_dot(v, v)); }}", + file=file) + print(file=file) + + # transpose + print("""[[nodiscard]] __device__ inline constexpr auto lc_transpose(const lc_float2x2 m) noexcept { return lc_make_float2x2(m[0].x, m[1].x, m[0].y, m[1].y); } +[[nodiscard]] __device__ inline constexpr auto lc_transpose(const lc_float3x3 m) noexcept { return lc_make_float3x3(m[0].x, m[1].x, m[2].x, m[0].y, m[1].y, m[2].y, m[0].z, m[1].z, m[2].z); } +[[nodiscard]] __device__ inline constexpr auto lc_transpose(const lc_float4x4 m) noexcept { return lc_make_float4x4(m[0].x, m[1].x, m[2].x, m[3].x, m[0].y, m[1].y, m[2].y, m[3].y, m[0].z, m[1].z, m[2].z, m[3].z, m[0].w, m[1].w, m[2].w, m[3].w); } +""", file=file) + + # determinant/inverse + print("""[[nodiscard]] __device__ inline constexpr auto lc_determinant(const lc_float2x2 m) noexcept { + return m[0][0] * m[1][1] - m[1][0] * m[0][1]; +} + +[[nodiscard]] __device__ constexpr auto lc_determinant(const lc_float3x3 m) noexcept {// from GLM + return m[0].x * (m[1].y * m[2].z - m[2].y * m[1].z) + - m[1].x * (m[0].y * m[2].z - m[2].y * m[0].z) + + m[2].x * (m[0].y * m[1].z - m[1].y * m[0].z); +} + +[[nodiscard]] __device__ inline constexpr auto lc_determinant(const lc_float4x4 m) noexcept {// from GLM + const auto coef00 = m[2].z * m[3].w - m[3].z * m[2].w; + const auto coef02 = m[1].z * m[3].w - m[3].z * m[1].w; + const auto coef03 = m[1].z * m[2].w - m[2].z * m[1].w; + const auto coef04 = m[2].y * m[3].w - m[3].y * m[2].w; + const auto coef06 = m[1].y * m[3].w - m[3].y * m[1].w; + const auto coef07 = m[1].y * m[2].w - m[2].y * m[1].w; + const auto coef08 = m[2].y * m[3].z - m[3].y * m[2].z; + const auto coef10 = m[1].y * m[3].z - m[3].y * m[1].z; + const auto coef11 = m[1].y * m[2].z - m[2].y * m[1].z; + const auto coef12 = m[2].x * m[3].w - m[3].x * m[2].w; + const auto coef14 = m[1].x * m[3].w - m[3].x * m[1].w; + const auto coef15 = m[1].x * m[2].w - m[2].x * m[1].w; + const auto coef16 = m[2].x * m[3].z - m[3].x * m[2].z; + const auto coef18 = m[1].x * m[3].z - m[3].x * m[1].z; + const auto coef19 = m[1].x * m[2].z - m[2].x * m[1].z; + const auto coef20 = m[2].x * m[3].y - m[3].x * m[2].y; + const auto coef22 = m[1].x * m[3].y - m[3].x * m[1].y; + const auto coef23 = m[1].x * m[2].y - m[2].x * m[1].y; + const auto fac0 = lc_make_float4(coef00, coef00, coef02, coef03); + const auto fac1 = lc_make_float4(coef04, coef04, coef06, coef07); + const auto fac2 = lc_make_float4(coef08, coef08, coef10, coef11); + const auto fac3 = lc_make_float4(coef12, coef12, coef14, coef15); + const auto fac4 = lc_make_float4(coef16, coef16, coef18, coef19); + const auto fac5 = lc_make_float4(coef20, coef20, coef22, coef23); + const auto Vec0 = lc_make_float4(m[1].x, m[0].x, m[0].x, m[0].x); + const auto Vec1 = lc_make_float4(m[1].y, m[0].y, m[0].y, m[0].y); + const auto Vec2 = lc_make_float4(m[1].z, m[0].z, m[0].z, m[0].z); + const auto Vec3 = lc_make_float4(m[1].w, m[0].w, m[0].w, m[0].w); + const auto inv0 = Vec1 * fac0 - Vec2 * fac1 + Vec3 * fac2; + const auto inv1 = Vec0 * fac0 - Vec2 * fac3 + Vec3 * fac4; + const auto inv2 = Vec0 * fac1 - Vec1 * fac3 + Vec3 * fac5; + const auto inv3 = Vec0 * fac2 - Vec1 * fac4 + Vec2 * fac5; + constexpr auto sign_a = lc_make_float4(+1.0f, -1.0f, +1.0f, -1.0f); + constexpr auto sign_b = lc_make_float4(-1.0f, +1.0f, -1.0f, +1.0f); + const auto inv_0 = inv0 * sign_a; + const auto inv_1 = inv1 * sign_b; + const auto inv_2 = inv2 * sign_a; + const auto inv_3 = inv3 * sign_b; + const auto dot0 = m[0] * lc_make_float4(inv_0.x, inv_1.x, inv_2.x, inv_3.x); + return dot0.x + dot0.y + dot0.z + dot0.w; +} + +[[nodiscard]] __device__ inline constexpr auto lc_inverse(const lc_float2x2 m) noexcept { + const auto one_over_determinant = 1.0f / (m[0][0] * m[1][1] - m[1][0] * m[0][1]); + return lc_make_float2x2(m[1][1] * one_over_determinant, + - m[0][1] * one_over_determinant, + - m[1][0] * one_over_determinant, + + m[0][0] * one_over_determinant); +} + +[[nodiscard]] __device__ inline constexpr auto lc_inverse(const lc_float3x3 m) noexcept {// from GLM + const auto one_over_determinant = 1.0f + / (m[0].x * (m[1].y * m[2].z - m[2].y * m[1].z) + - m[1].x * (m[0].y * m[2].z - m[2].y * m[0].z) + + m[2].x * (m[0].y * m[1].z - m[1].y * m[0].z)); + return lc_make_float3x3( + (m[1].y * m[2].z - m[2].y * m[1].z) * one_over_determinant, + (m[2].y * m[0].z - m[0].y * m[2].z) * one_over_determinant, + (m[0].y * m[1].z - m[1].y * m[0].z) * one_over_determinant, + (m[2].x * m[1].z - m[1].x * m[2].z) * one_over_determinant, + (m[0].x * m[2].z - m[2].x * m[0].z) * one_over_determinant, + (m[1].x * m[0].z - m[0].x * m[1].z) * one_over_determinant, + (m[1].x * m[2].y - m[2].x * m[1].y) * one_over_determinant, + (m[2].x * m[0].y - m[0].x * m[2].y) * one_over_determinant, + (m[0].x * m[1].y - m[1].x * m[0].y) * one_over_determinant); +} + +[[nodiscard]] __device__ inline constexpr auto lc_inverse(const lc_float4x4 m) noexcept {// from GLM + const auto coef00 = m[2].z * m[3].w - m[3].z * m[2].w; + const auto coef02 = m[1].z * m[3].w - m[3].z * m[1].w; + const auto coef03 = m[1].z * m[2].w - m[2].z * m[1].w; + const auto coef04 = m[2].y * m[3].w - m[3].y * m[2].w; + const auto coef06 = m[1].y * m[3].w - m[3].y * m[1].w; + const auto coef07 = m[1].y * m[2].w - m[2].y * m[1].w; + const auto coef08 = m[2].y * m[3].z - m[3].y * m[2].z; + const auto coef10 = m[1].y * m[3].z - m[3].y * m[1].z; + const auto coef11 = m[1].y * m[2].z - m[2].y * m[1].z; + const auto coef12 = m[2].x * m[3].w - m[3].x * m[2].w; + const auto coef14 = m[1].x * m[3].w - m[3].x * m[1].w; + const auto coef15 = m[1].x * m[2].w - m[2].x * m[1].w; + const auto coef16 = m[2].x * m[3].z - m[3].x * m[2].z; + const auto coef18 = m[1].x * m[3].z - m[3].x * m[1].z; + const auto coef19 = m[1].x * m[2].z - m[2].x * m[1].z; + const auto coef20 = m[2].x * m[3].y - m[3].x * m[2].y; + const auto coef22 = m[1].x * m[3].y - m[3].x * m[1].y; + const auto coef23 = m[1].x * m[2].y - m[2].x * m[1].y; + const auto fac0 = lc_make_float4(coef00, coef00, coef02, coef03); + const auto fac1 = lc_make_float4(coef04, coef04, coef06, coef07); + const auto fac2 = lc_make_float4(coef08, coef08, coef10, coef11); + const auto fac3 = lc_make_float4(coef12, coef12, coef14, coef15); + const auto fac4 = lc_make_float4(coef16, coef16, coef18, coef19); + const auto fac5 = lc_make_float4(coef20, coef20, coef22, coef23); + const auto Vec0 = lc_make_float4(m[1].x, m[0].x, m[0].x, m[0].x); + const auto Vec1 = lc_make_float4(m[1].y, m[0].y, m[0].y, m[0].y); + const auto Vec2 = lc_make_float4(m[1].z, m[0].z, m[0].z, m[0].z); + const auto Vec3 = lc_make_float4(m[1].w, m[0].w, m[0].w, m[0].w); + const auto inv0 = Vec1 * fac0 - Vec2 * fac1 + Vec3 * fac2; + const auto inv1 = Vec0 * fac0 - Vec2 * fac3 + Vec3 * fac4; + const auto inv2 = Vec0 * fac1 - Vec1 * fac3 + Vec3 * fac5; + const auto inv3 = Vec0 * fac2 - Vec1 * fac4 + Vec2 * fac5; + constexpr auto sign_a = lc_make_float4(+1.0f, -1.0f, +1.0f, -1.0f); + constexpr auto sign_b = lc_make_float4(-1.0f, +1.0f, -1.0f, +1.0f); + const auto inv_0 = inv0 * sign_a; + const auto inv_1 = inv1 * sign_b; + const auto inv_2 = inv2 * sign_a; + const auto inv_3 = inv3 * sign_b; + const auto dot0 = m[0] * lc_make_float4(inv_0.x, inv_1.x, inv_2.x, inv_3.x); + const auto dot1 = dot0.x + dot0.y + dot0.z + dot0.w; + const auto one_over_determinant = 1.0f / dot1; + return lc_make_float4x4(inv_0 * one_over_determinant, + inv_1 * one_over_determinant, + inv_2 * one_over_determinant, + inv_3 * one_over_determinant); +} + +[[nodiscard]] __device__ inline auto lc_reflect(const lc_float3 v, const lc_float3 n) noexcept { + return v - 2.0f * lc_dot(v, n) * n; +} + +template +[[nodiscard]] __device__ inline auto lc_bit_cast(S s) noexcept { + static_assert(sizeof(D) == sizeof(S)); + return reinterpret_cast(s); +} +template +[[nodiscard]] __device__ inline constexpr auto lc_zero() noexcept { + return T{}; +} +template +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return T::one(); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_int(1); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_float(1.0f); +} +template<> +[[nodiscard]] __device__ inline auto lc_one() noexcept { + return lc_half(1.0f); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_uint(1u); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_long(1); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_ulong(1); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_short(1); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_ushort(1); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_byte(1); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return lc_ubyte(1); +} +template<> +[[nodiscard]] __device__ inline constexpr auto lc_one() noexcept { + return true; +} +template +class lc_array { + +private: + T _data[N]; + +public: + template + __device__ constexpr lc_array(Elem... elem) noexcept : _data{elem...} {} + __device__ constexpr lc_array(lc_array &&) noexcept = default; + __device__ constexpr lc_array(const lc_array &) noexcept = default; + __device__ constexpr lc_array &operator=(lc_array &&) noexcept = default; + __device__ constexpr lc_array &operator=(const lc_array &) noexcept = default; + [[nodiscard]] __device__ T &operator[](size_t i) noexcept { return _data[i]; } + [[nodiscard]] __device__ T operator[](size_t i) const noexcept { return _data[i]; } + +public: + [[nodiscard]] __device__ static auto one() noexcept { + lc_array ret; + #pragma unroll + for (auto i = 0u; i < N; i++) { ret[i] = lc_one(); } + return ret; + } +}; + +[[nodiscard]] __device__ inline auto lc_mat_comp_mul(lc_float2x2 lhs, lc_float2x2 rhs) noexcept { + return lc_make_float2x2(lhs[0] * rhs[0], + lhs[1] * rhs[1]); +} + +[[nodiscard]] __device__ inline auto lc_mat_comp_mul(lc_float3x3 lhs, lc_float3x3 rhs) noexcept { + return lc_make_float3x3(lhs[0] * rhs[0], + lhs[1] * rhs[1], + lhs[2] * rhs[2]); +} + +[[nodiscard]] __device__ inline auto lc_mat_comp_mul(lc_float4x4 lhs, lc_float4x4 rhs) noexcept { + return lc_make_float4x4(lhs[0] * rhs[0], + lhs[1] * rhs[1], + lhs[2] * rhs[2], + lhs[3] * rhs[3]); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float2 v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float3 v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float4 v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half2 v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half3 v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_half4 v) noexcept { + return lc_select(v, lc_zero(), lc_isnan(v) | lc_isinf(v)); +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float2x2 v) noexcept { + v.cols[0] = lc_remove_nan(v.cols[0]); + v.cols[1] = lc_remove_nan(v.cols[1]); + return v; +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float3x3 v) noexcept { + v.cols[0] = lc_remove_nan(v.cols[0]); + v.cols[1] = lc_remove_nan(v.cols[1]); + v.cols[2] = lc_remove_nan(v.cols[2]); + return v; +} +[[nodiscard]] __device__ inline constexpr auto lc_remove_nan(lc_float4x4 v) noexcept { + v.cols[0] = lc_remove_nan(v.cols[0]); + v.cols[1] = lc_remove_nan(v.cols[1]); + v.cols[2] = lc_remove_nan(v.cols[2]); + v.cols[3] = lc_remove_nan(v.cols[3]); + return v; +} +""", file=file) + # accumlate_grad(T*, const T) for all types + float_types = [ + "lc_float", + "lc_float2x2", "lc_float3x3", "lc_float4x4", + "lc_float2", "lc_float3", "lc_float4", + "lc_half", "lc_half2", "lc_half3", "lc_half4", + ] + for t in float_types: + print( + f"__device__ inline void lc_accumulate_grad({t} *dst, {t} grad) noexcept {{ *dst = *dst + lc_remove_nan(grad); }}", + file=file) + non_differentiable_types = [ + "lc_short", "lc_ushort", "lc_int", "lc_uint", "lc_long", "lc_ulong", "lc_bool",'lc_byte', 'lc_ubyte', + 'lc_byte2', 'lc_byte3', 'lc_byte4', + 'lc_ubyte2', 'lc_ubyte3', 'lc_ubyte4', + "lc_short2", "lc_short3", "lc_short4", + "lc_ushort2", "lc_ushort3", "lc_ushort4", + "lc_int2", "lc_int3", "lc_int4", + "lc_uint2", "lc_uint3", "lc_uint4", + "lc_long2", "lc_long3", "lc_long4", + "lc_ulong2", "lc_ulong3", "lc_ulong4", + "lc_bool2", "lc_bool3", "lc_bool4", + ] + for t in non_differentiable_types: + print( + f"__device__ inline void lc_accumulate_grad({t} *dst, {t} grad) noexcept {{}}", file=file) + print( + "struct lc_user_data_t{}; constexpr lc_user_data_t _lc_user_data{};", file=file) + print('''template struct element_type_{using type = void;}; +template using element_type = typename element_type_::type; +''', file=file) + + + def gen_element_type(vt, et): + print(f'''template<> struct element_type_<{vt}> {{ using type = {et}; }};''', file=file) + + + for vt in ['lc_float2', 'lc_float3', 'lc_float4']: + gen_element_type(vt, "lc_float") + for vt in ['lc_half2', 'lc_half3', 'lc_half4']: + gen_element_type(vt, "lc_half") + for vt in ['lc_short2', 'lc_short3', 'lc_short4']: + gen_element_type(vt, 'lc_short') + for vt in ['lc_ushort2', 'lc_ushort3', 'lc_ushort4']: + gen_element_type(vt, 'lc_ushort') + for vt in ['lc_byte2', 'lc_byte3', 'lc_byte4']: + gen_element_type(vt, 'lc_byte') + for vt in ['lc_ubyte2', 'lc_ubyte3', 'lc_ubyte4']: + gen_element_type(vt, 'lc_ubyte') + for vt in ['lc_int2', 'lc_int3', 'lc_int4']: + gen_element_type(vt, 'lc_int') + for vt in ['lc_uint2', 'lc_uint3', 'lc_uint4']: + gen_element_type(vt, 'lc_uint') + for vt in ['lc_long2', 'lc_long3', 'lc_long4']: + gen_element_type(vt, 'lc_long') + for vt in ['lc_ulong2', 'lc_ulong3', 'lc_ulong4']: + gen_element_type(vt, 'lc_ulong') + + print(''' +template +__device__ inline void lc_accumulate_grad(lc_array *dst, lc_array grad) noexcept { + #pragma unroll + for (auto i = 0u; i < N; i++) { lc_accumulate_grad(&(*dst)[i], grad[i]); } +}''', file=file) diff --git a/src/backends/dx/CMakeLists.txt b/src/backends/dx/CMakeLists.txt index 93555228a..17eec5b50 100644 --- a/src/backends/dx/CMakeLists.txt +++ b/src/backends/dx/CMakeLists.txt @@ -72,8 +72,10 @@ if (WIN32) target_link_libraries(luisa-compute-backend-dx PRIVATE luisa-compute-oidn-ext) endif () + set(ZLIB_USE_STATIC_LIBS ON) find_package(ZLIB) if (ZLIB_FOUND) + message(STATUS "Found ZLIB: ${ZLIB_LIBRARIES}") target_link_libraries(luisa-compute-backend-dx PRIVATE ZLIB::ZLIB) else () # use maxwell's favorite xrepo otherwise target_include_directories(luisa-compute-backend-dx PRIVATE "../../../xrepo/packages/z/zlib/port/zlib/include") diff --git a/src/backends/fallback/CMakeLists.txt b/src/backends/fallback/CMakeLists.txt new file mode 100644 index 000000000..8b27aa82e --- /dev/null +++ b/src/backends/fallback/CMakeLists.txt @@ -0,0 +1,49 @@ +find_package(LLVM CONFIG) +find_package(embree CONFIG) + +if (LLVM_FOUND AND embree_FOUND) + set(LUISA_COMPUTE_ENABLE_FALLBACK ON) + set(LC_BACKEND_FALLBACK_SRC + fallback_device.cpp + #llvm_codegen.cpp + #llvm_codegen_value.cpp + #llvm_codegen_builtin.cpp + #llvm_codegen_type.cpp + #llvm_codegen_expr.cpp + #llvm_codegen_func.cpp + #llvm_codegen_stmt.cpp + #llvm_event.cpp + #llvm_shader.cpp + thread_pool.cpp + #dirty_range.cpp + fallback_bindless_array.cpp + fallback_stream.cpp + fallback_texture.cpp + fallback_mesh.cpp + fallback_accel.cpp + fallback_texture_bc.cpp + fallback_texture_sampling.cpp + fallback_codegen.cpp + fallback_shader.cpp + fallback_buffer.cpp + ) + luisa_compute_add_backend(fallback SOURCES ${LC_BACKEND_FALLBACK_SRC}) + message(STATUS "Build with fallback backend (LLVM ${LLVM_VERSION}, Embree ${embree_VERSION})") + llvm_map_components_to_libnames(LLVM_LIBS core executionengine support orcjit nativecodegen irreader passes analysis coroutines) + target_include_directories(luisa-compute-backend-fallback PRIVATE ${LLVM_INCLUDE_DIRS}) + target_link_libraries(luisa-compute-backend-fallback PRIVATE embree ${LLVM_LIBS} luisa-compute-xir) + if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + target_compile_options(luisa-compute-backend-fallback PRIVATE + /wd4624 /wd4996 # do not complain about LLVM + /fp:fast /fp:contract /fp:except-) + else () + target_compile_options(luisa-compute-backend-fallback PRIVATE -ffast-math) + endif () + # help distinguish between embree 3 and 4 + target_compile_definitions(luisa-compute-backend-fallback PRIVATE + LUISA_COMPUTE_EMBREE_VERSION=${embree_VERSION_MAJOR}) +elseif (NOT LUISA_COMPUTE_CHECK_BACKEND_DEPENDENCIES) + message(FATAL_ERROR "LLVM or Embree not found for the fallback backend.") +else () + message(WARNING "LLVM or Embree not found. Fallback backend will not be built.") +endif () diff --git a/src/backends/fallback/fallback_accel.cpp b/src/backends/fallback/fallback_accel.cpp new file mode 100644 index 000000000..f8e88c864 --- /dev/null +++ b/src/backends/fallback/fallback_accel.cpp @@ -0,0 +1,195 @@ +// +// Created by Mike Smith on 2022/2/11. +// + +#include + +#include "fallback_mesh.h" +#include "fallback_accel.h" +#include "thread_pool.h" + +namespace luisa::compute::fallback +{ + FallbackAccel::FallbackAccel(RTCDevice device, AccelUsageHint hint) noexcept + : _handle{rtcNewScene(device)}, _device(device) + { + switch (hint) + { + case AccelUsageHint::FAST_TRACE: + rtcSetSceneBuildQuality(_handle, RTC_BUILD_QUALITY_HIGH); + rtcSetSceneFlags(_handle, RTC_SCENE_FLAG_COMPACT); + break; + case AccelUsageHint::FAST_BUILD: + rtcSetSceneBuildQuality(_handle, RTC_BUILD_QUALITY_LOW); + rtcSetSceneFlags(_handle, RTC_SCENE_FLAG_DYNAMIC); + break; + } + } + + FallbackAccel::~FallbackAccel() noexcept { rtcReleaseScene(_handle); } + + void FallbackAccel::build(ThreadPool& pool, size_t instance_count, + luisa::span mods) noexcept + { + using Mod = AccelBuildCommand::Modification; + pool.async([this, instance_count, mods = luisa::vector{mods.cbegin(), mods.cend()}]() + { + if (instance_count < _instances.size()) + { + // remove redundant geometries + for (auto i = instance_count; i < _instances.size(); i++) { rtcDetachGeometry(_handle, i); } + _instances.resize(instance_count); + } + else + { + // create new geometries + auto device = rtcGetSceneDevice(_handle); + _instances.reserve(next_pow2(instance_count)); + for (auto i = _instances.size(); i < instance_count; i++) + { + auto geometry = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_INSTANCE); + rtcSetGeometryBuildQuality(geometry, RTC_BUILD_QUALITY_HIGH); + rtcAttachGeometryByID(_handle, geometry, i); + rtcReleaseGeometry(geometry); // already moved into the scene + _instances.emplace_back().geometry = geometry; + } + } + for (auto m: mods) + { + auto geometry = _instances[m.index].geometry; + if (m.flags & Mod::flag_primitive) + { + auto fbMesh = reinterpret_cast(m.primitive); + rtcSetGeometryInstancedScene( + geometry, fbMesh->handle()); + } + if (m.flags & Mod::flag_transform) + { + std::memcpy( + _instances[m.index].affine, m.affine, sizeof(m.affine)); + } + if (m.flags & Mod::flag_visibility) + { + _instances[m.index].visible = true; + } else + { + _instances[m.index].visible = false; + } + _instances[m.index].dirty = true; + } + for (auto&& instance: _instances) + { + if (instance.dirty) + { + auto geometry = instance.geometry; + rtcSetGeometryTransform(geometry, 0u, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, instance.affine); + instance.visible ? rtcEnableGeometry(geometry) : rtcDisableGeometry(geometry); + rtcCommitGeometry(geometry); + instance.dirty = false; + } + } + rtcCommitScene(_handle); + auto error = rtcGetDeviceError(_device); + if (error != RTC_ERROR_NONE) { + printf("Embree Error: %d\n", error); + } + }); + } + + std::array FallbackAccel::_compress(float4x4 m) noexcept + { + return { + m[0].x, m[1].x, m[2].x, m[3].x, + m[0].y, m[1].y, m[2].y, m[3].y, + m[0].z, m[1].z, m[2].z, m[3].z + }; + } + + float4x4 FallbackAccel::_decompress(std::array m) noexcept + { + return luisa::make_float4x4( + m[0], m[4], m[8], 0.f, + m[1], m[5], m[9], 0.f, + m[2], m[6], m[10], 0.f, + m[3], m[7], m[11], 1.f); + } + + namespace detail + { + void accel_trace_closest(const FallbackAccel* accel, float ox, float oy, float oz, float dx, float dy, float dz, + float tmin, float tmax, uint mask, SurfaceHit* hit) noexcept + { +#if LUISA_COMPUTE_EMBREE_VERSION == 3 + RTCIntersectContext ctx{}; + rtcInitIntersectContext(&ctx); +#else + RTCRayQueryContext ctx{}; + rtcInitRayQueryContext(&ctx); + RTCIntersectArguments args{.context = &ctx}; +#endif + RTCRayHit rh{}; + rh.ray.org_x = ox; + rh.ray.org_y = oy; + rh.ray.org_z = oz; + rh.ray.dir_x = dx; + rh.ray.dir_y = dy; + rh.ray.dir_z = dz; + rh.ray.tnear = tmin; + rh.ray.tfar = tmax; + + rh.ray.mask = mask; + rh.hit.geomID = RTC_INVALID_GEOMETRY_ID; + rh.hit.primID = RTC_INVALID_GEOMETRY_ID; + rh.hit.instID[0] = RTC_INVALID_GEOMETRY_ID; + rh.ray.flags = 0; +#if LUISA_COMPUTE_EMBREE_VERSION == 3 + rtcIntersect1(accel->scene(), &ctx, &rh); +#else + rtcIntersect1(accel->scene(), &rh, &args); +#endif + hit->inst = rh.hit.instID[0]; + hit->prim = rh.hit.primID; + hit->bary = make_float2(rh.hit.u, rh.hit.v); + hit->committed_ray_t = rh.ray.tfar; + } + + bool accel_trace_any(const FallbackAccel* accel, float ox, float oy, float oz, float dx, float dy, float dz, + float tmin, float tmax, uint mask) noexcept + { +#if LUISA_COMPUTE_EMBREE_VERSION == 3 + RTCIntersectContext ctx{}; + rtcInitIntersectContext(&ctx); +#else + RTCRayQueryContext ctx{}; + rtcInitRayQueryContext(&ctx); + RTCOccludedArguments args{.context = &ctx}; +#endif + RTCRay ray{}; + ray.org_x = ox; + ray.org_y = oy; + ray.org_z = oz; + ray.dir_x = dx; + ray.dir_y = dy; + ray.dir_z = dz; + ray.tnear = tmin; + ray.tfar = tmax; + + ray.mask = mask; + ray.flags = 0; +#if LUISA_COMPUTE_EMBREE_VERSION == 3 + rtcOccluded1(accel->scene(), &ctx, &ray); +#else + rtcOccluded1(accel->scene(), &ray, &args); +#endif + return ray.tfar < 0.f; + } + } // namespace detail +} // namespace luisa::compute::fallback + +void intersect_closest_wrapper(void* accel, float ox, float oy, float oz, float dx, float dy, float dz, float tmin, + float tmax, unsigned mask, void* hit) +{ + luisa::compute::fallback::detail::accel_trace_closest( + reinterpret_cast(accel), + ox, oy, oz, dx, dy, dz, tmin, tmax, mask, reinterpret_cast(hit)); +} diff --git a/src/backends/fallback/fallback_accel.h b/src/backends/fallback/fallback_accel.h new file mode 100644 index 000000000..7ca849703 --- /dev/null +++ b/src/backends/fallback/fallback_accel.h @@ -0,0 +1,77 @@ +// +// Created by Mike Smith on 2022/2/11. +// + +#pragma once + +#include +#include +#include +#include +#include + +#include "fallback_embree.h" +#include "llvm_abi.h" + +namespace luisa { +class ThreadPool; +}// namespace luisa + +namespace luisa::compute::fallback { + +class FallbackMesh; + +class FallbackAccel { + +public: + struct alignas(16) Instance { + float affine[12]; + bool visible; + bool dirty; + uint pad; + RTCGeometry geometry; + }; + static_assert(sizeof(Instance) == 64u); + + struct alignas(16) Handle { + const FallbackAccel *accel; + Instance *instances; + }; + +private: + const RTCDevice _device; + RTCScene _handle; + mutable luisa::vector _instances; + +private: + [[nodiscard]] static std::array _compress(float4x4 m) noexcept; + [[nodiscard]] static float4x4 _decompress(std::array m) noexcept; + +public: + [[nodiscard]] RTCScene scene()const noexcept {return _handle;} + FallbackAccel(RTCDevice device, AccelUsageHint hint) noexcept; + ~FallbackAccel() noexcept; + void build(ThreadPool &pool, size_t instance_count, + luisa::span mods) noexcept; + [[nodiscard]] auto handle() const noexcept { return Handle{this, _instances.data()}; } +}; + +[[nodiscard]] void accel_trace_closest(const FallbackAccel *accel, float ox, float oy, float oz, float dx, float dy, float dz, float tmin, float tmax, uint mask, SurfaceHit* hit) noexcept; +[[nodiscard]] bool accel_trace_any(const FallbackAccel *accel, float ox, float oy, float oz, float dx, float dy, float dz, float tmin, float tmax, uint mask) noexcept; + +struct alignas(16) FallbackAccelInstance { + float affine[12]; + bool visible; + bool dirty; + uint pad; + uint geom0; + uint geom1; +}; + +}// namespace luisa::compute::fallback + +LUISA_STRUCT(luisa::compute::fallback::FallbackAccelInstance, + affine, visible, dirty, pad, geom0, geom1) {}; + +void intersect_closest_wrapper(void *accel, float ox, float oy, float oz, float dx, float dy, float dz, float tmin, float tmax, unsigned mask, void *hit); + diff --git a/src/backends/fallback/fallback_bindless_array.cpp b/src/backends/fallback/fallback_bindless_array.cpp new file mode 100644 index 000000000..55f188fc7 --- /dev/null +++ b/src/backends/fallback/fallback_bindless_array.cpp @@ -0,0 +1,41 @@ +// +// Created by Mike Smith on 2022/2/11. +// + +#include "fallback_bindless_array.h" +#include "thread_pool.h" +#include "luisa/runtime/rtx/triangle.h" +#include "luisa/rust/api_types.hpp" + +namespace luisa::compute::fallback +{ + FallbackBindlessArray::FallbackBindlessArray(size_t capacity) noexcept + : _slots(capacity), _tracker{capacity} + { + } + + + void FallbackBindlessArray::update(ThreadPool& pool, luisa::span modifications) noexcept + { + using Mod = BindlessArrayUpdateCommand::Modification; + pool.async([this,mods = luisa::vector{modifications.cbegin(), modifications.cend()}] + { + for (auto m: mods) + { + _slots[m.slot].buffer = reinterpret_cast(m.buffer.handle); + } + }); + _tracker.commit(); + } + + bool FallbackBindlessArray::uses_resource(uint64_t handle) const noexcept + { + return _tracker.contains(handle); + } +} // namespace luisa::compute::Fallback +void bindless_buffer_read(void* bindless, unsigned slot, unsigned elem, unsigned stride, void* buffer) +{ + auto a = reinterpret_cast(bindless); + auto ptr = reinterpret_cast(a->slot(slot).buffer); + memcpy(buffer, ptr + elem*stride, stride); +} diff --git a/src/backends/fallback/fallback_bindless_array.h b/src/backends/fallback/fallback_bindless_array.h new file mode 100644 index 000000000..f54952b80 --- /dev/null +++ b/src/backends/fallback/fallback_bindless_array.h @@ -0,0 +1,48 @@ +// +// Created by Mike Smith on 2022/2/11. +// + +#pragma once + +//#include +#include +#include +#include "../common/resource_tracker.h" +#include "fallback_texture.h" +#include "dirty_range.h" + +namespace luisa +{ + class ThreadPool; +} + +namespace luisa::compute::fallback { + +class FallbackBindlessArray { + +public: + + struct Slot { + const void *buffer{nullptr}; + size_t buffer_offset{}; + Sampler sampler2d{}; + Sampler sampler3d{}; + const FallbackTexture *tex2d{nullptr}; + const FallbackTexture *tex3d{nullptr}; + }; + +private: + luisa::vector _slots{}; + //DirtyRange _dirty; + ResourceTracker _tracker; + +public: + explicit FallbackBindlessArray(size_t capacity) noexcept; + auto& slot(unsigned int idx) const noexcept { return _slots[idx]; } + void update(ThreadPool &pool, luisa::span modifications) noexcept; + [[nodiscard]] bool uses_resource(uint64_t handle) const noexcept; +}; + +}// namespace luisa::compute::Fallback + +void bindless_buffer_read(void* bindless, unsigned slot, unsigned elem, unsigned stride, void* buffer); \ No newline at end of file diff --git a/src/backends/fallback/fallback_buffer.cpp b/src/backends/fallback/fallback_buffer.cpp new file mode 100644 index 000000000..5865c4e13 --- /dev/null +++ b/src/backends/fallback/fallback_buffer.cpp @@ -0,0 +1,15 @@ +// +// Created by swfly on 2024/11/21. +// + +#include +#include "fallback_buffer.h" + +namespace luisa::compute::fallback { + +FallbackBufferView FallbackBuffer::view(size_t offset) noexcept { + LUISA_ASSERT(offset <= data.size(), "Buffer view out of range."); + return {static_cast(data.data() + offset), data.size() - offset}; +} + +}// namespace luisa::compute::fallback diff --git a/src/backends/fallback/fallback_buffer.h b/src/backends/fallback/fallback_buffer.h new file mode 100644 index 000000000..dd6ca0fc5 --- /dev/null +++ b/src/backends/fallback/fallback_buffer.h @@ -0,0 +1,26 @@ +// +// Created by swfly on 2024/11/21. +// + +#pragma once + +#include + +namespace luisa::compute::fallback { +struct alignas(16) FallbackBufferView { + void *ptr; + size_t size; +}; + +class FallbackBuffer { +public: + // FIXME: size + void *addr() { return data.data(); } + [[nodiscard]] FallbackBufferView view(size_t offset) noexcept; + +private: + + std::vector data{}; +}; + +}// namespace luisa::compute::fallback diff --git a/src/backends/fallback/fallback_codegen.cpp b/src/backends/fallback/fallback_codegen.cpp new file mode 100644 index 000000000..996e5ecc8 --- /dev/null +++ b/src/backends/fallback/fallback_codegen.cpp @@ -0,0 +1,2718 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "fallback_codegen.h" + +#include "fallback_buffer.h" +#include "fallback_texture.h" + +namespace luisa::compute::fallback { + +class FallbackCodegen { +private: + struct LLVMStruct { + llvm::StructType *type = nullptr; + luisa::vector padded_field_indices; + }; + + using IRBuilder = llvm::IRBuilder<>; + + struct CurrentFunction { + llvm::Function *func = nullptr; + luisa::unordered_map value_map; + luisa::unordered_set translated_basic_blocks; + + // builtin variables +#define LUISA_FALLBACK_BACKEND_DECL_BUILTIN_VARIABLE(NAME, INDEX) \ + static constexpr size_t builtin_variable_index_## NAME = INDEX; + LUISA_FALLBACK_BACKEND_DECL_BUILTIN_VARIABLE(thread_id, 0) + LUISA_FALLBACK_BACKEND_DECL_BUILTIN_VARIABLE(block_id, 1) + LUISA_FALLBACK_BACKEND_DECL_BUILTIN_VARIABLE(dispatch_id, 2) + LUISA_FALLBACK_BACKEND_DECL_BUILTIN_VARIABLE(block_size, 3) + LUISA_FALLBACK_BACKEND_DECL_BUILTIN_VARIABLE(dispatch_size, 4) +#undef LUISA_FALLBACK_BACKEND_DECL_BUILTIN_VARIABLE + static constexpr size_t builtin_variable_count = 5; + llvm::Value *builtin_variables[builtin_variable_count] = {}; + }; + +private: + llvm::LLVMContext &_llvm_context; + llvm::Module *_llvm_module = nullptr; + luisa::unordered_map> _llvm_struct_types; + luisa::unordered_map _llvm_constants; + luisa::unordered_map _llvm_functions; + +private: + void _reset() noexcept { + _llvm_module = nullptr; + _llvm_struct_types.clear(); + _llvm_constants.clear(); + _llvm_functions.clear(); + } + +private: + [[nodiscard]] static llvm::StringRef _get_name_from_metadata(auto something, llvm::StringRef fallback = {}) noexcept { + auto name_md = something->template find_metadata(); + return name_md ? llvm::StringRef{name_md->name()} : fallback; + } + + [[nodiscard]] static size_t _get_type_size(const Type *t) noexcept { + LUISA_ASSERT(t != nullptr, "Type is nullptr."); + if (!t->is_resource() && !t->is_custom()) { + return t->size(); + } + switch (t->tag()) { + case Type::Tag::BUFFER: return sizeof(FallbackBufferView); + case Type::Tag::TEXTURE: return sizeof(FallbackTextureView); + case Type::Tag::BINDLESS_ARRAY: return sizeof(void *); + case Type::Tag::ACCEL: return sizeof(void *); + case Type::Tag::CUSTOM: LUISA_NOT_IMPLEMENTED(); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid type: {}.", t->description()); + } + + [[nodiscard]] static size_t _get_type_alignment(const Type *t) noexcept { + LUISA_ASSERT(t != nullptr, "Type is nullptr."); + if (!t->is_resource() && !t->is_custom()) { + return t->alignment(); + } + switch (t->tag()) { + case Type::Tag::BUFFER: return alignof(FallbackBufferView); + case Type::Tag::TEXTURE: return alignof(FallbackTextureView); + case Type::Tag::BINDLESS_ARRAY: return alignof(void *); + case Type::Tag::ACCEL: return alignof(void *); + case Type::Tag::CUSTOM: LUISA_NOT_IMPLEMENTED(); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid type: {}.", t->description()); + } + + [[nodiscard]] LLVMStruct *_translate_struct_type(const Type *t) noexcept { + auto iter = _llvm_struct_types.try_emplace(t, nullptr).first; + if (iter->second) { return iter->second.get(); } + auto struct_type = (iter->second = luisa::make_unique()).get(); + auto member_index = 0u; + llvm::SmallVector<::llvm::Type *> field_types; + luisa::vector field_indices; + size_t size = 0u; + for (auto member : t->members()) { + auto aligned_offset = luisa::align(size, _get_type_alignment(member)); + if (aligned_offset > size) { + auto byte_type = ::llvm::Type::getInt8Ty(_llvm_context); + auto padding = ::llvm::ArrayType::get(byte_type, aligned_offset - size); + field_types.emplace_back(padding); + member_index++; + } + auto member_type = _translate_type(member, false); + field_types.emplace_back(member_type); + field_indices.emplace_back(member_index++); + size = aligned_offset + _get_type_size(member); + } + if (_get_type_size(t) > size) {// last padding + auto byte_type = ::llvm::Type::getInt8Ty(_llvm_context); + auto padding = ::llvm::ArrayType::get(byte_type, _get_type_size(t) - size); + field_types.emplace_back(padding); + } + struct_type->type = ::llvm::StructType::get(_llvm_context, field_types); + struct_type->padded_field_indices = std::move(field_indices); + return struct_type; + } + + [[nodiscard]] llvm::Type *_translate_type(const Type *t, bool register_use) noexcept { + if (t == nullptr) { return llvm::Type::getVoidTy(_llvm_context); } + switch (t->tag()) { + case Type::Tag::BOOL: return llvm::Type::getInt8Ty(_llvm_context); + case Type::Tag::FLOAT16: return llvm::Type::getHalfTy(_llvm_context); + case Type::Tag::FLOAT32: return llvm::Type::getFloatTy(_llvm_context); + case Type::Tag::FLOAT64: return llvm::Type::getDoubleTy(_llvm_context); + case Type::Tag::INT8: return llvm::Type::getInt8Ty(_llvm_context); + case Type::Tag::INT16: return llvm::Type::getInt16Ty(_llvm_context); + case Type::Tag::INT32: return llvm::Type::getInt32Ty(_llvm_context); + case Type::Tag::INT64: return llvm::Type::getInt64Ty(_llvm_context); + case Type::Tag::UINT8: return llvm::Type::getInt8Ty(_llvm_context); + case Type::Tag::UINT16: return llvm::Type::getInt16Ty(_llvm_context); + case Type::Tag::UINT32: return llvm::Type::getInt32Ty(_llvm_context); + case Type::Tag::UINT64: return llvm::Type::getInt64Ty(_llvm_context); + case Type::Tag::VECTOR: { + // note: we have to pad 3-element vectors to be 4-element + auto elem_type = _translate_type(t->element(), false); + auto dim = t->dimension(); + LUISA_ASSERT(dim == 2 || dim == 3 || dim == 4, "Invalid vector dimension."); + if (register_use) { return llvm::VectorType::get(elem_type, dim, false); } + return llvm::ArrayType::get(elem_type, dim == 3 ? 4 : dim); + } + case Type::Tag::MATRIX: { + auto col_type = _translate_type(Type::vector(t->element(), t->dimension()), false); + return llvm::ArrayType::get(col_type, t->dimension()); + } + case Type::Tag::ARRAY: { + auto elem_type = _translate_type(t->element(), false); + return llvm::ArrayType::get(elem_type, t->dimension()); + } + case Type::Tag::STRUCTURE: return _translate_struct_type(t)->type; + case Type::Tag::BUFFER: { + auto llvm_ptr_type = llvm::PointerType::get(_llvm_context, 0); + auto llvm_i64_type = llvm::Type::getInt64Ty(_llvm_context); + return llvm::StructType::get(_llvm_context, {llvm_ptr_type, llvm_i64_type}); + } + case Type::Tag::TEXTURE: return llvm::VectorType::get(llvm::Type::getFloatTy(_llvm_context), 4u, false);//I don't know why but yeah a texture view is 16bytes + case Type::Tag::BINDLESS_ARRAY: return llvm::PointerType::get(_llvm_context, 0); + case Type::Tag::ACCEL: { + return llvm::PointerType::get(_llvm_context, 0); + } + case Type::Tag::CUSTOM: LUISA_NOT_IMPLEMENTED(); + } + LUISA_ERROR_WITH_LOCATION("Invalid type: {}.", t->description()); + } + + [[nodiscard]] llvm::Constant *_translate_literal(const Type *t, const void *data, bool register_use) noexcept { + auto llvm_type = _translate_type(t, register_use); + switch (t->tag()) { + case Type::Tag::BOOL: return llvm::ConstantInt::get(llvm_type, *static_cast(data)); + case Type::Tag::INT8: return llvm::ConstantInt::get(llvm_type, *static_cast(data)); + case Type::Tag::UINT8: return llvm::ConstantInt::get(llvm_type, *static_cast(data)); + case Type::Tag::INT16: return llvm::ConstantInt::get(llvm_type, *static_cast(data)); + case Type::Tag::UINT16: return llvm::ConstantInt::get(llvm_type, *static_cast(data)); + case Type::Tag::INT32: return llvm::ConstantInt::get(llvm_type, *static_cast(data)); + case Type::Tag::UINT32: return llvm::ConstantInt::get(llvm_type, *static_cast(data)); + case Type::Tag::INT64: return llvm::ConstantInt::get(llvm_type, *static_cast(data)); + case Type::Tag::UINT64: return llvm::ConstantInt::get(llvm_type, *static_cast(data)); + case Type::Tag::FLOAT16: return llvm::ConstantFP::get(llvm_type, *static_cast(data)); + case Type::Tag::FLOAT32: return llvm::ConstantFP::get(llvm_type, *static_cast(data)); + case Type::Tag::FLOAT64: return llvm::ConstantFP::get(llvm_type, *static_cast(data)); + case Type::Tag::VECTOR: { + auto elem_type = t->element(); + auto stride = _get_type_size(elem_type); + auto dim = t->dimension(); + llvm::SmallVector elements; + for (auto i = 0u; i < dim; i++) { + auto elem_data = static_cast(data) + i * stride; + elements.emplace_back(_translate_literal(elem_type, elem_data, false)); + } + // for register use, we create an immediate vector + if (register_use) { + return llvm::ConstantVector::get(elements); + } + // for memory use we have to pad 3-element vectors to 4-element + if (dim == 3) { + auto llvm_elem_type = _translate_type(t->element(), false); + auto llvm_padding = llvm::Constant::getNullValue(llvm_elem_type); + elements.emplace_back(llvm_padding); + } + return llvm::ConstantArray::get(llvm::cast(llvm_type), elements); + } + case Type::Tag::MATRIX: { + LUISA_ASSERT(llvm_type->isArrayTy(), "Matrix type should be an array type."); + auto dim = t->dimension(); + auto col_type = Type::vector(t->element(), dim); + auto col_stride = _get_type_size(col_type); + llvm::SmallVector elements; + for (auto i = 0u; i < dim; i++) { + auto col_data = static_cast(data) + i * col_stride; + elements.emplace_back(_translate_literal(col_type, col_data, false)); + } + return llvm::ConstantArray::get(llvm::cast(llvm_type), elements); + } + case Type::Tag::ARRAY: { + LUISA_ASSERT(llvm_type->isArrayTy(), "Array type should be an array type."); + auto elem_type = t->element(); + auto stride = _get_type_size(elem_type); + auto dim = t->dimension(); + llvm::SmallVector elements; + elements.reserve(dim); + for (auto i = 0u; i < dim; i++) { + auto elem_data = static_cast(data) + i * stride; + elements.emplace_back(_translate_literal(elem_type, elem_data, false)); + } + return llvm::ConstantArray::get(llvm::cast(llvm_type), elements); + } + case Type::Tag::STRUCTURE: { + auto struct_type = _translate_struct_type(t); + LUISA_ASSERT(llvm_type == struct_type->type, "Type mismatch."); + auto padded_field_types = struct_type->type->elements(); + llvm::SmallVector fields; + fields.resize(padded_field_types.size(), nullptr); + LUISA_ASSERT(t->members().size() == struct_type->padded_field_indices.size(), + "Member count mismatch."); + // fill in data fields + size_t data_offset = 0u; + for (auto i = 0u; i < t->members().size(); i++) { + auto field_type = t->members()[i]; + data_offset = luisa::align(data_offset, _get_type_alignment(field_type)); + auto field_data = static_cast(data) + data_offset; + data_offset += _get_type_size(field_type); + auto padded_index = struct_type->padded_field_indices[i]; + fields[padded_index] = _translate_literal(field_type, field_data, false); + } + // fill in padding fields + for (auto i = 0u; i < fields.size(); i++) { + if (fields[i] == nullptr) { + auto field_type = padded_field_types[i]; + LUISA_ASSERT(field_type->isArrayTy(), "Padding field should be an array type."); + fields[i] = llvm::ConstantAggregateZero::get(field_type); + } + } + return llvm::ConstantStruct::get(struct_type->type, fields); + } + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid type: {}.", t->description()); + } + + [[nodiscard]] llvm::Constant *_translate_constant(const xir::Constant *c) { + if (auto iter = _llvm_constants.find(c); iter != _llvm_constants.end()) { + return iter->second; + } + auto type = c->type(); + // we have to create a global variable for non-basic constants + auto llvm_value = _translate_literal(type, c->data(), type->is_basic()); + // promote non-basic constants to globals + if (!type->is_basic()) { + auto name = luisa::format("const{}", _llvm_constants.size()); + auto g = llvm::dyn_cast( + _llvm_module->getOrInsertGlobal(llvm::StringRef{name}, llvm_value->getType())); + g->setConstant(true); + g->setLinkage(llvm::GlobalValue::LinkageTypes::PrivateLinkage); + g->setInitializer(llvm_value); + g->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + llvm_value = g; + } + // cache + _llvm_constants.emplace(c, llvm_value); + return llvm_value; + } + + void _translate_module(const xir::Module *module) noexcept { + for (auto &f : module->functions()) { + static_cast(_translate_function(&f)); + } + } + + [[nodiscard]] llvm::Value *_lookup_value(CurrentFunction ¤t, IRBuilder &b, const xir::Value *v, bool load_global = true) noexcept { + LUISA_ASSERT(v != nullptr, "Value is null."); + switch (v->derived_value_tag()) { + case xir::DerivedValueTag::FUNCTION: { + return _translate_function(static_cast(v)); + } + case xir::DerivedValueTag::BASIC_BLOCK: { + return _find_or_create_basic_block(current, static_cast(v)); + } + case xir::DerivedValueTag::CONSTANT: { + auto c = _translate_constant(static_cast(v)); + if (load_global && c->getType()->isPointerTy()) { + auto llvm_type = _translate_type(v->type(), true); + auto alignment = _get_type_alignment(v->type()); + return b.CreateAlignedLoad(llvm_type, c, llvm::MaybeAlign{alignment}); + } + return c; + } + case xir::DerivedValueTag::INSTRUCTION: [[fallthrough]]; + case xir::DerivedValueTag::ARGUMENT: { + auto iter = current.value_map.find(v); + LUISA_ASSERT(iter != current.value_map.end(), "Value not found."); + return iter->second; + } + } + LUISA_ERROR_WITH_LOCATION("Invalid value."); + } + + [[nodiscard]] llvm::Constant *_translate_string_or_null(IRBuilder &b, luisa::string_view s) noexcept { + if (s.empty()) { + auto ptr_type = llvm::PointerType::get(_llvm_context, 0); + return llvm::ConstantPointerNull::get(ptr_type); + } + return b.CreateGlobalStringPtr(s); + } + + [[nodiscard]] llvm::Value *_translate_gep(CurrentFunction ¤t, IRBuilder &b, + const Type *expected_elem_type, + const Type *ptr_type, llvm::Value *llvm_ptr, + luisa::span indices) noexcept { + LUISA_ASSERT(llvm_ptr->getType()->isPointerTy(), "Invalid pointer type."); + while (!indices.empty()) { + // get the index + auto index = indices.front()->value(); + indices = indices.subspan(1u); + // structures need special handling + if (ptr_type->is_structure()) { + LUISA_ASSERT(index->derived_value_tag() == xir::DerivedValueTag::CONSTANT, + "Structure index should be a constant."); + auto static_index = [c = static_cast(index)]() noexcept -> uint64_t { + auto t = c->type(); + switch (t->tag()) { + case Type::Tag::INT8: return *static_cast(c->data()); + case Type::Tag::UINT8: return *static_cast(c->data()); + case Type::Tag::INT16: return *static_cast(c->data()); + case Type::Tag::UINT16: return *static_cast(c->data()); + case Type::Tag::INT32: return *static_cast(c->data()); + case Type::Tag::UINT32: return *static_cast(c->data()); + case Type::Tag::INT64: return *static_cast(c->data()); + case Type::Tag::UINT64: return *static_cast(c->data()); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid index type: {}.", t->description()); + }(); + // remap the index for padded fields + LUISA_ASSERT(static_index < ptr_type->members().size(), "Invalid structure index."); + auto llvm_struct_type = _translate_struct_type(ptr_type); + auto padded_index = llvm_struct_type->padded_field_indices[static_index]; + // index into the struct and update member type + llvm_ptr = b.CreateStructGEP(llvm_struct_type->type, llvm_ptr, padded_index); + ptr_type = ptr_type->members()[static_index]; + } else { + LUISA_ASSERT(ptr_type->is_array() || ptr_type->is_vector() || ptr_type->is_matrix(), "Invalid pointer type."); + auto llvm_index = _lookup_value(current, b, index); + auto llvm_ptr_type = _translate_type(ptr_type, false); + auto llvm_zero = b.getInt64(0); + llvm_ptr = b.CreateInBoundsGEP(llvm_ptr_type, llvm_ptr, {llvm_zero, llvm_index}); + ptr_type = ptr_type->is_matrix() ? + Type::vector(ptr_type->element(), ptr_type->dimension()) : + ptr_type->element(); + } + } + LUISA_ASSERT(ptr_type == expected_elem_type, "Type mismatch."); + return llvm_ptr; + } + + [[nodiscard]] llvm::Value *_translate_extract(CurrentFunction ¤t, IRBuilder &b, const xir::IntrinsicInst *inst) noexcept { + auto base = inst->operand(0u); + auto indices = inst->operand_uses().subspan(1u); + auto llvm_base = _lookup_value(current, b, base, false); + // if we have an immediate vector, we can directly extract elements + if (base->type()->is_vector() && !llvm_base->getType()->isPointerTy()) { + LUISA_ASSERT(indices.size() == 1u, "Immediate vector should have only one index."); + auto llvm_index = _lookup_value(current, b, indices.front()->value()); + return b.CreateExtractElement(llvm_base, llvm_index); + } + // otherwise we have to use GEP + if (!llvm_base->getType()->isPointerTy()) {// create a temporary alloca if base is not a pointer + auto llvm_base_type = _translate_type(base->type(), false); + auto llvm_temp = b.CreateAlloca(llvm_base_type); + auto alignment = _get_type_alignment(base->type()); + if (llvm_temp->getAlign() < alignment) { + llvm_temp->setAlignment(llvm::Align{alignment}); + } + b.CreateAlignedStore(llvm_base, llvm_temp, llvm::MaybeAlign{alignment}); + llvm_base = llvm_temp; + } + // GEP and load the element + auto llvm_gep = _translate_gep(current, b, inst->type(), base->type(), llvm_base, indices); + auto llvm_type = _translate_type(inst->type(), true); + return b.CreateAlignedLoad(llvm_type, llvm_gep, llvm::MaybeAlign{_get_type_alignment(inst->type())}); + } + + [[nodiscard]] llvm::Value *_translate_insert(CurrentFunction ¤t, IRBuilder &b, const xir::IntrinsicInst *inst) noexcept { + auto base = inst->operand(0u); + auto value = inst->operand(1u); + auto indices = inst->operand_uses().subspan(2u); + auto llvm_base = _lookup_value(current, b, base, false); + auto llvm_value = _lookup_value(current, b, value, false); + // if we have an immediate vector, we can directly insert elements + if (base->type()->is_vector() && !llvm_base->getType()->isPointerTy()) { + LUISA_ASSERT(indices.size() == 1u, "Immediate vector should have only one index."); + auto llvm_index = _lookup_value(current, b, indices.front()->value()); + return b.CreateInsertElement(llvm_base, llvm_value, llvm_index); + } + // otherwise we have to make a copy of the base, store the element, and load the modified value + auto llvm_base_type = _translate_type(base->type(), false); + auto llvm_temp = b.CreateAlloca(llvm_base_type); + auto alignment = _get_type_alignment(base->type()); + if (llvm_temp->getAlign() < alignment) { + llvm_temp->setAlignment(llvm::Align{alignment}); + } + // load the base if it is a pointer + if (llvm_base->getType()->isPointerTy()) { + llvm_base = b.CreateAlignedLoad(llvm_base_type, llvm_base, llvm::MaybeAlign{alignment}); + } + // store the base + b.CreateAlignedStore(llvm_base, llvm_temp, llvm::MaybeAlign{alignment}); + // GEP and store the element + auto llvm_gep = _translate_gep(current, b, value->type(), base->type(), llvm_temp, indices); + b.CreateAlignedStore(llvm_value, llvm_gep, llvm::MaybeAlign{_get_type_alignment(value->type())}); + // load the modified value + return b.CreateAlignedLoad(llvm_base_type, llvm_temp, llvm::MaybeAlign{alignment}); + } + + [[nodiscard]] llvm::Value *_translate_unary_plus(CurrentFunction ¤t, IRBuilder &b, const xir::Value *operand) noexcept { + return _lookup_value(current, b, operand); + } + + [[nodiscard]] llvm::Value *_translate_unary_minus(CurrentFunction ¤t, IRBuilder &b, const xir::Value *operand) noexcept { + auto llvm_operand = _lookup_value(current, b, operand); + auto operand_type = operand->type(); + LUISA_ASSERT(operand_type != nullptr, "Operand type is null."); + auto operand_elem_type = operand_type->is_vector() ? operand_type->element() : operand_type; + switch (operand_elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: return b.CreateNSWNeg(llvm_operand); + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: return b.CreateNeg(llvm_operand); + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: return b.CreateFNeg(llvm_operand); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid unary minus operand type: {}.", operand_type->description()); + } + + [[nodiscard]] static llvm::Value *_cmp_ne_zero(IRBuilder &b, llvm::Value *value) noexcept { + auto zero = llvm::Constant::getNullValue(value->getType()); + return value->getType()->isFPOrFPVectorTy() ? + b.CreateFCmpUNE(value, zero) : + b.CreateICmpNE(value, zero); + } + + [[nodiscard]] static llvm::Value *_cmp_eq_zero(IRBuilder &b, llvm::Value *value) noexcept { + auto zero = llvm::Constant::getNullValue(value->getType()); + return value->getType()->isFPOrFPVectorTy() ? + b.CreateFCmpUEQ(value, zero) : + b.CreateICmpEQ(value, zero); + } + + [[nodiscard]] static llvm::Value *_zext_i1_to_i8(IRBuilder &b, llvm::Value *value) noexcept { + LUISA_DEBUG_ASSERT(value->getType()->isIntOrIntVectorTy(1), "Invalid value type."); + auto i8_type = llvm::cast(llvm::Type::getInt8Ty(b.getContext())); + if (value->getType()->isVectorTy()) { + auto vec_type = llvm::cast(value->getType()); + i8_type = llvm::VectorType::get(i8_type, vec_type->getElementCount()); + } + return b.CreateZExt(value, i8_type); + } + + [[nodiscard]] llvm::Value *_translate_unary_logic_not(CurrentFunction ¤t, IRBuilder &b, const xir::Value *operand) noexcept { + auto llvm_operand = _lookup_value(current, b, operand); + auto operand_type = operand->type(); + LUISA_ASSERT(operand_type != nullptr, "Operand type is null."); + LUISA_ASSERT(operand_type->is_scalar() || operand_type->is_vector(), "Invalid operand type."); + auto llvm_cmp = _cmp_eq_zero(b, llvm_operand); + return _zext_i1_to_i8(b, llvm_cmp); + } + + [[nodiscard]] llvm::Value *_translate_unary_bit_not(CurrentFunction ¤t, IRBuilder &b, const xir::Value *operand) noexcept { + auto llvm_operand = _lookup_value(current, b, operand); + LUISA_ASSERT(llvm_operand->getType()->isIntOrIntVectorTy() && + !llvm_operand->getType()->isIntOrIntVectorTy(1), + "Invalid operand type."); + return b.CreateNot(llvm_operand); + } + + [[nodiscard]] llvm::Value *_translate_binary_add(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + LUISA_ASSERT(lhs->type() == rhs->type(), "Type mismatch."); + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: return b.CreateNSWAdd(llvm_lhs, llvm_rhs); + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: return b.CreateAdd(llvm_lhs, llvm_rhs); + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: return b.CreateFAdd(llvm_lhs, llvm_rhs); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid binary add operand type: {}.", elem_type->description()); + } + + //swfly tries to write more binary operations + [[nodiscard]] llvm::Value *_translate_binary_sub(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + LUISA_ASSERT(lhs->type() == rhs->type(), "Type mismatch."); + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: return b.CreateNSWSub(llvm_lhs, llvm_rhs); + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: return b.CreateSub(llvm_lhs, llvm_rhs); + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: return b.CreateFSub(llvm_lhs, llvm_rhs); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid binary sub operand type: {}.", elem_type->description()); + } + + [[nodiscard]] llvm::Value *_translate_binary_mul(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + LUISA_ASSERT(lhs->type() == rhs->type(), "Type mismatch."); + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: return b.CreateNSWMul(llvm_lhs, llvm_rhs); + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: return b.CreateMul(llvm_lhs, llvm_rhs); + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: return b.CreateFMul(llvm_lhs, llvm_rhs); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid binary mul operand type: {}.", elem_type->description()); + } + + [[nodiscard]] llvm::Value *_translate_binary_div(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + LUISA_ASSERT(lhs->type() == rhs->type(), "Type mismatch."); + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: return b.CreateSDiv(llvm_lhs, llvm_rhs); + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: return b.CreateUDiv(llvm_lhs, llvm_rhs); + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: return b.CreateFDiv(llvm_lhs, llvm_rhs); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid binary add operand type: {}.", elem_type->description()); + } + + [[nodiscard]] llvm::Value *_translate_binary_mod(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + LUISA_ASSERT(lhs->type() == rhs->type(), "Type mismatch."); + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: return b.CreateSRem(llvm_lhs, llvm_rhs);// Signed integer remainder + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: return b.CreateURem(llvm_lhs, llvm_rhs);// Unsigned integer remainder + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid binary mod operand type: {}.", elem_type->description()); + } + + [[nodiscard]] llvm::Value *_translate_binary_logic_and(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + // Lookup LLVM values for operands + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto lhs_type = lhs->type(); + auto rhs_type = rhs->type(); + // Type and null checks + LUISA_ASSERT(lhs_type != nullptr && rhs_type != nullptr, "Operand type is null."); + LUISA_ASSERT(lhs_type == rhs_type, "Type mismatch for logic and."); + LUISA_ASSERT(lhs_type->is_scalar() || lhs_type->is_vector(), "Invalid operand type."); + LUISA_ASSERT(rhs_type->is_scalar() || rhs_type->is_vector(), "Invalid operand type."); + // Convert operands to boolean values (non-zero becomes true, zero becomes false) + auto llvm_lhs_bool = _cmp_ne_zero(b, llvm_lhs); + auto llvm_rhs_bool = _cmp_ne_zero(b, llvm_rhs); + // Perform logical AND (a && b) + auto llvm_and_result = b.CreateAnd(llvm_lhs_bool, llvm_rhs_bool); + // Convert result to i8 for consistency with your implementation needs + return _zext_i1_to_i8(b, llvm_and_result); + } + + [[nodiscard]] llvm::Value *_translate_binary_logic_or(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + // Lookup LLVM values for operands + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto lhs_type = lhs->type(); + auto rhs_type = rhs->type(); + // Type and null checks + LUISA_ASSERT(lhs_type != nullptr && rhs_type != nullptr, "Operand type is null."); + LUISA_ASSERT(lhs_type == rhs_type, "Type mismatch for logic and."); + LUISA_ASSERT(lhs_type->is_scalar() || lhs_type->is_vector(), "Invalid operand type."); + LUISA_ASSERT(rhs_type->is_scalar() || rhs_type->is_vector(), "Invalid operand type."); + // Convert operands to boolean values (non-zero becomes true, zero becomes false) + auto llvm_lhs_bool = _cmp_ne_zero(b, llvm_lhs); + auto llvm_rhs_bool = _cmp_ne_zero(b, llvm_rhs); + // Perform logical OR (a && b) + auto llvm_or_result = b.CreateOr(llvm_lhs_bool, llvm_rhs_bool); + // Convert result to i8 for consistency with your implementation needs + return _zext_i1_to_i8(b, llvm_or_result); + } + + [[nodiscard]] llvm::Value *_translate_binary_bit_and(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + // Lookup LLVM values for operands + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto lhs_type = lhs->type(); + auto rhs_type = rhs->type(); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + // Type and null checks + LUISA_ASSERT(lhs_type != nullptr && rhs_type != nullptr, "Operand type is null."); + LUISA_ASSERT(lhs_type == rhs_type, "Type mismatch for bitwise and."); + LUISA_ASSERT(lhs_type->is_scalar() || lhs_type->is_vector(), "Invalid operand type."); + + // Perform bitwise AND operation + switch (elem_type->tag()) { + case Type::Tag::BOOL: [[fallthrough]]; + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: [[fallthrough]]; + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: return b.CreateAnd(llvm_lhs, llvm_rhs); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid binary bit and operand type: {}.", elem_type->description()); + } + + [[nodiscard]] llvm::Value *_translate_binary_bit_or(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + // Lookup LLVM values for operands + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto lhs_type = lhs->type(); + auto rhs_type = rhs->type(); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + // Type and null checks + LUISA_ASSERT(lhs_type != nullptr && rhs_type != nullptr, "Operand type is null."); + LUISA_ASSERT(lhs_type == rhs_type, "Type mismatch for bitwise and."); + LUISA_ASSERT(lhs_type->is_scalar() || lhs_type->is_vector(), "Invalid operand type."); + + // Perform bitwise AND operation + switch (elem_type->tag()) { + case Type::Tag::BOOL: [[fallthrough]]; + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: [[fallthrough]]; + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: return b.CreateOr(llvm_lhs, llvm_rhs); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid binary bit or operand type: {}.", elem_type->description()); + } + + [[nodiscard]] llvm::Value *_translate_binary_bit_xor(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + // Lookup LLVM values for operands + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto lhs_type = lhs->type(); + auto rhs_type = rhs->type(); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + // Type and null checks + LUISA_ASSERT(lhs_type != nullptr && rhs_type != nullptr, "Operand type is null."); + LUISA_ASSERT(lhs_type == rhs_type, "Type mismatch for bitwise and."); + LUISA_ASSERT(lhs_type->is_scalar() || lhs_type->is_vector(), "Invalid operand type."); + + // Perform bitwise AND operation + switch (elem_type->tag()) { + case Type::Tag::BOOL: [[fallthrough]]; + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: [[fallthrough]]; + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: return b.CreateXor(llvm_lhs, llvm_rhs); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid binary bit xor operand type: {}.", elem_type->description()); + } + + [[nodiscard]] llvm::Value *_translate_binary_shift_left(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + // Lookup LLVM values for operands + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto lhs_type = lhs->type(); + auto rhs_type = rhs->type(); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + + // Type and null checks + LUISA_ASSERT(lhs_type != nullptr && rhs_type != nullptr, "Operand type is null."); + LUISA_ASSERT(lhs_type == rhs_type, "Type mismatch for shift left."); + LUISA_ASSERT(lhs_type->is_scalar() || lhs_type->is_vector(), "Invalid operand type."); + + // Perform shift left operation (only valid for integer types) + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: [[fallthrough]]; + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: return b.CreateShl(llvm_lhs, llvm_rhs); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid operand type for shift left operation: {}.", elem_type->description()); + } + + [[nodiscard]] llvm::Value *_translate_binary_shift_right(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + // Lookup LLVM values for operands + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto lhs_type = lhs->type(); + auto rhs_type = rhs->type(); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + + // Type and null checks + LUISA_ASSERT(lhs_type != nullptr && rhs_type != nullptr, "Operand type is null."); + LUISA_ASSERT(lhs_type == rhs_type, "Type mismatch for shift left."); + LUISA_ASSERT(lhs_type->is_scalar() || lhs_type->is_vector(), "Invalid operand type."); + + // Perform shift left operation (only valid for integer types) + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: return b.CreateAShr(llvm_lhs, llvm_rhs); + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: return b.CreateLShr(llvm_lhs, llvm_rhs); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid operand type for shift left operation: {}.", elem_type->description()); + } + + [[nodiscard]] llvm::Value *_translate_binary_rotate_left(CurrentFunction ¤t, IRBuilder &b, const xir::Value *value, const xir::Value *shift) noexcept { + auto llvm_value = _lookup_value(current, b, value); + auto llvm_shift = _lookup_value(current, b, shift); + auto value_type = value->type(); + auto elem_type = value_type->is_vector() ? value_type->element() : value_type; + LUISA_ASSERT(value_type != nullptr, "Operand type is null."); + LUISA_ASSERT(value_type == shift->type(), "Type mismatch for rotate left."); + LUISA_ASSERT(value_type->is_scalar() || value_type->is_vector(), "Invalid operand type."); + auto bit_width = 0u; + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::UINT8: bit_width = 8; break; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::UINT16: bit_width = 16; break; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::UINT32: bit_width = 32; break; + case Type::Tag::INT64: [[fallthrough]]; + case Type::Tag::UINT64: bit_width = 64; break; + default: LUISA_ERROR_WITH_LOCATION( + "Invalid operand type for rotate left operation: {}.", + elem_type->description()); + } + auto llvm_elem_type = _translate_type(elem_type, false); + auto llvm_bit_width = llvm::ConstantInt::get(llvm_elem_type, bit_width); + if (value_type->is_vector()) { + llvm_bit_width = llvm::ConstantVector::getSplat( + llvm::ElementCount::getFixed(value_type->dimension()), + llvm_bit_width); + } + auto shifted_left = b.CreateShl(llvm_value, llvm_shift); + auto complement_shift = b.CreateSub(llvm_bit_width, llvm_shift); + auto shifted_right = b.CreateLShr(llvm_value, complement_shift); + return b.CreateOr(shifted_left, shifted_right); + } + + [[nodiscard]] llvm::Value *_translate_binary_rotate_right(CurrentFunction ¤t, IRBuilder &b, const xir::Value *value, const xir::Value *shift) noexcept { + // Lookup LLVM values for operands + auto llvm_value = _lookup_value(current, b, value); + auto llvm_shift = _lookup_value(current, b, shift); + auto value_type = value->type(); + auto elem_type = value_type->is_vector() ? value_type->element() : value_type; + + // Type and null checks + LUISA_ASSERT(value_type != nullptr, "Operand type is null."); + LUISA_ASSERT(value_type == shift->type(), "Type mismatch for rotate right."); + LUISA_ASSERT(value_type->is_scalar() || value_type->is_vector(), "Invalid operand type."); + + auto bit_width = 0u; + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::UINT8: bit_width = 8; break; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::UINT16: bit_width = 16; break; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::UINT32: bit_width = 32; break; + case Type::Tag::INT64: [[fallthrough]]; + case Type::Tag::UINT64: bit_width = 64; break; + default: LUISA_ERROR_WITH_LOCATION( + "Invalid operand type for rotate right operation: {}.", + elem_type->description()); + } + auto llvm_elem_type = _translate_type(elem_type, false); + auto llvm_bit_width = llvm::ConstantInt::get(llvm_elem_type, bit_width); + if (value_type->is_vector()) { + llvm_bit_width = llvm::ConstantVector::getSplat( + llvm::ElementCount::getFixed(value_type->dimension()), + llvm_bit_width); + } + auto shifted_right = b.CreateLShr(llvm_value, llvm_shift); + auto complement_shift = b.CreateSub(llvm_bit_width, llvm_shift); + auto shifted_left = b.CreateShl(llvm_value, complement_shift); + return b.CreateOr(shifted_left, shifted_right); + } + + [[nodiscard]] llvm::Value *_translate_binary_less(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + // Lookup LLVM values for operands + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto lhs_type = lhs->type(); + auto rhs_type = rhs->type(); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + + // Type and null checks + LUISA_ASSERT(lhs_type != nullptr && rhs_type != nullptr, "Operand type is null."); + LUISA_ASSERT(lhs_type == rhs_type, "Type mismatch for binary less."); + LUISA_ASSERT(lhs_type->is_scalar() || lhs_type->is_vector(), "Invalid operand type."); + + // Perform less-than comparison based on the type + llvm::Value *result = nullptr; + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: result = b.CreateICmpSLT(llvm_lhs, llvm_rhs); break;// Signed integer less-than comparison + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: result = b.CreateICmpULT(llvm_lhs, llvm_rhs); break;// Unsigned integer less-than comparison + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: result = b.CreateFCmpOLT(llvm_lhs, llvm_rhs); break;// Floating-point unordered less-than comparison + default: LUISA_ERROR_WITH_LOCATION("Invalid operand type for binary less-equal operation: {}.", elem_type->description()); + } + return _zext_i1_to_i8(b, result); + } + + [[nodiscard]] llvm::Value *_translate_binary_greater(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto lhs_type = lhs->type(); + auto rhs_type = rhs->type(); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + + LUISA_ASSERT(lhs_type != nullptr && rhs_type != nullptr, "Operand type is null."); + LUISA_ASSERT(lhs_type == rhs_type, "Type mismatch for binary greater."); + LUISA_ASSERT(lhs_type->is_scalar() || lhs_type->is_vector(), "Invalid operand type."); + + llvm::Value *result = nullptr; + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: result = b.CreateICmpSGT(llvm_lhs, llvm_rhs); break;// Signed integer greater-than + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: result = b.CreateICmpUGT(llvm_lhs, llvm_rhs); break;// Unsigned integer greater-than + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: result = b.CreateFCmpOGT(llvm_lhs, llvm_rhs); break;// Ordered greater-than + default: LUISA_ERROR_WITH_LOCATION("Invalid operand type for binary less-equal operation: {}.", elem_type->description()); + } + return _zext_i1_to_i8(b, result); + } + + [[nodiscard]] llvm::Value *_translate_binary_less_equal(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto lhs_type = lhs->type(); + auto rhs_type = rhs->type(); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + + LUISA_ASSERT(lhs_type != nullptr && rhs_type != nullptr, "Operand type is null."); + LUISA_ASSERT(lhs_type == rhs_type, "Type mismatch for binary less-equal."); + LUISA_ASSERT(lhs_type->is_scalar() || lhs_type->is_vector(), "Invalid operand type."); + + llvm::Value *result = nullptr; + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: result = b.CreateICmpSLE(llvm_lhs, llvm_rhs); break;// Signed integer less-than-or-equal + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: result = b.CreateICmpULE(llvm_lhs, llvm_rhs); break;// Unsigned integer less-than-or-equal + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: result = b.CreateFCmpOLE(llvm_lhs, llvm_rhs); break;// Ordered less-than-or-equal + default: LUISA_ERROR_WITH_LOCATION("Invalid operand type for binary less-equal operation: {}.", elem_type->description()); + } + return _zext_i1_to_i8(b, result); + } + + [[nodiscard]] llvm::Value *_translate_binary_greater_equal(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto lhs_type = lhs->type(); + auto rhs_type = rhs->type(); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + + LUISA_ASSERT(lhs_type != nullptr && rhs_type != nullptr, "Operand type is null."); + LUISA_ASSERT(lhs_type == rhs_type, "Type mismatch for binary greater-equal."); + LUISA_ASSERT(lhs_type->is_scalar() || lhs_type->is_vector(), "Invalid operand type."); + + llvm::Value *result = nullptr; + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: result = b.CreateICmpSGE(llvm_lhs, llvm_rhs); break;// Signed integer greater-than-or-equal + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: result = b.CreateICmpUGE(llvm_lhs, llvm_rhs); break;// Unsigned integer greater-than-or-equal + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: result = b.CreateFCmpOGE(llvm_lhs, llvm_rhs); break;// Ordered greater-than-or-equal + default: LUISA_ERROR_WITH_LOCATION("Invalid operand type for binary less-equal operation: {}.", elem_type->description()); + } + return _zext_i1_to_i8(b, result); + } + + [[nodiscard]] llvm::Value *_translate_binary_equal(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto lhs_type = lhs->type(); + auto rhs_type = rhs->type(); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + + LUISA_ASSERT(lhs_type != nullptr && rhs_type != nullptr, "Operand type is null."); + LUISA_ASSERT(lhs_type == rhs_type, "Type mismatch for binary equal."); + LUISA_ASSERT(lhs_type->is_scalar() || lhs_type->is_vector(), "Invalid operand type."); + + llvm::Value *result = nullptr; + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: [[fallthrough]]; + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: result = b.CreateICmpEQ(llvm_lhs, llvm_rhs); break;// Integer equality comparison + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: result = b.CreateFCmpOEQ(llvm_lhs, llvm_rhs); break;// Ordered equality comparison + default: LUISA_ERROR_WITH_LOCATION("Invalid operand type for binary less-equal operation: {}.", elem_type->description()); + } + return _zext_i1_to_i8(b, result); + } + + [[nodiscard]] llvm::Value *_translate_binary_not_equal(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + auto llvm_lhs = _lookup_value(current, b, lhs); + auto llvm_rhs = _lookup_value(current, b, rhs); + auto lhs_type = lhs->type(); + auto rhs_type = rhs->type(); + auto elem_type = lhs->type()->is_vector() ? lhs->type()->element() : lhs->type(); + + LUISA_ASSERT(lhs_type != nullptr && rhs_type != nullptr, "Operand type is null."); + LUISA_ASSERT(lhs_type == rhs_type, "Type mismatch for binary equal."); + LUISA_ASSERT(lhs_type->is_scalar() || lhs_type->is_vector(), "Invalid operand type."); + + llvm::Value *result = nullptr; + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: [[fallthrough]]; + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: result = b.CreateICmpNE(llvm_lhs, llvm_rhs); break;// Integer equality comparison + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: result = b.CreateFCmpONE(llvm_lhs, llvm_rhs); break;// Ordered equality comparison + default: LUISA_ERROR_WITH_LOCATION("Invalid operand type for binary less-equal operation: {}.", elem_type->description()); + } + return _zext_i1_to_i8(b, result); + } + + [[nodiscard]] llvm::Value *_translate_unary_fp_math_operation(CurrentFunction ¤t, IRBuilder &b, const xir::Value *operand, llvm::Intrinsic::ID intrinsic_id) noexcept { + // Lookup LLVM value for operand + auto llvm_operand = _lookup_value(current, b, operand); + auto operand_type = operand->type(); + + // Type and null checks + LUISA_ASSERT(operand_type != nullptr, "Operand type is null."); + LUISA_ASSERT(operand_type->is_scalar() || operand_type->is_vector(), "Invalid operand type."); + + // Check if the operand is a valid floating-point type + auto elem_type = operand_type->is_vector() ? operand_type->element() : operand_type; + switch (elem_type->tag()) { + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: + // Use LLVM's intrinsic function based on the provided intrinsic ID + return b.CreateUnaryIntrinsic(intrinsic_id, llvm_operand); + default: + break; + } + LUISA_ERROR_WITH_LOCATION("Invalid operand type for unary math operation {}: {}.", + intrinsic_id, operand_type->description()); + } + + [[nodiscard]] llvm::Value *_translate_binary_fp_math_operation(CurrentFunction ¤t, IRBuilder &b, + const xir::Value *op0, const xir::Value *op1, + llvm::Intrinsic::ID intrinsic_id) noexcept { + auto llvm_op0 = _lookup_value(current, b, op0); + auto llvm_op1 = _lookup_value(current, b, op1); + auto op0_type = op0->type(); + auto op1_type = op1->type(); + LUISA_ASSERT(op0_type == op1_type, "Type mismatch."); + LUISA_ASSERT(op0_type != nullptr && (op0_type->is_scalar() || op0_type->is_vector()), "Invalid operand type."); + auto elem_type = op0_type->is_vector() ? op0_type->element() : op0_type; + switch (elem_type->tag()) { + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: + return b.CreateBinaryIntrinsic(intrinsic_id, llvm_op0, llvm_op1); + default: + break; + } + LUISA_ERROR_WITH_LOCATION("Invalid operand type for binary math operation {}: {}.", + intrinsic_id, op0_type->description()); + } + + [[nodiscard]] llvm::Value *_translate_vector_reduce(CurrentFunction ¤t, IRBuilder &b, + xir::IntrinsicOp op, const xir::Value *operand) noexcept { + LUISA_ASSERT(operand->type() != nullptr && operand->type()->is_vector(), + "Invalid operand type for reduce_sum operation."); + auto operand_elem_type = operand->type()->element(); + auto llvm_operand = _lookup_value(current, b, operand); + switch (operand->type()->element()->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::INT64: [[fallthrough]]; + case Type::Tag::UINT64: { + switch (op) { + case xir::IntrinsicOp::REDUCE_SUM: return b.CreateAddReduce(llvm_operand); + case xir::IntrinsicOp::REDUCE_PRODUCT: return b.CreateMulReduce(llvm_operand); + case xir::IntrinsicOp::REDUCE_MIN: return b.CreateIntMinReduce(llvm_operand); + case xir::IntrinsicOp::REDUCE_MAX: return b.CreateIntMaxReduce(llvm_operand); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid reduce operation: {}.", xir::to_string(op)); + } + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: { + auto llvm_elem_type = _translate_type(operand_elem_type, false); + auto llvm_zero = llvm::ConstantFP::get(llvm_elem_type, 0.); + auto llvm_one = llvm::ConstantFP::get(llvm_elem_type, 1.); + switch (op) { + case xir::IntrinsicOp::REDUCE_SUM: return b.CreateFAddReduce(llvm_zero, llvm_operand); + case xir::IntrinsicOp::REDUCE_PRODUCT: return b.CreateFMulReduce(llvm_one, llvm_operand); + case xir::IntrinsicOp::REDUCE_MIN: return b.CreateFPMinReduce(llvm_operand); + case xir::IntrinsicOp::REDUCE_MAX: return b.CreateFPMaxReduce(llvm_operand); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid reduce operation: {}.", xir::to_string(op)); + } + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid operand type for reduce_sum operation: {}.", + operand_elem_type->description()); + } + + [[nodiscard]] llvm::Value *_translate_vector_dot(CurrentFunction ¤t, IRBuilder &b, const xir::Value *lhs, const xir::Value *rhs) noexcept { + auto llvm_mul = _translate_binary_mul(current, b, lhs, rhs); + if (llvm_mul->getType()->isFPOrFPVectorTy()) { + auto llvm_elem_type = llvm_mul->getType()->isVectorTy() ? + llvm::cast(llvm_mul->getType())->getElementType() : + llvm_mul->getType(); + auto llvm_zero = llvm::ConstantFP::get(llvm_elem_type, 0.); + return b.CreateFAddReduce(llvm_zero, llvm_mul); + } + return b.CreateAddReduce(llvm_mul); + } + + [[nodiscard]] llvm::Value *_translate_isinf_isnan(CurrentFunction ¤t, IRBuilder &b, xir::IntrinsicOp op, const xir::Value *x) noexcept { + auto type = x->type(); + auto elem_type = type->is_vector() ? type->element() : type; + auto llvm_x = _lookup_value(current, b, x); + auto [llvm_mask, llvm_test] = [&] { + switch (elem_type->tag()) { + case Type::Tag::FLOAT16: return std::make_pair( + llvm::cast(b.getInt16(0x7fffu)), + llvm::cast(b.getInt16(0x7c00u))); + case Type::Tag::FLOAT32: return std::make_pair( + llvm::cast(b.getInt32(0x7fffffffu)), + llvm::cast(b.getInt32(0x7f800000u))); + case Type::Tag::FLOAT64: return std::make_pair( + llvm::cast(b.getInt64(0x7fffffffffffffffull)), + llvm::cast(b.getInt64(0x7ff0000000000000ull))); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid operand type for isinf/isnan operation: {}.", type->description()); + }(); + if (type->is_vector()) { + auto dim = llvm::ElementCount::getFixed(type->dimension()); + llvm_mask = llvm::ConstantVector::getSplat(dim, llvm_mask); + llvm_test = llvm::ConstantVector::getSplat(dim, llvm_test); + } + auto llvm_int_type = llvm_mask->getType(); + auto llvm_bits = b.CreateBitCast(llvm_x, llvm_int_type); + auto llvm_and = b.CreateAnd(llvm_bits, llvm_mask); + LUISA_DEBUG_ASSERT(op == xir::IntrinsicOp::ISINF || op == xir::IntrinsicOp::ISNAN, + "Unexpected intrinsic operation."); + auto llvm_cmp = op == xir::IntrinsicOp::ISINF ? + b.CreateICmpEQ(llvm_and, llvm_test) : + b.CreateICmpUGE(llvm_and, llvm_test); + return _zext_i1_to_i8(b, llvm_cmp); + } + + [[nodiscard]] llvm::Value *_translate_buffer_write(CurrentFunction ¤t, IRBuilder &b, const xir::IntrinsicInst *inst, bool byte_address = false) noexcept { + //LUISA_NOT_IMPLEMENTED(); + auto buffer = inst->operand(0u); + LUISA_ASSERT(buffer->type()->is_buffer(), "Invalid buffer type."); + auto slot = inst->operand(1u); + auto value = inst->operand(2u); + auto llvm_buffer = _lookup_value(current, b, buffer); // Get the buffer view + auto llvm_buffer_addr = b.CreateExtractValue(llvm_buffer, {0});// Get the buffer address + auto llvm_slot = _lookup_value(current, b, slot); // Get the slot index + auto llvm_value = _lookup_value(current, b, value); // Get the value to write + auto element_type = llvm_value->getType(); // Type of the value being written + auto slot_type = byte_address ? b.getInt8Ty() : element_type; + auto target_address = b.CreateInBoundsGEP( + slot_type, // Element type + llvm_buffer_addr,// Base pointer + llvm_slot // Index + ); + auto alignment = _get_type_alignment(value->type()); + //b.CreateAlignmentAssumption(current.func->getDataLayout(), target_address, alignment); + return b.CreateAlignedStore(llvm_value, target_address, llvm::MaybeAlign{alignment}); + } + + [[nodiscard]] llvm::Value *_translate_buffer_read(CurrentFunction ¤t, IRBuilder &b, const xir::IntrinsicInst *inst, bool byte_address = false) noexcept { + //LUISA_NOT_IMPLEMENTED(); + auto buffer = inst->operand(0u); + LUISA_ASSERT(buffer->type()->is_buffer(), "Invalid buffer type."); + auto slot = inst->operand(1u); + auto llvm_buffer = _lookup_value(current, b, buffer); // Get the buffer view + auto llvm_buffer_addr = b.CreateExtractValue(llvm_buffer, {0});// Get the buffer address + auto llvm_slot = _lookup_value(current, b, slot); // Get the slot index + auto element_type = _translate_type(inst->type(), true); // Type of the value being read + auto slot_type = byte_address ? b.getInt8Ty() : element_type; + auto target_address = b.CreateInBoundsGEP( + slot_type, // Element type + llvm_buffer_addr,// Base pointer + llvm_slot // Index + ); + auto alignment = _get_type_alignment(inst->type()); + //b.CreateAlignmentAssumption(current.func->getDataLayout(), target_address, alignment); + return b.CreateAlignedLoad(element_type, target_address, llvm::MaybeAlign{alignment}); + } + + [[nodiscard]] llvm::Value *_translate_buffer_size(CurrentFunction ¤t, IRBuilder &b, const xir::IntrinsicInst *inst, bool byte_address = false) noexcept { + auto buffer = inst->operand(0u); + LUISA_ASSERT(buffer->type()->is_buffer(), "Invalid buffer type."); + auto llvm_buffer = _lookup_value(current, b, buffer); + auto llvm_byte_size = b.CreateExtractValue(llvm_buffer, {1}); + auto llvm_result_type = _translate_type(inst->type(), true); + llvm_byte_size = b.CreateZExtOrTrunc(llvm_byte_size, llvm_result_type); + if (!byte_address) { + auto elem_size = buffer->type()->element()->size(); + auto llvm_elem_size = llvm::ConstantInt::get(llvm_result_type, elem_size); + llvm_byte_size = b.CreateUDiv(llvm_byte_size, llvm_elem_size); + } + return llvm_byte_size; + } + + [[nodiscard]] llvm::Value *_translate_buffer_device_address(CurrentFunction ¤t, IRBuilder &b, const xir::IntrinsicInst *inst) noexcept { + auto buffer = inst->operand(0u); + LUISA_ASSERT(buffer->type()->is_buffer(), "Invalid buffer type."); + auto llvm_buffer = _lookup_value(current, b, buffer); + auto llvm_buffer_ptr = b.CreateExtractValue(llvm_buffer, {0}); + auto llvm_int_type = _translate_type(inst->type(), false); + return b.CreatePtrToInt(llvm_buffer_ptr, llvm_int_type); + } + + [[nodiscard]] llvm::Value *_translate_device_address_read(CurrentFunction ¤t, IRBuilder &b, const xir::IntrinsicInst *inst) noexcept { + auto llvm_device_address = _lookup_value(current, b, inst->operand(0u)); + auto llvm_ptr_type = llvm::PointerType::get(_llvm_context, 0); + auto llvm_ptr = b.CreateIntToPtr(llvm_device_address, llvm_ptr_type); + auto alignment = _get_type_alignment(inst->type()); + //b.CreateAlignmentAssumption(current.func->getDataLayout(), llvm_ptr, alignment); + auto llvm_result_type = _translate_type(inst->type(), true); + return b.CreateAlignedLoad(llvm_result_type, llvm_ptr, llvm::MaybeAlign{alignment}); + } + + [[nodiscard]] llvm::Value *_translate_device_address_write(CurrentFunction ¤t, IRBuilder &b, const xir::IntrinsicInst *inst) noexcept { + auto llvm_device_address = _lookup_value(current, b, inst->operand(0u)); + auto llvm_value = _lookup_value(current, b, inst->operand(1u)); + auto llvm_ptr_type = llvm::PointerType::get(_llvm_context, 0); + auto llvm_ptr = b.CreateIntToPtr(llvm_device_address, llvm_ptr_type); + auto alignment = _get_type_alignment(inst->operand(1u)->type()); + //b.CreateAlignmentAssumption(current.func->getDataLayout(), llvm_ptr, alignment); + return b.CreateAlignedStore(llvm_value, llvm_ptr, llvm::MaybeAlign{alignment}); + } + + [[nodiscard]] llvm::Value *_translate_texture_read( + CurrentFunction ¤t, + IRBuilder &b, + const xir::Instruction *inst) noexcept { + + auto view_struct = inst->operand(0u); + auto coord = inst->operand(1u); + LUISA_ASSERT(view_struct->type() == Type::of>()|| + view_struct->type() == Type::of>(), "Invalid texture view type."); + + static const char* function_names[] = + { + "texture.read.2d.float", + "texture.read.2d.uint" + }; + unsigned int functionIdx = 0u; + if (view_struct->type() == Type::of>()) + functionIdx = 1u; + + // Get LLVM values for the arguments + auto llvm_view_struct = _lookup_value(current, b, view_struct); + auto llvm_coord = _lookup_value(current, b, coord); + + auto texture_struct_alloca = b.CreateAlloca(llvm_view_struct->getType(), nullptr, ""); + b.CreateStore(llvm_view_struct, texture_struct_alloca); + + auto outType = llvm::VectorType::get(_translate_type(view_struct->type()->element(), false), + 4u, false); + // Allocate space for the result locally + auto result_alloca = b.CreateAlloca(outType, nullptr, ""); + + // Extract x and y from uint2 coordinate + auto coord_x = b.CreateExtractElement(llvm_coord, b.getInt32(0), ""); + auto coord_y = b.CreateExtractElement(llvm_coord, b.getInt32(1), ""); + + // Define the function type: void(void*, uint, uint, void*) + auto func_type = llvm::FunctionType::get( + b.getVoidTy(), + {b.getPtrTy(), // void* texture_ptr + b.getInt32Ty(),// uint x + b.getInt32Ty(),// uint y + b.getPtrTy()}, // void* result + false); + + // Get the function pointer from the symbol map + auto func = _llvm_module->getOrInsertFunction(function_names[functionIdx], func_type); + + // Call the function + b.CreateCall(func, {texture_struct_alloca, coord_x, coord_y, result_alloca}); + + // Return the loaded result + return b.CreateLoad(outType, result_alloca, ""); + } + + [[nodiscard]] llvm::Value *_translate_texture_write( + CurrentFunction ¤t, + IRBuilder &b, + const xir::Value *view_struct, + const xir::Value *coord, + const xir::Value *val) noexcept { + + LUISA_ASSERT(view_struct->type() == Type::of>()|| + view_struct->type() == Type::of>(), "Invalid texture view type."); + + static const char* function_names[] = + { + "texture.write.2d.float", + "texture.write.2d.uint" + }; + + unsigned int functionIdx = 0u; + if (view_struct->type() == Type::of>()) + functionIdx = 1u; + + // Get LLVM values for the arguments + auto llvm_view_struct = _lookup_value(current, b, view_struct); + auto llvm_coord = _lookup_value(current, b, coord); + auto llvm_val = _lookup_value(current, b, val); + + // Allocate space for the texture view struct + auto texture_struct_alloca = b.CreateAlloca(llvm_view_struct->getType(), nullptr, ""); + b.CreateStore(llvm_view_struct, texture_struct_alloca); + + // Extract x and y from uint2 coordinate + auto coord_x = b.CreateExtractElement(llvm_coord, b.getInt32(0), ""); + auto coord_y = b.CreateExtractElement(llvm_coord, b.getInt32(1), ""); + + auto val_alloca = b.CreateAlloca(llvm_val->getType(), nullptr, ""); + b.CreateStore(llvm_val, val_alloca); + + // Define the function type: void(void*, uint, uint, void*) + auto func_type = llvm::FunctionType::get( + b.getVoidTy(), + {b.getPtrTy(), // void* texture_ptr + b.getInt32Ty(),// uint x + b.getInt32Ty(),// uint y + b.getPtrTy()}, // void* value + false); + + // Add attributes to the function (write operations typically do not use `readonly`) + auto func = _llvm_module->getOrInsertFunction(function_names[functionIdx], func_type); + + // Call the function + return b.CreateCall(func, {texture_struct_alloca, coord_x, coord_y, val_alloca}); + } + + [[nodiscard]] llvm::Value *_translate_aggregate(CurrentFunction ¤t, + IRBuilder &b, const xir::IntrinsicInst *inst) { + auto type = inst->type(); + LUISA_ASSERT(type->is_vector(), "only aggregate vectors at the moment"); + auto elem_type = type->element(); + auto dim = type->dimension(); + + auto llvm_elem_type = _translate_type(elem_type, true); + + auto llvm_return_type = llvm::VectorType::get(llvm_elem_type, dim, false); + + auto vector = llvm::cast(llvm::PoisonValue::get(llvm_return_type)); + for (int i = 0; i < dim; i++) { + auto operand = inst->operand(i); + LUISA_ASSERT(operand->type() == elem_type, "element type doesn't match"); + auto llvm_operand = _lookup_value(current, b, operand); + LUISA_ASSERT(llvm_operand->getType() == llvm_elem_type, "element type doesn't match"); + + vector = b.CreateInsertElement(vector, llvm_operand, static_cast(i)); + } + return vector; + } + + [[nodiscard]] llvm::Value *_translate_shuffle(CurrentFunction ¤t, + IRBuilder &b, const xir::IntrinsicInst *inst) { + + // swfly has to give up using llvm's intrinsic for shuffle because it's too difficult + // don't give up + auto result_type = inst->type(); + LUISA_ASSERT(result_type->is_vector(), "shuffle target must be a vector"); + + auto result_elem_type = result_type->element(); + auto result_dim = result_type->dimension(); + LUISA_ASSERT(inst->operand_count() == result_dim + 1u, "shuffle operand count doesn't match"); + + auto src = inst->operand(0); + LUISA_ASSERT(src != nullptr, "shuffle target is null"); + + auto src_type = src->type(); + LUISA_ASSERT(src_type != nullptr && src_type->element() == result_elem_type, + "shuffle element type doesn't match"); + + auto llvm_src = _lookup_value(current, b, src); + + auto indices = inst->operand_uses().subspan(1); + auto statically_shuffled = std::all_of(indices.cbegin(), indices.cend(), [](const xir::Use *v) { + LUISA_ASSERT(v->value() != nullptr, "shuffle index is null"); + return v->value()->derived_value_tag() == xir::DerivedValueTag::CONSTANT; + }); + + // we may use llvm's shufflevector intrinsic if all indices are constant + if (statically_shuffled) { + llvm::SmallVector static_indices; + for (auto i : indices) { + auto static_index = [src_dim = src_type->dimension(), index = static_cast(i->value())] { + auto safe_index = [src_dim](auto x) noexcept { + LUISA_ASSERT(x >= 0u && x < src_dim, "shuffle index out of range"); + return static_cast(x); + }; + switch (index->type()->tag()) { + case Type::Tag::INT8: return safe_index(index->as()); + case Type::Tag::UINT8: return safe_index(index->as()); + case Type::Tag::INT16: return safe_index(index->as()); + case Type::Tag::UINT16: return safe_index(index->as()); + case Type::Tag::INT32: return safe_index(index->as()); + case Type::Tag::UINT32: return safe_index(index->as()); + case Type::Tag::INT64: return safe_index(index->as()); + case Type::Tag::UINT64: return safe_index(index->as()); + default: break; + } + LUISA_ERROR_WITH_LOCATION("invalid shuffle index type: {}.", index->type()->description()); + }(); + static_indices.push_back(static_index); + } + auto llvm_poison_value = llvm::PoisonValue::get(llvm_src->getType()); + return b.CreateShuffleVector(llvm_src, llvm_poison_value, static_indices); + } + + // otherwise, we extract elements and create the target vector + auto llvm_result_type = _translate_type(result_type, true); + auto llvm_result = llvm::cast(llvm::PoisonValue::get(llvm_result_type)); + for (auto i = 0u; i < result_dim; i++) { + auto llvm_index = _lookup_value(current, b, indices[i]->value()); + auto llvm_src_elem = b.CreateExtractElement(llvm_src, llvm_index); + llvm_result = b.CreateInsertElement(llvm_result, llvm_src_elem, i); + } + return llvm_result; + } + + [[nodiscard]] llvm::Value *_translate_bindless_read( + CurrentFunction ¤t, + IRBuilder &b, + const xir::IntrinsicInst *inst) noexcept + { + auto bindless_ptr = inst->operand(0u); + auto slotIdx = inst->operand(1u); + auto elemIdx = inst->operand(2u); + auto type = inst->type(); + auto alignment = _get_type_alignment(inst->type()); + auto size = inst->type()->size(); + + // Get LLVM values for the arguments + auto llvm_bindless = _lookup_value(current, b, bindless_ptr); + auto llvm_slot = _lookup_value(current, b, slotIdx); + auto llvm_elem = _lookup_value(current, b, elemIdx); + + auto llvm_data_stride = llvm::ConstantInt::get(b.getInt32Ty(), inst->type()->size()); + + auto llvm_value_type = _translate_type(inst->type(), true); + // Allocate space for the texture view struct + auto val_alloca = b.CreateAlloca(llvm_value_type, nullptr, ""); + + + // Define the function type: void(void*, uint, uint, void*) + auto func_type = llvm::FunctionType::get( + b.getVoidTy(), + {b.getPtrTy(), // void* texture_ptr + b.getInt32Ty(),// slot + b.getInt32Ty(),// elem + b.getInt32Ty(), //stride + b.getPtrTy()}, // void* value + false); + + // Add attributes to the function (write operations typically do not use `readonly`) + auto func = _llvm_module->getOrInsertFunction("bindless.buffer.read", func_type); + + // Call the function + b.CreateCall(func, {llvm_bindless, llvm_slot, llvm_elem, llvm_data_stride, val_alloca}); + // Return the loaded result + return b.CreateLoad(llvm_value_type, val_alloca, ""); + } + [[nodiscard]] llvm::Value *_translate_accel_trace( + CurrentFunction ¤t, + IRBuilder &b, + const xir::IntrinsicInst *inst) noexcept { + + // Extract LLVM values for the operands + const xir::Value *accel = inst->operand(0u); + const xir::Value *ray = inst->operand(1u); + const xir::Value *mask = inst->operand(2u); + + // Get LLVM values for the arguments + auto llvm_accel = _lookup_value(current, b, accel); + auto llvm_ray = _lookup_value(current, b, ray); + auto llvm_mask = _lookup_value(current, b, mask); + + // Allocate space for the SurfaceHit result locally + auto hit_type = llvm::StructType::create( + b.getContext(), + {b.getInt32Ty(), // uint inst + b.getInt32Ty(), // uint prim + llvm::VectorType::get(b.getFloatTy(), 2u, false),// float2 bary + b.getFloatTy()}, // float committed_ray_t + "SurfaceHit"); + + auto hit_alloca = b.CreateAlloca(hit_type, nullptr, ""); + + // Extract ray components + auto compressed_origin = b.CreateExtractValue(llvm_ray, 0, "compressed_origin"); + auto compressed_t_min = b.CreateExtractValue(llvm_ray, 1, "compressed_t_min"); + auto compressed_direction = b.CreateExtractValue(llvm_ray, 2, "compressed_direction"); + auto compressed_t_max = b.CreateExtractValue(llvm_ray, 3, "compressed_t_max"); + + //printTypeLayout(compressed_origin->getType()); + // Extract x, y, z for origin + auto origin_x = b.CreateExtractValue(compressed_origin, 0, "origin_x"); + auto origin_y = b.CreateExtractValue(compressed_origin, 1, "origin_y"); + auto origin_z = b.CreateExtractValue(compressed_origin, 2, "origin_z"); + + // Extract x, y, z for direction + auto direction_x = b.CreateExtractValue(compressed_direction, 0, "direction_x"); + auto direction_y = b.CreateExtractValue(compressed_direction, 1, "direction_y"); + auto direction_z = b.CreateExtractValue(compressed_direction, 2, "direction_z"); + + // Define the function type: void(void*, float, float, float, float, float, float, float, float, unsigned, void*) + auto func_type = llvm::FunctionType::get( + b.getVoidTy(), + { + b.getPtrTy(), // void* accel + b.getFloatTy(),// float ox + b.getFloatTy(),// float oy + b.getFloatTy(),// float oz + b.getFloatTy(),// float dx + b.getFloatTy(),// float dy + b.getFloatTy(),// float dz + b.getFloatTy(),// float tmin + b.getFloatTy(),// float tmax + b.getInt32Ty(),// unsigned mask + b.getPtrTy() // void* hit + }, + false); + + // Get the function pointer from the symbol map + auto func = _llvm_module->getOrInsertFunction("intersect.closest", func_type); + + // Call the function + b.CreateCall( + func, + { + llvm_accel, // accel pointer + origin_x, // ray.origin.x + origin_y, // ray.origin.y + origin_z, // ray.origin.z + direction_x, // ray.direction.x + direction_y, // ray.direction.y + direction_z, // ray.direction.z + compressed_t_min,// ray.t_min + compressed_t_max,// ray.t_max + llvm_mask, // mask + hit_alloca // hit pointer + }); + + // Load the SurfaceHit result and return + return b.CreateLoad(hit_type, hit_alloca, "hit_result"); + } + + [[nodiscard]] llvm::Value *_translate_intrinsic_inst(CurrentFunction ¤t, IRBuilder &b, const xir::IntrinsicInst *inst) noexcept { + switch (inst->op()) { + case xir::IntrinsicOp::NOP: LUISA_ERROR_WITH_LOCATION("Unexpected NOP."); + case xir::IntrinsicOp::UNARY_PLUS: return _translate_unary_plus(current, b, inst->operand(0u)); + case xir::IntrinsicOp::UNARY_MINUS: return _translate_unary_minus(current, b, inst->operand(0u)); + case xir::IntrinsicOp::UNARY_LOGIC_NOT: return _translate_unary_logic_not(current, b, inst->operand(0u)); + case xir::IntrinsicOp::UNARY_BIT_NOT: return _translate_unary_bit_not(current, b, inst->operand(0u)); + case xir::IntrinsicOp::BINARY_ADD: return _translate_binary_add(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_SUB: return _translate_binary_sub(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_MUL: return _translate_binary_mul(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_DIV: return _translate_binary_div(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_MOD: return _translate_binary_mod(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_LOGIC_AND: return _translate_binary_logic_and(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_LOGIC_OR: return _translate_binary_logic_or(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_BIT_AND: return _translate_binary_bit_and(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_BIT_OR: return _translate_binary_bit_or(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_BIT_XOR: return _translate_binary_bit_xor(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_SHIFT_LEFT: return _translate_binary_shift_left(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_SHIFT_RIGHT: return _translate_binary_shift_right(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_ROTATE_LEFT: return _translate_binary_rotate_left(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_ROTATE_RIGHT: return _translate_binary_rotate_right(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_LESS: return _translate_binary_less(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_GREATER: return _translate_binary_greater(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_LESS_EQUAL: return _translate_binary_less_equal(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_GREATER_EQUAL: return _translate_binary_greater_equal(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_EQUAL: return _translate_binary_equal(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::BINARY_NOT_EQUAL: return _translate_binary_not_equal(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::THREAD_ID: return current.builtin_variables[CurrentFunction::builtin_variable_index_thread_id]; + case xir::IntrinsicOp::BLOCK_ID: return current.builtin_variables[CurrentFunction::builtin_variable_index_block_id]; + case xir::IntrinsicOp::WARP_LANE_ID: return llvm::ConstantInt::get(b.getInt32Ty(), 0);// CPU only has one lane + case xir::IntrinsicOp::DISPATCH_ID: return current.builtin_variables[CurrentFunction::builtin_variable_index_dispatch_id]; + case xir::IntrinsicOp::KERNEL_ID: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::OBJECT_ID: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::BLOCK_SIZE: return current.builtin_variables[CurrentFunction::builtin_variable_index_block_size]; + case xir::IntrinsicOp::WARP_SIZE: return llvm::ConstantInt::get(b.getInt32Ty(), 1);// CPU only has one lane + case xir::IntrinsicOp::DISPATCH_SIZE: return current.builtin_variables[CurrentFunction::builtin_variable_index_dispatch_size]; + case xir::IntrinsicOp::SYNCHRONIZE_BLOCK: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::ALL: { + auto llvm_operand = _lookup_value(current, b, inst->operand(0u)); + return b.CreateAndReduce(llvm_operand); + } + case xir::IntrinsicOp::ANY: { + auto llvm_operand = _lookup_value(current, b, inst->operand(0u)); + return b.CreateOrReduce(llvm_operand); + } + case xir::IntrinsicOp::SELECT: { + // note that the order of operands is reversed + auto llvm_false_value = _lookup_value(current, b, inst->operand(0u)); + auto llvm_true_value = _lookup_value(current, b, inst->operand(1u)); + auto llvm_condition = _lookup_value(current, b, inst->operand(2u)); + auto llvm_zero = llvm::Constant::getNullValue(llvm_condition->getType()); + auto llvm_cmp = b.CreateICmpNE(llvm_condition, llvm_zero); + return b.CreateSelect(llvm_cmp, llvm_true_value, llvm_false_value); + } + case xir::IntrinsicOp::CLAMP: { + // clamp(x, lb, ub) = min(max(x, lb), ub) + auto x_type = inst->operand(0u)->type(); + auto lb_type = inst->operand(1u)->type(); + auto ub_type = inst->operand(2u)->type(); + LUISA_ASSERT(x_type != nullptr && x_type == lb_type && x_type == ub_type, "Type mismatch for clamp."); + auto llvm_x = _lookup_value(current, b, inst->operand(0u)); + auto llvm_lb = _lookup_value(current, b, inst->operand(1u)); + auto llvm_ub = _lookup_value(current, b, inst->operand(2u)); + auto elem_type = x_type->is_vector() ? x_type->element() : x_type; + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: { + auto llvm_max = b.CreateBinaryIntrinsic(llvm::Intrinsic::smax, llvm_x, llvm_lb); + return b.CreateBinaryIntrinsic(llvm::Intrinsic::smin, llvm_max, llvm_ub); + } + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: { + auto llvm_max = b.CreateBinaryIntrinsic(llvm::Intrinsic::umax, llvm_x, llvm_lb); + return b.CreateBinaryIntrinsic(llvm::Intrinsic::umin, llvm_max, llvm_ub); + } + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: { + auto llvm_max = b.CreateBinaryIntrinsic(llvm::Intrinsic::maxnum, llvm_x, llvm_lb); + return b.CreateBinaryIntrinsic(llvm::Intrinsic::minnum, llvm_max, llvm_ub); + } + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid operand type for clamp operation: {}.", x_type->description()); + } + case xir::IntrinsicOp::SATURATE: { + // saturate(x) = min(max(x, 0), 1) + auto llvm_x = _lookup_value(current, b, inst->operand(0u)); + LUISA_ASSERT(llvm_x->getType()->isFPOrFPVectorTy(), "Invalid operand type for saturate operation."); + auto llvm_zero = llvm::ConstantFP::get(llvm_x->getType(), 0.); + auto llvm_one = llvm::ConstantFP::get(llvm_x->getType(), 1.); + auto llvm_max = b.CreateBinaryIntrinsic(llvm::Intrinsic::maxnum, llvm_x, llvm_zero); + return b.CreateBinaryIntrinsic(llvm::Intrinsic::minnum, llvm_max, llvm_one); + } + case xir::IntrinsicOp::LERP: { + // lerp(a, b, t) = (b - a) * t + a = fma(t, b - a, a) + auto va_type = inst->operand(0u)->type(); + auto vb_type = inst->operand(1u)->type(); + auto t_type = inst->operand(2u)->type(); + LUISA_ASSERT(va_type != nullptr && va_type == vb_type && va_type == t_type, "Type mismatch for lerp."); + auto llvm_va = _lookup_value(current, b, inst->operand(0u)); + auto llvm_vb = _lookup_value(current, b, inst->operand(1u)); + auto llvm_t = _lookup_value(current, b, inst->operand(2u)); + LUISA_ASSERT(llvm_va->getType()->isFPOrFPVectorTy(), "Invalid operand type for lerp operation."); + auto llvm_diff = b.CreateFSub(llvm_vb, llvm_va); + return b.CreateIntrinsic(llvm_va->getType(), llvm::Intrinsic::fma, {llvm_t, llvm_diff, llvm_va}); + } + case xir::IntrinsicOp::SMOOTHSTEP: { + // smoothstep(edge0, edge1, x) = t * t * (3.0 - 2.0 * t), where t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0) + auto type = inst->type(); + LUISA_ASSERT(type != nullptr && + type == inst->operand(0u)->type() && + type == inst->operand(1u)->type() && + type == inst->operand(2u)->type(), + "Type mismatch for smoothstep."); + auto elem_type = type->is_vector() ? type->element() : type; + LUISA_ASSERT(elem_type->is_float16() || elem_type->is_float32() || elem_type->is_float64(), + "Invalid operand type for smoothstep operation."); + auto llvm_edge0 = _lookup_value(current, b, inst->operand(0u)); + auto llvm_edge1 = _lookup_value(current, b, inst->operand(1u)); + auto llvm_x = _lookup_value(current, b, inst->operand(2u)); + // constant 0, 1, -2, and 3 + auto llvm_elem_type = _translate_type(elem_type, false); + auto llvm_zero = llvm::ConstantFP::get(llvm_elem_type, 0.); + auto llvm_one = llvm::ConstantFP::get(llvm_elem_type, 1.); + auto llvm_minus_two = llvm::ConstantFP::get(llvm_elem_type, -2.); + auto llvm_three = llvm::ConstantFP::get(llvm_elem_type, 3.); + if (type->is_vector()) { + auto dim = llvm::ElementCount::getFixed(type->dimension()); + llvm_zero = llvm::ConstantVector::getSplat(dim, llvm_zero); + llvm_one = llvm::ConstantVector::getSplat(dim, llvm_one); + llvm_minus_two = llvm::ConstantVector::getSplat(dim, llvm_minus_two); + llvm_three = llvm::ConstantVector::getSplat(dim, llvm_three); + } + // t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0) + auto llvm_x_minus_edge0 = b.CreateFSub(llvm_x, llvm_edge0); + auto llvm_edge1_minus_edge0 = b.CreateFSub(llvm_edge1, llvm_edge0); + auto llvm_t = b.CreateFDiv(llvm_x_minus_edge0, llvm_edge1_minus_edge0); + // clamp t + llvm_t = b.CreateBinaryIntrinsic(llvm::Intrinsic::maxnum, llvm_zero, llvm_t); + llvm_t = b.CreateBinaryIntrinsic(llvm::Intrinsic::minnum, llvm_one, llvm_t); + // smoothstep + auto llvm_tt = b.CreateFMul(llvm_t, llvm_t); + auto llvm_three_minus_two_t = b.CreateIntrinsic(llvm_t->getType(), llvm::Intrinsic::fma, {llvm_minus_two, llvm_t, llvm_three}); + return b.CreateFMul(llvm_tt, llvm_three_minus_two_t); + } + case xir::IntrinsicOp::STEP: { + // step(edge, x) = x < edge ? 0 : 1 = uitofp(x >= edge) + auto llvm_edge = _lookup_value(current, b, inst->operand(0u)); + auto llvm_x = _lookup_value(current, b, inst->operand(1u)); + auto llvm_cmp = b.CreateFCmpOGE(llvm_x, llvm_edge); + return b.CreateUIToFP(llvm_cmp, llvm_x->getType()); + } + case xir::IntrinsicOp::ABS: { + auto llvm_x = _lookup_value(current, b, inst->operand(0u)); + auto llvm_intrinsic = llvm_x->getType()->isFPOrFPVectorTy() ? + llvm::Intrinsic::fabs : + llvm::Intrinsic::abs; + return b.CreateUnaryIntrinsic(llvm_intrinsic, llvm_x); + } + case xir::IntrinsicOp::MIN: { + auto llvm_x = _lookup_value(current, b, inst->operand(0u)); + auto llvm_y = _lookup_value(current, b, inst->operand(1u)); + auto elem_type = inst->type()->is_vector() ? inst->type()->element() : inst->type(); + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: return b.CreateBinaryIntrinsic(llvm::Intrinsic::smin, llvm_x, llvm_y); + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: return b.CreateBinaryIntrinsic(llvm::Intrinsic::umin, llvm_x, llvm_y); + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: return b.CreateBinaryIntrinsic(llvm::Intrinsic::minnum, llvm_x, llvm_y); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid operand type for min operation: {}.", + inst->type()->description()); + } + case xir::IntrinsicOp::MAX: { + auto llvm_x = _lookup_value(current, b, inst->operand(0u)); + auto llvm_y = _lookup_value(current, b, inst->operand(1u)); + auto elem_type = inst->type()->is_vector() ? inst->type()->element() : inst->type(); + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: return b.CreateBinaryIntrinsic(llvm::Intrinsic::smax, llvm_x, llvm_y); + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: return b.CreateBinaryIntrinsic(llvm::Intrinsic::umax, llvm_x, llvm_y); + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: return b.CreateBinaryIntrinsic(llvm::Intrinsic::maxnum, llvm_x, llvm_y); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid operand type for max operation: {}.", + inst->type()->description()); + } + case xir::IntrinsicOp::CLZ: { + auto llvm_x = _lookup_value(current, b, inst->operand(0u)); + return b.CreateUnaryIntrinsic(llvm::Intrinsic::ctlz, llvm_x); + } + case xir::IntrinsicOp::CTZ: { + auto llvm_x = _lookup_value(current, b, inst->operand(0u)); + return b.CreateUnaryIntrinsic(llvm::Intrinsic::cttz, llvm_x); + } + case xir::IntrinsicOp::POPCOUNT: { + auto llvm_x = _lookup_value(current, b, inst->operand(0u)); + return b.CreateUnaryIntrinsic(llvm::Intrinsic::ctpop, llvm_x); + } + case xir::IntrinsicOp::REVERSE: { + auto llvm_x = _lookup_value(current, b, inst->operand(0u)); + return b.CreateUnaryIntrinsic(llvm::Intrinsic::bitreverse, llvm_x); + } + case xir::IntrinsicOp::ISINF: return _translate_isinf_isnan(current, b, inst->op(), inst->operand(0u)); + case xir::IntrinsicOp::ISNAN: return _translate_isinf_isnan(current, b, inst->op(), inst->operand(0u)); + case xir::IntrinsicOp::ACOS: break; + case xir::IntrinsicOp::ACOSH: break; + case xir::IntrinsicOp::ASIN: break; + case xir::IntrinsicOp::ASINH: break; + case xir::IntrinsicOp::ATAN: break; + case xir::IntrinsicOp::ATAN2: break; + case xir::IntrinsicOp::ATANH: break; + case xir::IntrinsicOp::COS: return _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::cos); + case xir::IntrinsicOp::COSH: break; + case xir::IntrinsicOp::SIN: return _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::sin); + case xir::IntrinsicOp::SINH: break; + case xir::IntrinsicOp::TAN: { + auto llvm_sin = _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::sin); + auto llvm_cos = _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::cos); + return b.CreateFDiv(llvm_sin, llvm_cos); + } + case xir::IntrinsicOp::TANH: break; + case xir::IntrinsicOp::EXP: return _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::exp); + case xir::IntrinsicOp::EXP2: return _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::exp2); + case xir::IntrinsicOp::EXP10: return _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::exp10); + case xir::IntrinsicOp::LOG: return _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::log); + case xir::IntrinsicOp::LOG2: return _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::log2); + case xir::IntrinsicOp::LOG10: return _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::log10); + case xir::IntrinsicOp::POW: return _translate_binary_fp_math_operation(current, b, inst->operand(0u), inst->operand(1u), llvm::Intrinsic::pow); + case xir::IntrinsicOp::POW_INT: { + auto base = inst->operand(0u); + auto index = inst->operand(1u); + auto llvm_base = _lookup_value(current, b, base); + auto llvm_index = _lookup_value(current, b, index); + LUISA_ASSERT(llvm_base->getType()->isFPOrFPVectorTy() && + llvm_index->getType()->isIntOrIntVectorTy() && + !llvm_index->getType()->isIntOrIntVectorTy(1), + "Invalid operand type for pow_int operation."); + if (llvm_base->getType()->isVectorTy() || llvm_index->getType()->isVectorTy()) { + LUISA_ASSERT(llvm_base->getType()->isVectorTy() && llvm_index->getType()->isVectorTy() && + llvm::cast(llvm_base->getType())->getElementCount() == + llvm::cast(llvm_index->getType())->getElementCount(), + "pow_int operation requires both operands to be vectors of the same dimension."); + } + return b.CreateBinaryIntrinsic(llvm::Intrinsic::powi, llvm_base, llvm_index); + } + case xir::IntrinsicOp::SQRT: return _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::sqrt); + case xir::IntrinsicOp::RSQRT: { + auto llvm_operand = _lookup_value(current, b, inst->operand(0u)); + auto llvm_sqrt = b.CreateUnaryIntrinsic(llvm::Intrinsic::sqrt, llvm_operand); + auto operand_type = inst->operand(0u)->type(); + auto operand_elem_type = operand_type->is_vector() ? operand_type->element() : operand_type; + auto llvm_elem_type = _translate_type(operand_elem_type, false); + auto llvm_one = llvm::ConstantFP::get(llvm_elem_type, 1.f); + if (operand_type->is_vector()) { + auto dim = operand_type->dimension(); + llvm_one = llvm::ConstantVector::getSplat(llvm::ElementCount::getFixed(dim), llvm_one); + } + return b.CreateFDiv(llvm_one, llvm_sqrt); + } + case xir::IntrinsicOp::CEIL: return _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::ceil); + case xir::IntrinsicOp::FLOOR: return _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::floor); + case xir::IntrinsicOp::FRACT: { + // fract(x) = x - floor(x) + auto llvm_operand = _lookup_value(current, b, inst->operand(0u)); + auto llvm_floor = _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::floor); + return b.CreateFSub(llvm_operand, llvm_floor); + } + case xir::IntrinsicOp::TRUNC: return _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::trunc); + case xir::IntrinsicOp::ROUND: return _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::round); + case xir::IntrinsicOp::RINT: return _translate_unary_fp_math_operation(current, b, inst->operand(0u), llvm::Intrinsic::rint); + case xir::IntrinsicOp::FMA: { + // fma(a, b, c) = a * b + c, or we can use llvm intrinsic for fp + auto va = inst->operand(0u); + auto vb = inst->operand(1u); + auto vc = inst->operand(2u); + LUISA_ASSERT(va->type() != nullptr && va->type() == vb->type() && va->type() == vc->type(), "Type mismatch for fma."); + auto llvm_va = _lookup_value(current, b, va); + auto llvm_vb = _lookup_value(current, b, vb); + auto llvm_vc = _lookup_value(current, b, vc); + auto elem_type = va->type()->is_vector() ? va->type()->element() : va->type(); + switch (elem_type->tag()) { + case Type::Tag::INT8: [[fallthrough]]; + case Type::Tag::INT16: [[fallthrough]]; + case Type::Tag::INT32: [[fallthrough]]; + case Type::Tag::INT64: { + auto llvm_mul = b.CreateNSWMul(llvm_va, llvm_vb); + return b.CreateNSWAdd(llvm_mul, llvm_vc); + } + case Type::Tag::UINT8: [[fallthrough]]; + case Type::Tag::UINT16: [[fallthrough]]; + case Type::Tag::UINT32: [[fallthrough]]; + case Type::Tag::UINT64: { + auto llvm_mul = b.CreateMul(llvm_va, llvm_vb); + return b.CreateAdd(llvm_mul, llvm_vc); + } + case Type::Tag::FLOAT16: [[fallthrough]]; + case Type::Tag::FLOAT32: [[fallthrough]]; + case Type::Tag::FLOAT64: { + return b.CreateIntrinsic(llvm_va->getType(), llvm::Intrinsic::fma, {llvm_va, llvm_vb, llvm_vc}); + } + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid operand type for fma operation: {}.", va->type()->description()); + } + case xir::IntrinsicOp::COPYSIGN: return _translate_binary_fp_math_operation(current, b, inst->operand(0u), inst->operand(1u), llvm::Intrinsic::copysign); + case xir::IntrinsicOp::CROSS: { + // cross(u, v) = (u.y * v.z - v.y * u.z, u.z * v.x - v.z * u.x, u.x * v.y - v.x * u.y) + auto u = _lookup_value(current, b, inst->operand(0u)); + auto v = _lookup_value(current, b, inst->operand(1u)); + auto poison = llvm::PoisonValue::get(u->getType()); + auto s0 = b.CreateShuffleVector(u, poison, {1, 2, 0}); + auto s1 = b.CreateShuffleVector(v, poison, {2, 0, 1}); + auto s2 = b.CreateShuffleVector(v, poison, {1, 2, 0}); + auto s3 = b.CreateShuffleVector(u, poison, {2, 0, 1}); + auto s01 = b.CreateFMul(s0, s1); + auto s23 = b.CreateFMul(s2, s3); + return b.CreateFSub(s01, s23); + } + case xir::IntrinsicOp::DOT: return _translate_vector_dot(current, b, inst->operand(0u), inst->operand(1u)); + case xir::IntrinsicOp::LENGTH: { + auto v = inst->operand(0u); + auto llvm_length_squared = _translate_vector_dot(current, b, v, v); + return b.CreateUnaryIntrinsic(llvm::Intrinsic::sqrt, llvm_length_squared); + } + case xir::IntrinsicOp::LENGTH_SQUARED: { + auto v = inst->operand(0u); + return _translate_vector_dot(current, b, v, v); + } + case xir::IntrinsicOp::NORMALIZE: { + auto v = inst->operand(0u); + auto llvm_length_squared = _translate_vector_dot(current, b, v, v); + auto llvm_length = b.CreateUnaryIntrinsic(llvm::Intrinsic::sqrt, llvm_length_squared); + auto llvm_v = _lookup_value(current, b, v); + auto llvm_length_splat = b.CreateVectorSplat(v->type()->dimension(), llvm_length); + return b.CreateFDiv(llvm_v, llvm_length_splat); + } + case xir::IntrinsicOp::FACEFORWARD: { + // faceforward(n, i, n_ref) = dot(i, n_ref) < 0 ? n : -n + auto n = inst->operand(0u); + auto i = inst->operand(1u); + auto n_ref = inst->operand(2u); + auto llvm_dot = _translate_vector_dot(current, b, i, n_ref); + auto llvm_zero = llvm::ConstantFP::get(llvm_dot->getType(), 0.); + auto llvm_cmp = b.CreateFCmpOLT(llvm_dot, llvm_zero); + auto llvm_pos_n = _lookup_value(current, b, n); + auto llvm_neg_n = b.CreateFNeg(llvm_pos_n); + return b.CreateSelect(llvm_cmp, llvm_pos_n, llvm_neg_n); + } + case xir::IntrinsicOp::REFLECT: { + // reflect(I, N) = I - 2.0 * dot(N, I) * N = fma(splat(-2.0 * dot(N, I)), N, I) + auto i = inst->operand(0u); + auto n = inst->operand(1u); + auto llvm_dot = _translate_vector_dot(current, b, n, i); + auto llvm_i = _lookup_value(current, b, i); + auto llvm_n = _lookup_value(current, b, n); + auto dim = llvm::cast(llvm_n->getType())->getElementCount(); + auto llvm_minus_two = llvm::ConstantFP::get(llvm_dot->getType(), -2.); + auto llvm_minus_two_dot = b.CreateFMul(llvm_minus_two, llvm_dot); + llvm_minus_two_dot = b.CreateVectorSplat(dim, llvm_minus_two_dot); + return b.CreateIntrinsic(llvm_n->getType(), llvm::Intrinsic::fma, + {llvm_minus_two_dot, llvm_n, llvm_i}); + } + case xir::IntrinsicOp::REDUCE_SUM: return _translate_vector_reduce(current, b, xir::IntrinsicOp::REDUCE_SUM, inst->operand(0u)); + case xir::IntrinsicOp::REDUCE_PRODUCT: return _translate_vector_reduce(current, b, xir::IntrinsicOp::REDUCE_PRODUCT, inst->operand(0u)); + case xir::IntrinsicOp::REDUCE_MIN: return _translate_vector_reduce(current, b, xir::IntrinsicOp::REDUCE_MIN, inst->operand(0u)); + case xir::IntrinsicOp::REDUCE_MAX: return _translate_vector_reduce(current, b, xir::IntrinsicOp::REDUCE_MAX, inst->operand(0u)); + case xir::IntrinsicOp::OUTER_PRODUCT: break; + case xir::IntrinsicOp::MATRIX_COMP_NEG: break; + case xir::IntrinsicOp::MATRIX_COMP_ADD: break; + case xir::IntrinsicOp::MATRIX_COMP_SUB: break; + case xir::IntrinsicOp::MATRIX_COMP_MUL: break; + case xir::IntrinsicOp::MATRIX_COMP_DIV: break; + case xir::IntrinsicOp::MATRIX_LINALG_MUL: break; + case xir::IntrinsicOp::MATRIX_DETERMINANT: break; + case xir::IntrinsicOp::MATRIX_TRANSPOSE: break; + case xir::IntrinsicOp::MATRIX_INVERSE: break; + case xir::IntrinsicOp::ATOMIC_EXCHANGE: break; + case xir::IntrinsicOp::ATOMIC_COMPARE_EXCHANGE: break; + case xir::IntrinsicOp::ATOMIC_FETCH_ADD: break; + case xir::IntrinsicOp::ATOMIC_FETCH_SUB: break; + case xir::IntrinsicOp::ATOMIC_FETCH_AND: break; + case xir::IntrinsicOp::ATOMIC_FETCH_OR: break; + case xir::IntrinsicOp::ATOMIC_FETCH_XOR: break; + case xir::IntrinsicOp::ATOMIC_FETCH_MIN: break; + case xir::IntrinsicOp::ATOMIC_FETCH_MAX: break; + case xir::IntrinsicOp::BUFFER_READ: return _translate_buffer_read(current, b, inst); + case xir::IntrinsicOp::BUFFER_WRITE: return _translate_buffer_write(current, b, inst); + case xir::IntrinsicOp::BUFFER_SIZE: return _translate_buffer_size(current, b, inst); + case xir::IntrinsicOp::BYTE_BUFFER_READ: return _translate_buffer_read(current, b, inst, true); + case xir::IntrinsicOp::BYTE_BUFFER_WRITE: return _translate_buffer_write(current, b, inst, true); + case xir::IntrinsicOp::BYTE_BUFFER_SIZE: return _translate_buffer_size(current, b, inst, true); + case xir::IntrinsicOp::TEXTURE2D_READ: return _translate_texture_read(current, b, inst); + case xir::IntrinsicOp::TEXTURE2D_WRITE: return _translate_texture_write(current, b, inst->operand(0u), inst->operand(1u), inst->operand(2u)); + case xir::IntrinsicOp::TEXTURE2D_SIZE: break; + case xir::IntrinsicOp::TEXTURE2D_SAMPLE: break; + case xir::IntrinsicOp::TEXTURE2D_SAMPLE_LEVEL: break; + case xir::IntrinsicOp::TEXTURE2D_SAMPLE_GRAD: break; + case xir::IntrinsicOp::TEXTURE2D_SAMPLE_GRAD_LEVEL: break; + case xir::IntrinsicOp::TEXTURE3D_READ: break; + case xir::IntrinsicOp::TEXTURE3D_WRITE: break; + case xir::IntrinsicOp::TEXTURE3D_SIZE: break; + case xir::IntrinsicOp::TEXTURE3D_SAMPLE: break; + case xir::IntrinsicOp::TEXTURE3D_SAMPLE_LEVEL: break; + case xir::IntrinsicOp::TEXTURE3D_SAMPLE_GRAD: break; + case xir::IntrinsicOp::TEXTURE3D_SAMPLE_GRAD_LEVEL: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE2D_SAMPLE: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE2D_SAMPLE_LEVEL: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE2D_SAMPLE_GRAD: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE2D_SAMPLE_GRAD_LEVEL: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE3D_SAMPLE: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE3D_SAMPLE_LEVEL: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE3D_SAMPLE_GRAD: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE3D_SAMPLE_GRAD_LEVEL: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE2D_SAMPLE_SAMPLER: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE2D_SAMPLE_LEVEL_SAMPLER: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE2D_SAMPLE_GRAD_SAMPLER: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE2D_SAMPLE_GRAD_LEVEL_SAMPLER: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE3D_SAMPLE_SAMPLER: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE3D_SAMPLE_LEVEL_SAMPLER: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE3D_SAMPLE_GRAD_SAMPLER: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE3D_SAMPLE_GRAD_LEVEL_SAMPLER: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE2D_READ: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE3D_READ: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE2D_READ_LEVEL: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE3D_READ_LEVEL: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE2D_SIZE: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE3D_SIZE: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE2D_SIZE_LEVEL: break; + case xir::IntrinsicOp::BINDLESS_TEXTURE3D_SIZE_LEVEL: break; + case xir::IntrinsicOp::BINDLESS_BUFFER_READ: return _translate_bindless_read(current, b, inst); + case xir::IntrinsicOp::BINDLESS_BUFFER_WRITE: break; + case xir::IntrinsicOp::BINDLESS_BUFFER_SIZE: break; + case xir::IntrinsicOp::BINDLESS_BUFFER_TYPE: break; + case xir::IntrinsicOp::BINDLESS_BYTE_BUFFER_READ: break; + case xir::IntrinsicOp::BINDLESS_BYTE_BUFFER_WRITE: break; + case xir::IntrinsicOp::BINDLESS_BYTE_BUFFER_SIZE: break; + case xir::IntrinsicOp::BUFFER_DEVICE_ADDRESS: return _translate_buffer_device_address(current, b, inst); + case xir::IntrinsicOp::BINDLESS_BUFFER_DEVICE_ADDRESS: break; + case xir::IntrinsicOp::DEVICE_ADDRESS_READ: return _translate_device_address_read(current, b, inst); + case xir::IntrinsicOp::DEVICE_ADDRESS_WRITE: return _translate_device_address_write(current, b, inst); + case xir::IntrinsicOp::AGGREGATE: return _translate_aggregate(current, b, inst); + case xir::IntrinsicOp::SHUFFLE: return _translate_shuffle(current, b, inst); + case xir::IntrinsicOp::INSERT: return _translate_insert(current, b, inst); + case xir::IntrinsicOp::EXTRACT: return _translate_extract(current, b, inst); + case xir::IntrinsicOp::AUTODIFF_REQUIRES_GRADIENT: break; + case xir::IntrinsicOp::AUTODIFF_GRADIENT: break; + case xir::IntrinsicOp::AUTODIFF_GRADIENT_MARKER: break; + case xir::IntrinsicOp::AUTODIFF_ACCUMULATE_GRADIENT: break; + case xir::IntrinsicOp::AUTODIFF_BACKWARD: break; + case xir::IntrinsicOp::AUTODIFF_DETACH: break; + case xir::IntrinsicOp::RAY_TRACING_INSTANCE_TRANSFORM: break; + case xir::IntrinsicOp::RAY_TRACING_INSTANCE_USER_ID: break; + case xir::IntrinsicOp::RAY_TRACING_INSTANCE_VISIBILITY_MASK: break; + case xir::IntrinsicOp::RAY_TRACING_SET_INSTANCE_TRANSFORM: break; + case xir::IntrinsicOp::RAY_TRACING_SET_INSTANCE_VISIBILITY: break; + case xir::IntrinsicOp::RAY_TRACING_SET_INSTANCE_OPACITY: break; + case xir::IntrinsicOp::RAY_TRACING_SET_INSTANCE_USER_ID: break; + case xir::IntrinsicOp::RAY_TRACING_TRACE_CLOSEST: return _translate_accel_trace(current, b, inst); + case xir::IntrinsicOp::RAY_TRACING_TRACE_ANY: break; + case xir::IntrinsicOp::RAY_TRACING_QUERY_ALL: break; + case xir::IntrinsicOp::RAY_TRACING_QUERY_ANY: break; + case xir::IntrinsicOp::RAY_TRACING_INSTANCE_MOTION_MATRIX: break; + case xir::IntrinsicOp::RAY_TRACING_INSTANCE_MOTION_SRT: break; + case xir::IntrinsicOp::RAY_TRACING_SET_INSTANCE_MOTION_MATRIX: break; + case xir::IntrinsicOp::RAY_TRACING_SET_INSTANCE_MOTION_SRT: break; + case xir::IntrinsicOp::RAY_TRACING_TRACE_CLOSEST_MOTION_BLUR: break; + case xir::IntrinsicOp::RAY_TRACING_TRACE_ANY_MOTION_BLUR: break; + case xir::IntrinsicOp::RAY_TRACING_QUERY_ALL_MOTION_BLUR: break; + case xir::IntrinsicOp::RAY_TRACING_QUERY_ANY_MOTION_BLUR: break; + case xir::IntrinsicOp::RAY_QUERY_WORLD_SPACE_RAY: break; + case xir::IntrinsicOp::RAY_QUERY_PROCEDURAL_CANDIDATE_HIT: break; + case xir::IntrinsicOp::RAY_QUERY_TRIANGLE_CANDIDATE_HIT: break; + case xir::IntrinsicOp::RAY_QUERY_COMMITTED_HIT: break; + case xir::IntrinsicOp::RAY_QUERY_COMMIT_TRIANGLE: break; + case xir::IntrinsicOp::RAY_QUERY_COMMIT_PROCEDURAL: break; + case xir::IntrinsicOp::RAY_QUERY_TERMINATE: break; + case xir::IntrinsicOp::RAY_QUERY_PROCEED: break; + case xir::IntrinsicOp::RAY_QUERY_IS_TRIANGLE_CANDIDATE: break; + case xir::IntrinsicOp::RAY_QUERY_IS_PROCEDURAL_CANDIDATE: break; + case xir::IntrinsicOp::RASTER_DISCARD: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::RASTER_DDX: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::RASTER_DDY: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_IS_FIRST_ACTIVE_LANE: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_FIRST_ACTIVE_LANE: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_ACTIVE_ALL_EQUAL: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_ACTIVE_BIT_AND: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_ACTIVE_BIT_OR: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_ACTIVE_BIT_XOR: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_ACTIVE_COUNT_BITS: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_ACTIVE_MAX: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_ACTIVE_MIN: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_ACTIVE_PRODUCT: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_ACTIVE_SUM: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_ACTIVE_ALL: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_ACTIVE_ANY: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_ACTIVE_BIT_MASK: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_PREFIX_COUNT_BITS: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_PREFIX_SUM: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_PREFIX_PRODUCT: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_READ_LANE: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::WARP_READ_FIRST_ACTIVE_LANE: LUISA_NOT_IMPLEMENTED(); + case xir::IntrinsicOp::INDIRECT_DISPATCH_SET_KERNEL: break; + case xir::IntrinsicOp::INDIRECT_DISPATCH_SET_COUNT: break; + case xir::IntrinsicOp::SHADER_EXECUTION_REORDER: return nullptr;// no-op on the LLVM side + } + LUISA_INFO("unsupported intrinsic op type:{}", static_cast(inst->op())); + LUISA_NOT_IMPLEMENTED(); + // TODO: implement + if (auto llvm_ret_type = _translate_type(inst->type(), true)) { + return llvm::Constant::getNullValue(llvm_ret_type); + } + return nullptr; + } + + [[nodiscard]] llvm::Value *_translate_cast_inst(CurrentFunction ¤t, IRBuilder &b, + const Type *dst_type, xir::CastOp op, + const xir::Value *src_value) noexcept { + auto llvm_value = _lookup_value(current, b, src_value); + auto src_type = src_value->type(); + switch (op) { + case xir::CastOp::STATIC_CAST: { + if (dst_type == src_type) { return llvm_value; } + LUISA_ASSERT((dst_type->is_scalar() && src_type->is_scalar()) || + (dst_type->is_vector() && src_type->is_vector() && + dst_type->dimension() == src_type->dimension()), + "Invalid static cast."); + auto dst_is_scalar = dst_type->is_scalar(); + auto src_is_scalar = src_type->is_scalar(); + auto dst_elem_type = dst_is_scalar ? dst_type : dst_type->element(); + auto src_elem_type = src_is_scalar ? src_type : src_type->element(); + // typeN -> boolN + if (dst_elem_type->is_bool()) { + auto cmp = _cmp_ne_zero(b, llvm_value); + return _zext_i1_to_i8(b, cmp); + } + // general case + auto classify = [](const Type *t) noexcept { + return std::make_tuple( + t->is_float16() || t->is_float32() || t->is_float64(), + t->is_int8() || t->is_int16() || t->is_int32() || t->is_int64(), + t->is_uint8() || t->is_uint16() || t->is_uint32() || t->is_uint64() || t->is_bool()); + }; + auto llvm_dst_type = _translate_type(dst_type, true); + auto [dst_float, dst_int, dst_uint] = classify(dst_elem_type); + auto [src_float, src_int, src_uint] = classify(src_elem_type); + if (dst_float) { + if (src_float) { return b.CreateFPCast(llvm_value, llvm_dst_type); } + if (src_int) { return b.CreateSIToFP(llvm_value, llvm_dst_type); } + if (src_uint) { return b.CreateUIToFP(llvm_value, llvm_dst_type); } + } + if (dst_int) { + if (src_float) { return b.CreateFPToSI(llvm_value, llvm_dst_type); } + if (src_int) { return b.CreateIntCast(llvm_value, llvm_dst_type, true); } + if (src_uint) { return b.CreateIntCast(llvm_value, llvm_dst_type, false); } + } + if (dst_uint) { + if (src_float) { return b.CreateFPToUI(llvm_value, llvm_dst_type); } + if (src_int) { return b.CreateIntCast(llvm_value, llvm_dst_type, true); } + if (src_uint) { return b.CreateIntCast(llvm_value, llvm_dst_type, false); } + } + LUISA_ERROR_WITH_LOCATION("Invalid static cast."); + } + case xir::CastOp::BITWISE_CAST: { + // create a temporary alloca + auto alignment = std::max(_get_type_alignment(src_type), + _get_type_alignment(dst_type)); + LUISA_ASSERT(_get_type_size(src_type) == _get_type_size(dst_type), "Bitwise cast size mismatch."); + auto llvm_src_type = _translate_type(src_type, true); + auto llvm_dst_type = _translate_type(dst_type, true); + auto llvm_temp = b.CreateAlloca(llvm_src_type); + if (llvm_temp->getAlign() < alignment) { + llvm_temp->setAlignment(llvm::Align{alignment}); + } + // store src value + b.CreateAlignedStore(llvm_value, llvm_temp, llvm::MaybeAlign{alignment}); + // load dst value + return b.CreateAlignedLoad(llvm_dst_type, llvm_temp, llvm::MaybeAlign{alignment}); + } + } + LUISA_ERROR_WITH_LOCATION("Invalid cast operation."); + } + + [[nodiscard]] llvm::Value *_translate_instruction(CurrentFunction ¤t, IRBuilder &b, const xir::Instruction *inst) noexcept { + switch (inst->derived_instruction_tag()) { + case xir::DerivedInstructionTag::SENTINEL: { + LUISA_ERROR_WITH_LOCATION("Invalid instruction."); + } + case xir::DerivedInstructionTag::IF: { + auto if_inst = static_cast(inst); + auto llvm_condition = _lookup_value(current, b, if_inst->condition()); + auto llvm_false = b.getInt8(0); + llvm_condition = b.CreateICmpNE(llvm_condition, llvm_false); + auto llvm_true_block = _find_or_create_basic_block(current, if_inst->true_block()); + auto llvm_false_block = _find_or_create_basic_block(current, if_inst->false_block()); + auto llvm_merge_block = _find_or_create_basic_block(current, if_inst->merge_block()); + auto llvm_inst = b.CreateCondBr(llvm_condition, llvm_true_block, llvm_false_block); + _translate_instructions_in_basic_block(current, llvm_true_block, if_inst->true_block()); + _translate_instructions_in_basic_block(current, llvm_false_block, if_inst->false_block()); + _translate_instructions_in_basic_block(current, llvm_merge_block, if_inst->merge_block()); + return llvm_inst; + } + case xir::DerivedInstructionTag::SWITCH: { + auto switch_inst = static_cast(inst); + auto llvm_condition = _lookup_value(current, b, switch_inst->value()); + auto llvm_merge_block = _find_or_create_basic_block(current, switch_inst->merge_block()); + auto llvm_default_block = _find_or_create_basic_block(current, switch_inst->default_block()); + auto llvm_inst = b.CreateSwitch(llvm_condition, llvm_default_block, switch_inst->case_count()); + for (auto i = 0u; i < switch_inst->case_count(); i++) { + auto case_value = switch_inst->case_value(i); + auto llvm_case_value = b.getInt32(case_value); + auto llvm_case_block = _find_or_create_basic_block(current, switch_inst->case_block(i)); + llvm_inst->addCase(llvm_case_value, llvm_case_block); + } + _translate_instructions_in_basic_block(current, llvm_default_block, switch_inst->default_block()); + for (auto &case_block_use : switch_inst->case_block_uses()) { + auto case_block = static_cast(case_block_use->value()); + auto llvm_case_block = _find_or_create_basic_block(current, case_block); + _translate_instructions_in_basic_block(current, llvm_case_block, case_block); + } + _translate_instructions_in_basic_block(current, llvm_merge_block, switch_inst->merge_block()); + return llvm_inst; + } + case xir::DerivedInstructionTag::LOOP: { + auto loop_inst = static_cast(inst); + auto llvm_merge_block = _find_or_create_basic_block(current, loop_inst->merge_block()); + auto llvm_prepare_block = _find_or_create_basic_block(current, loop_inst->prepare_block()); + auto llvm_body_block = _find_or_create_basic_block(current, loop_inst->body_block()); + auto llvm_update_block = _find_or_create_basic_block(current, loop_inst->update_block()); + auto llvm_inst = b.CreateBr(llvm_prepare_block); + _translate_instructions_in_basic_block(current, llvm_prepare_block, loop_inst->prepare_block()); + _translate_instructions_in_basic_block(current, llvm_body_block, loop_inst->body_block()); + _translate_instructions_in_basic_block(current, llvm_update_block, loop_inst->update_block()); + _translate_instructions_in_basic_block(current, llvm_merge_block, loop_inst->merge_block()); + return llvm_inst; + } + case xir::DerivedInstructionTag::SIMPLE_LOOP: { + auto loop_inst = static_cast(inst); + auto llvm_merge_block = _find_or_create_basic_block(current, loop_inst->merge_block()); + auto llvm_body_block = _find_or_create_basic_block(current, loop_inst->body_block()); + auto llvm_inst = b.CreateBr(llvm_body_block); + _translate_instructions_in_basic_block(current, llvm_body_block, loop_inst->body_block()); + _translate_instructions_in_basic_block(current, llvm_merge_block, loop_inst->merge_block()); + return llvm_inst; + } + case xir::DerivedInstructionTag::CONDITIONAL_BRANCH: { + auto cond_br_inst = static_cast(inst); + auto llvm_condition = _lookup_value(current, b, cond_br_inst->condition()); + auto llvm_false = b.getInt8(0); + llvm_condition = b.CreateICmpNE(llvm_condition, llvm_false); + auto llvm_true_block = _find_or_create_basic_block(current, cond_br_inst->true_block()); + auto llvm_false_block = _find_or_create_basic_block(current, cond_br_inst->false_block()); + return b.CreateCondBr(llvm_condition, llvm_true_block, llvm_false_block); + } + case xir::DerivedInstructionTag::UNREACHABLE: { + LUISA_ASSERT(inst->type() == nullptr, "Unreachable instruction should not have a type."); + return b.CreateUnreachable(); + } + case xir::DerivedInstructionTag::BRANCH: [[fallthrough]]; + case xir::DerivedInstructionTag::BREAK: [[fallthrough]]; + case xir::DerivedInstructionTag::CONTINUE: { + auto br_inst = static_cast(inst); + auto llvm_target_block = _find_or_create_basic_block(current, br_inst->target_block()); + return b.CreateBr(llvm_target_block); + } + case xir::DerivedInstructionTag::RETURN: { + auto return_inst = static_cast(inst); + if (auto ret_val = return_inst->return_value()) { + auto llvm_ret_val = _lookup_value(current, b, ret_val); + return b.CreateRet(llvm_ret_val); + } + return b.CreateRetVoid(); + } + case xir::DerivedInstructionTag::PHI: { + LUISA_ERROR_WITH_LOCATION("Unexpected phi instruction. Please run reg2mem pass first."); + } + case xir::DerivedInstructionTag::ALLOCA: { + auto llvm_type = _translate_type(inst->type(), false); + auto llvm_inst = b.CreateAlloca(llvm_type); + auto alignment = _get_type_alignment(inst->type()); + if (llvm_inst->getAlign() < alignment) { + llvm_inst->setAlignment(llvm::Align{alignment}); + } + return llvm_inst; + } + case xir::DerivedInstructionTag::LOAD: { + auto load_inst = static_cast(inst); + auto alignment = _get_type_alignment(load_inst->variable()->type()); + auto llvm_type = _translate_type(load_inst->type(), true); + auto llvm_ptr = _lookup_value(current, b, load_inst->variable()); + return b.CreateAlignedLoad(llvm_type, llvm_ptr, llvm::MaybeAlign{alignment}); + } + case xir::DerivedInstructionTag::STORE: { + auto store_inst = static_cast(inst); + auto alignment = _get_type_alignment(store_inst->variable()->type()); + auto ptr = store_inst->variable(); + auto value = store_inst->value(); + auto llvm_ptr = _lookup_value(current, b, ptr); + auto llvm_value = _lookup_value(current, b, value); + return b.CreateAlignedStore(llvm_value, llvm_ptr, llvm::MaybeAlign{alignment}); + } + case xir::DerivedInstructionTag::GEP: { + auto gep_inst = static_cast(inst); + auto ptr = gep_inst->base(); + auto llvm_ptr = _lookup_value(current, b, ptr, false); + return _translate_gep(current, b, gep_inst->type(), ptr->type(), llvm_ptr, gep_inst->index_uses()); + } + case xir::DerivedInstructionTag::CALL: { + auto call_inst = static_cast(inst); + auto llvm_func = llvm::cast(_lookup_value(current, b, call_inst->callee())); + llvm::SmallVector llvm_args; + llvm_args.reserve(call_inst->argument_count()); + for (auto i = 0u; i < call_inst->argument_count(); i++) { + auto llvm_arg = _lookup_value(current, b, call_inst->argument(i)); + llvm_args.emplace_back(llvm_arg); + } + // built-in variables + for (auto &builtin_variable : current.builtin_variables) { + llvm_args.emplace_back(builtin_variable); + } + return b.CreateCall(llvm_func, llvm_args); + } + case xir::DerivedInstructionTag::INTRINSIC: { + auto intrinsic_inst = static_cast(inst); + return _translate_intrinsic_inst(current, b, intrinsic_inst); + } + case xir::DerivedInstructionTag::CAST: { + auto cast_inst = static_cast(inst); + return _translate_cast_inst(current, b, cast_inst->type(), cast_inst->op(), cast_inst->value()); + } + case xir::DerivedInstructionTag::PRINT: { + LUISA_WARNING_WITH_LOCATION("Ignoring print instruction.");// TODO... + return nullptr; + } + case xir::DerivedInstructionTag::ASSERT: { + auto assert_inst = static_cast(inst); + auto llvm_condition = _lookup_value(current, b, assert_inst->condition()); + auto llvm_message = _translate_string_or_null(b, assert_inst->message()); + auto llvm_void_type = llvm::Type::getVoidTy(_llvm_context); + auto assert_func_type = llvm::FunctionType::get(llvm_void_type, {llvm_condition->getType(), llvm_message->getType()}, false); + auto external_assert = _llvm_module->getOrInsertFunction("luisa.assert", assert_func_type); + auto external_assert_signature = llvm::cast(external_assert.getCallee()); + external_assert_signature->addFnAttr(llvm::Attribute::NoCapture); + external_assert_signature->addFnAttr(llvm::Attribute::ReadOnly); + return b.CreateCall(external_assert, {llvm_condition, llvm_message}); + } + case xir::DerivedInstructionTag::ASSUME: { + auto assume_inst = static_cast(inst); + auto llvm_condition = _lookup_value(current, b, assume_inst->condition()); + // TODO: we ignore assumption message for now + return b.CreateAssumption(llvm_condition); + } + case xir::DerivedInstructionTag::OUTLINE: { + auto outline_inst = static_cast(inst); + auto llvm_target_block = _find_or_create_basic_block(current, outline_inst->target_block()); + auto llvm_merge_block = _find_or_create_basic_block(current, outline_inst->merge_block()); + auto llvm_inst = b.CreateBr(llvm_target_block); + _translate_instructions_in_basic_block(current, llvm_target_block, outline_inst->target_block()); + _translate_instructions_in_basic_block(current, llvm_merge_block, outline_inst->merge_block()); + return llvm_inst; + } + case xir::DerivedInstructionTag::AUTO_DIFF: LUISA_NOT_IMPLEMENTED(); + case xir::DerivedInstructionTag::RAY_QUERY: LUISA_NOT_IMPLEMENTED(); + } + LUISA_ERROR_WITH_LOCATION("Invalid instruction."); + } + + [[nodiscard]] llvm::BasicBlock *_find_or_create_basic_block(CurrentFunction ¤t, const xir::BasicBlock *bb) noexcept { + auto iter = current.value_map.try_emplace(bb, nullptr).first; + if (iter->second) { return llvm::cast(iter->second); } + auto llvm_bb = llvm::BasicBlock::Create(_llvm_context, _get_name_from_metadata(bb), current.func); + iter->second = llvm_bb; + return llvm_bb; + } + + void _translate_instructions_in_basic_block(CurrentFunction ¤t, llvm::BasicBlock *llvm_bb, const xir::BasicBlock *bb) noexcept { + if (current.translated_basic_blocks.emplace(llvm_bb).second) { + for (auto &inst : bb->instructions()) { + IRBuilder b{llvm_bb}; + auto llvm_value = _translate_instruction(current, b, &inst); + auto [_, success] = current.value_map.emplace(&inst, llvm_value); + LUISA_ASSERT(success, "Instruction already translated."); + } + } + } + + [[nodiscard]] llvm::BasicBlock *_translate_basic_block(CurrentFunction ¤t, const xir::BasicBlock *bb) noexcept { + auto llvm_bb = _find_or_create_basic_block(current, bb); + _translate_instructions_in_basic_block(current, llvm_bb, bb); + return llvm_bb; + } + + [[nodiscard]] llvm::Function *_translate_kernel_function(const xir::KernelFunction *f) noexcept { + // create a wrapper function for the kernel with the following template: + // struct Params { params... }; + // struct LaunchConfig { + // uint3 block_id; + // uint3 dispatch_size; + // uint3 block_size; + // }; + // void kernel_wrapper(Params *params, LaunchConfig *config) { + // entry: + // block_id = config->block_id; + // block_size = config->block_size; + // /* assume(block_size == f.block_size) */ + // dispatch_size = config->dispatch_size; + // thread_count = block_size.x * block_size.y * block_size.z; + // pi = alloca i32; + // store 0, pi; + // br loop; + // loop: + // i = load pi; + // thread_id_x = i % block_size.x; + // thread_id_y = (i / block_size.x) % block_size.y; + // thread_id_z = i / (block_size.x * block_size.y); + // thread_id = (thread_id_x, thread_id_y, thread_id_z); + // dispatch_id = block_id * block_size + thread_id; + // in_range = reduce_and(dispatch_id < dispatch_size); + // br in_range, body, update; + // body: + // call f(params, thread_id, block_id, dispatch_id, block_size, dispatch_size); + // br update; + // update: + // next_i = i + 1; + // store next_i, pi; + // br next_i < thread_count, loop, merge; + // merge: + // ret; + + // create the kernel function + auto llvm_kernel = _translate_function_definition(f, llvm::Function::PrivateLinkage, "kernel"); + + // create the wrapper function + auto llvm_void_type = llvm::Type::getVoidTy(_llvm_context); + auto llvm_ptr_type = llvm::PointerType::get(_llvm_context, 0); + auto function_name = luisa::format("kernel.main", luisa::string_view{llvm_kernel->getName()}); + auto llvm_wrapper_type = llvm::FunctionType::get(llvm_void_type, {llvm_ptr_type, llvm_ptr_type}, false); + auto llvm_wrapper_function = llvm::Function::Create(llvm_wrapper_type, llvm::Function::ExternalLinkage, llvm::Twine{function_name}, _llvm_module); + llvm_wrapper_function->getArg(0)->setName("launch.params"); + llvm_wrapper_function->getArg(1)->setName("launch.config"); + _llvm_functions.emplace(f, llvm_wrapper_function); + + // create the entry block for the wrapper function + auto llvm_entry_block = llvm::BasicBlock::Create(_llvm_context, "entry", llvm_wrapper_function); + IRBuilder b{llvm_entry_block}; + + auto arg_count = f->arguments().size(); + + // create the params struct type + auto llvm_i8_type = llvm::Type::getInt8Ty(_llvm_context); + llvm::SmallVector padded_param_indices; + llvm::SmallVector llvm_param_types; + constexpr auto param_alignment = 16u; + auto param_size_accum = static_cast(0); + for (auto i = 0u; i < arg_count; i++) { + auto arg_type = f->arguments()[i]->type(); + LUISA_ASSERT(_get_type_alignment(arg_type) <= param_alignment, "Invalid argument alignment."); + auto param_offset = luisa::align(param_size_accum, param_alignment); + // pad if necessary + if (param_offset > param_size_accum) { + auto llvm_padding_type = llvm::ArrayType::get(llvm_i8_type, param_offset - param_size_accum); + llvm_param_types.emplace_back(llvm_padding_type); + } + padded_param_indices.emplace_back(llvm_param_types.size()); + auto param_type = _translate_type(arg_type, false); + llvm_param_types.emplace_back(param_type); + param_size_accum = param_offset + _get_type_size(arg_type);//so evil, save me please + } + // pad the last argument + if (auto total_size = luisa::align(param_size_accum, param_alignment); + total_size > param_size_accum) { + auto llvm_padding_type = llvm::ArrayType::get(llvm_i8_type, total_size - param_size_accum); + llvm_param_types.emplace_back(llvm_padding_type); + } + auto llvm_params_struct_type = llvm::StructType::create(_llvm_context, llvm_param_types, "LaunchParams"); + // load the params + auto llvm_param_ptr = llvm_wrapper_function->getArg(0); + llvm::SmallVector llvm_args; + for (auto i = 0u; i < arg_count; i++) { + auto arg_type = f->arguments()[i]->type(); + auto padded_index = padded_param_indices[i]; + auto arg_name = luisa::format("arg{}", i); + auto llvm_gep = b.CreateStructGEP(llvm_params_struct_type, llvm_param_ptr, padded_index, + llvm::Twine{arg_name}.concat(".ptr")); + auto llvm_arg_type = _translate_type(arg_type, true); + auto llvm_arg = b.CreateAlignedLoad(llvm_arg_type, llvm_gep, + llvm::MaybeAlign{_get_type_alignment(arg_type)}, + llvm::Twine{arg_name}); + llvm_args.emplace_back(llvm_arg); + } + // load the launch config + auto llvm_builtin_storage_type = _translate_type(Type::of(), false); + auto llvm_launch_config_struct_type = llvm::StructType::create( + _llvm_context, + { + llvm_builtin_storage_type,// block_id + llvm_builtin_storage_type,// dispatch_size + llvm_builtin_storage_type,// block_size (optionally read) + }, + "LaunchConfig"); + auto llvm_i32_type = llvm::Type::getInt32Ty(_llvm_context); + auto llvm_builtin_type = llvm::VectorType::get(llvm_i32_type, 3, false); + auto llvm_config_ptr = llvm_wrapper_function->getArg(1); + auto load_builtin = [&](const char *name, size_t index) noexcept { + auto llvm_gep = b.CreateStructGEP(llvm_launch_config_struct_type, llvm_config_ptr, index, llvm::Twine{name}.concat(".ptr")); + return b.CreateAlignedLoad(llvm_builtin_type, llvm_gep, llvm::MaybeAlign{alignof(uint3)}, llvm::Twine{name}); + }; + auto llvm_block_id = load_builtin("block_id", 0); + auto llvm_dispatch_size = load_builtin("dispatch_size", 1); + auto static_block_size = f->block_size(); + auto llvm_block_size = !all(static_block_size == 0u) ? + llvm::cast(_translate_literal(Type::of(), &static_block_size, true)) : + llvm::cast(load_builtin("block_size", 2)); + // compute number of threads per block + auto llvm_block_size_x = b.CreateExtractElement(llvm_block_size, static_cast(0)); + auto llvm_block_size_y = b.CreateExtractElement(llvm_block_size, static_cast(1)); + auto llvm_block_size_z = b.CreateExtractElement(llvm_block_size, static_cast(2)); + // hint that block size is power of two if we are using dynamic block size + if (all(static_block_size == 0u)) { + auto assume_power_of_two = [&](llvm::Value *v) noexcept { + // power of two check: (v & (v - 1)) == 0 + auto v_minus_one = b.CreateNUWSub(v, b.getInt32(1)); + auto v_and_v_minus_one = b.CreateAnd(v, v_minus_one); + auto is_zero = b.CreateICmpEQ(v_and_v_minus_one, b.getInt32(0)); + return b.CreateAssumption(is_zero); + }; + assume_power_of_two(llvm_block_size_x); + assume_power_of_two(llvm_block_size_y); + assume_power_of_two(llvm_block_size_z); + } + auto llvm_thread_count = b.CreateNUWMul(llvm_block_size_x, llvm_block_size_y, "thread_count"); + llvm_thread_count = b.CreateNUWMul(llvm_thread_count, llvm_block_size_z); + // thread-in-block loop + auto llvm_ptr_i = b.CreateAlloca(llvm_i32_type, nullptr, "loop.i.ptr"); + b.CreateStore(b.getInt32(0), llvm_ptr_i); + // loop head + auto llvm_loop_block = llvm::BasicBlock::Create(_llvm_context, "loop.head", llvm_wrapper_function); + b.CreateBr(llvm_loop_block); + b.SetInsertPoint(llvm_loop_block); + // compute thread id + auto llvm_i = b.CreateLoad(llvm_i32_type, llvm_ptr_i, "loop.i"); + auto llvm_thread_id_x = b.CreateURem(llvm_i, llvm_block_size_x, "thread_id.x"); + auto llvm_thread_id_yz = b.CreateUDiv(llvm_i, llvm_block_size_x); + auto llvm_thread_id_y = b.CreateURem(llvm_thread_id_yz, llvm_block_size_y, "thread_id.y"); + auto llvm_thread_id_z = b.CreateUDiv(llvm_thread_id_yz, llvm_block_size_y, "thread_id.z"); + auto llvm_thread_id = llvm::cast(llvm::PoisonValue::get(llvm_builtin_type)); + llvm_thread_id = b.CreateInsertElement(llvm_thread_id, llvm_thread_id_x, static_cast(0)); + llvm_thread_id = b.CreateInsertElement(llvm_thread_id, llvm_thread_id_y, static_cast(1)); + llvm_thread_id = b.CreateInsertElement(llvm_thread_id, llvm_thread_id_z, static_cast(2)); + llvm_thread_id->setName("thread_id"); + // compute dispatch id + auto llvm_dispatch_id = b.CreateNUWMul(llvm_block_id, llvm_block_size); + llvm_dispatch_id = b.CreateNUWAdd(llvm_dispatch_id, llvm_thread_id, "dispatch_id"); + // check if in range + auto llvm_in_range = b.CreateICmpULT(llvm_dispatch_id, llvm_dispatch_size); + llvm_in_range = b.CreateAndReduce(llvm_in_range); + llvm_in_range->setName("thread_id.in.range"); + // branch + auto llvm_loop_body_block = llvm::BasicBlock::Create(_llvm_context, "loop.body", llvm_wrapper_function); + auto llvm_loop_update_block = llvm::BasicBlock::Create(_llvm_context, "loop.update", llvm_wrapper_function); + b.CreateCondBr(llvm_in_range, llvm_loop_body_block, llvm_loop_update_block); + // loop body + b.SetInsertPoint(llvm_loop_body_block); + // call the kernel + auto call_args = llvm_args; + for (auto i = 0u; i < CurrentFunction::builtin_variable_count; i++) { + switch (i) { + case CurrentFunction::builtin_variable_index_thread_id: call_args.emplace_back(llvm_thread_id); break; + case CurrentFunction::builtin_variable_index_block_id: call_args.emplace_back(llvm_block_id); break; + case CurrentFunction::builtin_variable_index_dispatch_id: call_args.emplace_back(llvm_dispatch_id); break; + case CurrentFunction::builtin_variable_index_block_size: call_args.emplace_back(llvm_block_size); break; + case CurrentFunction::builtin_variable_index_dispatch_size: call_args.emplace_back(llvm_dispatch_size); break; + default: LUISA_ERROR_WITH_LOCATION("Invalid builtin variable index."); + } + } + b.CreateCall(llvm_kernel, call_args); + b.CreateBr(llvm_loop_update_block); + // loop update + b.SetInsertPoint(llvm_loop_update_block); + auto llvm_next_i = b.CreateNUWAdd(llvm_i, b.getInt32(1), "loop.i.next"); + b.CreateStore(llvm_next_i, llvm_ptr_i); + auto llvm_loop_cond = b.CreateICmpULT(llvm_next_i, llvm_thread_count, "loop.cond"); + auto llvm_loop_merge_block = llvm::BasicBlock::Create(_llvm_context, "loop.merge", llvm_wrapper_function); + b.CreateCondBr(llvm_loop_cond, llvm_loop_block, llvm_loop_merge_block); + // loop merge + b.SetInsertPoint(llvm_loop_merge_block); + b.CreateRetVoid(); + + return llvm_wrapper_function; + } + + [[nodiscard]] llvm::Function *_translate_function_definition(const xir::FunctionDefinition *f, + llvm::Function::LinkageTypes linkage, + llvm::StringRef default_name) noexcept { + auto llvm_ret_type = _translate_type(f->type(), true); + llvm::SmallVector llvm_arg_types; + for (auto arg : f->arguments()) { + if (arg->is_reference()) { + // reference arguments are passed by pointer + llvm_arg_types.emplace_back(llvm::PointerType::get(_llvm_context, 0)); + } else { + // value and resource arguments are passed by value + llvm_arg_types.emplace_back(_translate_type(arg->type(), true)); + } + } + // built-in variables + auto llvm_i32_type = llvm::Type::getInt32Ty(_llvm_context); + auto llvm_i32x3_type = llvm::VectorType::get(llvm_i32_type, 3, false); + for (auto builtin = 0u; builtin < CurrentFunction::builtin_variable_count; builtin++) { + llvm_arg_types.emplace_back(llvm_i32x3_type); + } + + // create function + auto llvm_func_type = llvm::FunctionType::get(llvm_ret_type, llvm_arg_types, false); + auto func_name = _get_name_from_metadata(f, default_name); + auto llvm_func = llvm::Function::Create(llvm_func_type, linkage, llvm::Twine{func_name}, _llvm_module); + _llvm_functions.emplace(f, llvm_func); + // create current translation context + CurrentFunction current{.func = llvm_func}; + // map arguments + auto arg_index = 0u; + for (auto &llvm_arg : current.func->args()) { + auto non_builtin_count = f->arguments().size(); + if (auto arg_i = arg_index++; arg_i < non_builtin_count) { + auto arg = f->arguments()[arg_i]; + current.value_map.emplace(arg, &llvm_arg); + } else {// built-in variable + auto builtin = arg_i - non_builtin_count; + switch (builtin) { + case CurrentFunction::builtin_variable_index_thread_id: llvm_arg.setName("thread_id"); break; + case CurrentFunction::builtin_variable_index_block_id: llvm_arg.setName("block_id"); break; + case CurrentFunction::builtin_variable_index_dispatch_id: llvm_arg.setName("dispatch_id"); break; + case CurrentFunction::builtin_variable_index_block_size: llvm_arg.setName("block_size"); break; + case CurrentFunction::builtin_variable_index_dispatch_size: llvm_arg.setName("dispatch_size"); break; + default: LUISA_ERROR_WITH_LOCATION("Invalid builtin variable index."); + } + current.builtin_variables[builtin] = &llvm_arg; + } + } + // translate body + static_cast(_translate_basic_block(current, f->body_block())); + // return + return llvm_func; + } + + [[nodiscard]] llvm::Function *_translate_callable_function(const xir::CallableFunction *f) noexcept { + return _translate_function_definition(f, llvm::Function::PrivateLinkage, "callable"); + } + + [[nodiscard]] llvm::Function *_translate_function(const xir::Function *f) noexcept { + if (auto iter = _llvm_functions.find(f); iter != _llvm_functions.end()) { + return iter->second; + } + auto llvm_func = [&] { + switch (f->derived_function_tag()) { + case xir::DerivedFunctionTag::KERNEL: + return _translate_kernel_function(static_cast(f)); + case xir::DerivedFunctionTag::CALLABLE: + return _translate_callable_function(static_cast(f)); + case xir::DerivedFunctionTag::EXTERNAL: LUISA_NOT_IMPLEMENTED(); + } + LUISA_ERROR_WITH_LOCATION("Invalid function type."); + }(); + _llvm_functions.emplace(f, llvm_func); + return llvm_func; + } + +public: + explicit FallbackCodegen(llvm::LLVMContext &ctx) noexcept + : _llvm_context{ctx} {} + + [[nodiscard]] auto emit(const xir::Module *module) noexcept { + auto llvm_module = std::make_unique(llvm::StringRef{_get_name_from_metadata(module)}, _llvm_context); + auto location_md = module->find_metadata(); + auto module_location = location_md ? location_md->file().string() : "unknown"; + llvm_module->setSourceFileName(location_md ? location_md->file().string() : "unknown"); + _llvm_module = llvm_module.get(); + _translate_module(module); + _reset(); + return llvm_module; + } +}; + +std::unique_ptr +luisa_fallback_backend_codegen(llvm::LLVMContext &llvm_ctx, const xir::Module *module) noexcept { + FallbackCodegen codegen{llvm_ctx}; + return codegen.emit(module); +} + +}// namespace luisa::compute::fallback diff --git a/src/backends/fallback/fallback_codegen.h b/src/backends/fallback/fallback_codegen.h new file mode 100644 index 000000000..7b721fba9 --- /dev/null +++ b/src/backends/fallback/fallback_codegen.h @@ -0,0 +1,18 @@ +#pragma once + +namespace llvm { +class Module; +class LLVMContext; +}// namespace llvm + +namespace luisa::compute::xir { +class Module; +}// namespace luisa::compute::xir + +namespace luisa::compute::fallback { + +[[nodiscard]] std::unique_ptr +luisa_fallback_backend_codegen(llvm::LLVMContext &llvm_ctx, + const xir::Module *module) noexcept; + +}// namespace luisa::compute::fallback diff --git a/src/backends/fallback/fallback_device.cpp b/src/backends/fallback/fallback_device.cpp new file mode 100644 index 000000000..dc9c9352e --- /dev/null +++ b/src/backends/fallback/fallback_device.cpp @@ -0,0 +1,312 @@ +// +// Created by Mike Smith on 2022/5/23. +// + +#include +#include +#include +#include +#include + +#include +#include +#include "fallback_stream.h" +#include "fallback_device.h" +#include "fallback_texture.h" +#include "fallback_mesh.h" +#include "fallback_accel.h" +#include "fallback_bindless_array.h" +#include "fallback_shader.h" + +//#include "llvm_event.h" +//#include "llvm_shader.h" +//#include "llvm_codegen.h" + +#include +#include + +//#include "fallback_texture_sampling_wrapper.ll"; + +namespace luisa::compute::fallback { + +static void loadLLVMModuleFromString(::llvm::orc::LLJIT &jit, const char *ir_string) { + // Create an LLVM context + auto llvm_ctx = std::make_unique(); + // Wrap the string in a MemoryBuffer + auto buffer = ::llvm::MemoryBuffer::getMemBuffer(ir_string, "embedded_ir"); + // Parse the IR + ::llvm::SMDiagnostic err; + auto module = ::llvm::parseIR(buffer->getMemBufferRef(), err, *llvm_ctx); + if (!module) { + throw std::runtime_error("Failed to parse embedded LLVM IR: " + err.getMessage().str()); + } + // Wrap the module in a ThreadSafeModule + auto tsm = ::llvm::orc::ThreadSafeModule(std::move(module), std::move(llvm_ctx)); + + // Add the module to the JIT + if (auto err = jit.addIRModule(std::move(tsm))) { + ::llvm::handleAllErrors(std::move(err), [](const ::llvm::ErrorInfoBase &err) { + LUISA_WARNING_WITH_LOCATION("LLJIT::addIRModule(): {}", err.message()); + }); + } +} + +extern "C" int my_function(int x, int y) { + printf("my_function called with arguments: %d, %d\n", x, y); + return x + y; +} +FallbackDevice::FallbackDevice(Context &&ctx) noexcept + : DeviceInterface{std::move(ctx)}, + _rtc_device{rtcNewDevice(nullptr)} { + static std::once_flag flag; + std::call_once(flag, [] { + ::llvm::InitializeNativeTarget(); + ::llvm::InitializeNativeTargetAsmPrinter(); + }); +} + +void *FallbackDevice::native_handle() const noexcept { + return reinterpret_cast(reinterpret_cast(this)); +} + +void FallbackDevice::destroy_buffer(uint64_t handle) noexcept { + luisa::deallocate_with_allocator(reinterpret_cast(handle)); +} + +void FallbackDevice::destroy_texture(uint64_t handle) noexcept { + luisa::delete_with_allocator(reinterpret_cast(handle)); +} + +void FallbackDevice::destroy_bindless_array(uint64_t handle) noexcept { + luisa::delete_with_allocator(reinterpret_cast(handle)); +} + +void FallbackDevice::destroy_stream(uint64_t handle) noexcept { + luisa::delete_with_allocator(reinterpret_cast(handle)); +} + +void FallbackDevice::synchronize_stream(uint64_t stream_handle) noexcept { + reinterpret_cast(stream_handle)->synchronize(); +} + +void FallbackDevice::destroy_shader(uint64_t handle) noexcept { + //luisa::delete_with_allocator(reinterpret_cast(handle)); +} + +void FallbackDevice::destroy_event(uint64_t handle) noexcept { + //luisa::delete_with_allocator(reinterpret_cast(handle)); +} + +void FallbackDevice::destroy_mesh(uint64_t handle) noexcept { + luisa::delete_with_allocator(reinterpret_cast(handle)); +} + +void FallbackDevice::destroy_accel(uint64_t handle) noexcept { + luisa::delete_with_allocator(reinterpret_cast(handle)); +} + +void FallbackDevice::destroy_swap_chain(uint64_t handle) noexcept { + LUISA_ERROR_WITH_LOCATION("Not implemented."); +} + +void FallbackDevice::present_display_in_stream( + uint64_t stream_handle, uint64_t swap_chain_handle, uint64_t image_handle) noexcept { + LUISA_ERROR_WITH_LOCATION("Not implemented."); +} + +FallbackDevice::~FallbackDevice() noexcept { + rtcReleaseDevice(_rtc_device); +} + +uint FallbackDevice::compute_warp_size() const noexcept { + return 1; +} + +BufferCreationInfo FallbackDevice::create_buffer(const Type *element, size_t elem_count, void *external_memory) noexcept { + + BufferCreationInfo info{}; + + info.element_stride = element->size(); + info.total_size_bytes = info.element_stride * elem_count; + info.handle = reinterpret_cast( + luisa::allocate_with_allocator(info.total_size_bytes)); + info.native_handle = reinterpret_cast(info.handle); + return info; +} + +BufferCreationInfo FallbackDevice::create_buffer(const ir::CArc *element, size_t elem_count, void *external_memory) noexcept { + return BufferCreationInfo(); +} + +ResourceCreationInfo FallbackDevice::create_texture(PixelFormat format, uint dimension, uint width, uint height, uint depth, uint mipmap_levels, bool simultaneous_access, bool allow_raster_target) noexcept { + ResourceCreationInfo info{}; + auto texture = luisa::new_with_allocator( + pixel_format_to_storage(format), dimension, + make_uint3(width, height, depth), mipmap_levels); + info.handle = reinterpret_cast(texture); + return info; +} + +ResourceCreationInfo FallbackDevice::create_stream(StreamTag stream_tag) noexcept { + return ResourceCreationInfo{ + .handle = reinterpret_cast(luisa::new_with_allocator())}; +} + +void FallbackDevice::dispatch(uint64_t stream_handle, CommandList &&list) noexcept { + auto stream = reinterpret_cast(stream_handle); + stream->dispatch(std::move(list)); +} + +void FallbackDevice::set_stream_log_callback(uint64_t stream_handle, const DeviceInterface::StreamLogCallback &callback) noexcept { + DeviceInterface::set_stream_log_callback(stream_handle, callback); +} + +SwapchainCreationInfo FallbackDevice::create_swapchain(const SwapchainOption &option, uint64_t stream_handle) noexcept { + return SwapchainCreationInfo(); +} + +ShaderCreationInfo FallbackDevice::create_shader(const ShaderOption &option, Function kernel) noexcept { + return ShaderCreationInfo{ + ResourceCreationInfo{ + .handle = reinterpret_cast(luisa::new_with_allocator(option, kernel))}}; + return ShaderCreationInfo(); +} + +ShaderCreationInfo FallbackDevice::create_shader(const ShaderOption &option, const ir::KernelModule *kernel) noexcept { + return ShaderCreationInfo(); +} + +ShaderCreationInfo FallbackDevice::create_shader(const ShaderOption &option, const ir_v2::KernelModule &kernel) noexcept { + return DeviceInterface::create_shader(option, kernel); +} + +ShaderCreationInfo FallbackDevice::load_shader(luisa::string_view name, luisa::span arg_types) noexcept { + return ShaderCreationInfo(); +} + +Usage FallbackDevice::shader_argument_usage(uint64_t handle, size_t index) noexcept { + return Usage::READ; +} + +void FallbackDevice::signal_event(uint64_t handle, uint64_t stream_handle, uint64_t fence_value) noexcept { + reinterpret_cast(stream_handle)->signal(reinterpret_cast(handle)); +} + +void FallbackDevice::wait_event(uint64_t handle, uint64_t stream_handle, uint64_t fence_value) noexcept { + reinterpret_cast(stream_handle)->wait(reinterpret_cast(handle)); +} + +bool FallbackDevice::is_event_completed(uint64_t handle, uint64_t fence_value) const noexcept { + return false; +} + +void FallbackDevice::synchronize_event(uint64_t handle, uint64_t fence_value) noexcept { + //reinterpret_cast(handle)->wait(); +} + +ResourceCreationInfo FallbackDevice::create_mesh(const AccelOption &option) noexcept { + return { + .handle = reinterpret_cast(luisa::new_with_allocator(_rtc_device, option.hint)), + .native_handle = nullptr}; +} + +ResourceCreationInfo FallbackDevice::create_procedural_primitive(const AccelOption &option) noexcept { + return ResourceCreationInfo(); +} + +void FallbackDevice::destroy_procedural_primitive(uint64_t handle) noexcept { +} + +ResourceCreationInfo FallbackDevice::create_curve(const AccelOption &option) noexcept { + return DeviceInterface::create_curve(option); +} + +void FallbackDevice::destroy_curve(uint64_t handle) noexcept { + DeviceInterface::destroy_curve(handle); +} + +ResourceCreationInfo FallbackDevice::create_motion_instance(const AccelMotionOption &option) noexcept { + return DeviceInterface::create_motion_instance(option); +} + +void FallbackDevice::destroy_motion_instance(uint64_t handle) noexcept { + DeviceInterface::destroy_motion_instance(handle); +} + +ResourceCreationInfo FallbackDevice::create_accel(const AccelOption &option) noexcept { + return ResourceCreationInfo{ + .handle = reinterpret_cast(luisa::new_with_allocator(_rtc_device, option.hint)), + .native_handle = nullptr}; +} + +string FallbackDevice::query(luisa::string_view property) noexcept { + return DeviceInterface::query(property); +} + +DeviceExtension *FallbackDevice::extension(luisa::string_view name) noexcept { + return DeviceInterface::extension(name); +} + +void FallbackDevice::set_name(luisa::compute::Resource::Tag resource_tag, uint64_t resource_handle, luisa::string_view name) noexcept { +} + +SparseBufferCreationInfo FallbackDevice::create_sparse_buffer(const Type *element, size_t elem_count) noexcept { + return DeviceInterface::create_sparse_buffer(element, elem_count); +} + +ResourceCreationInfo FallbackDevice::allocate_sparse_buffer_heap(size_t byte_size) noexcept { + return DeviceInterface::allocate_sparse_buffer_heap(byte_size); +} + +void FallbackDevice::deallocate_sparse_buffer_heap(uint64_t handle) noexcept { + DeviceInterface::deallocate_sparse_buffer_heap(handle); +} + +void FallbackDevice::update_sparse_resources(uint64_t stream_handle, vector &&textures_update) noexcept { + DeviceInterface::update_sparse_resources(stream_handle, std::move(textures_update)); +} + +void FallbackDevice::destroy_sparse_buffer(uint64_t handle) noexcept { + DeviceInterface::destroy_sparse_buffer(handle); +} + +ResourceCreationInfo FallbackDevice::allocate_sparse_texture_heap(size_t byte_size, bool is_compressed_type) noexcept { + return DeviceInterface::allocate_sparse_texture_heap(byte_size, is_compressed_type); +} + +void FallbackDevice::deallocate_sparse_texture_heap(uint64_t handle) noexcept { + DeviceInterface::deallocate_sparse_texture_heap(handle); +} + +SparseTextureCreationInfo FallbackDevice::create_sparse_texture(PixelFormat format, uint dimension, uint width, uint height, uint depth, uint mipmap_levels, bool simultaneous_access) noexcept { + return DeviceInterface::create_sparse_texture(format, dimension, width, height, depth, mipmap_levels, simultaneous_access); +} + +void FallbackDevice::destroy_sparse_texture(uint64_t handle) noexcept { + DeviceInterface::destroy_sparse_texture(handle); +} + +ResourceCreationInfo FallbackDevice::create_bindless_array(size_t size) noexcept { + ResourceCreationInfo info{}; + auto array = luisa::new_with_allocator(size); + info.handle = reinterpret_cast(array); + return info; +} + +ResourceCreationInfo FallbackDevice::create_event() noexcept { + return ResourceCreationInfo{}; + // return ResourceCreationInfo + // { + // .handle = reinterpret_cast(luisa::new_with_allocator()) + // }; +} + +}// namespace luisa::compute::fallback + +LUISA_EXPORT_API luisa::compute::DeviceInterface *create(luisa::compute::Context &&ctx, std::string_view) noexcept { + return luisa::new_with_allocator(std::move(ctx)); +} + +LUISA_EXPORT_API void destroy(luisa::compute::DeviceInterface *device) noexcept { + luisa::delete_with_allocator(device); +} diff --git a/src/backends/fallback/fallback_device.h b/src/backends/fallback/fallback_device.h new file mode 100644 index 000000000..f3db3b536 --- /dev/null +++ b/src/backends/fallback/fallback_device.h @@ -0,0 +1,86 @@ +// +// Created by Mike Smith on 2022/5/23. +// + +#pragma once + +#include +#include "fallback_embree.h" + +namespace llvm { +class TargetMachine; +}// namespace llvm + +namespace llvm::orc { +class LLJIT; +}// namespace llvm::orc + +namespace luisa::compute::fallback { + +class FallbackDevice : public DeviceInterface { + +private: + RTCDevice _rtc_device; + mutable std::mutex _jit_mutex; + +public: + explicit FallbackDevice(Context &&ctx) noexcept; + ~FallbackDevice() noexcept override; + //[[nodiscard]] ::llvm::TargetMachine *target_machine() const noexcept { return _target_machine.get(); } + //[[nodiscard]] ::llvm::orc::LLJIT *jit() const noexcept { return _jit.get(); } + [[nodiscard]] auto &jit_mutex() const noexcept { return _jit_mutex; } + void *native_handle() const noexcept override; + void destroy_buffer(uint64_t handle) noexcept override; + void destroy_texture(uint64_t handle) noexcept override; + void destroy_bindless_array(uint64_t handle) noexcept override; + + void destroy_stream(uint64_t handle) noexcept override; + void synchronize_stream(uint64_t stream_handle) noexcept override; + void destroy_swap_chain(uint64_t handle) noexcept override; + void present_display_in_stream(uint64_t stream_handle, uint64_t swapchain_handle, uint64_t image_handle) noexcept override; + void destroy_shader(uint64_t handle) noexcept override; + void destroy_event(uint64_t handle) noexcept override; + void destroy_mesh(uint64_t handle) noexcept override; + void destroy_accel(uint64_t handle) noexcept override; + uint compute_warp_size() const noexcept override; + BufferCreationInfo create_buffer(const Type *element, size_t elem_count, void *external_memory) noexcept override; + BufferCreationInfo create_buffer(const ir::CArc *element, size_t elem_count, void *external_memory) noexcept override; + ResourceCreationInfo create_texture(PixelFormat format, uint dimension, uint width, uint height, uint depth, uint mipmap_levels, bool simultaneous_access, bool allow_raster_target) noexcept override; + ResourceCreationInfo create_stream(StreamTag stream_tag) noexcept override; + void dispatch(uint64_t stream_handle, CommandList &&list) noexcept override; + void set_stream_log_callback(uint64_t stream_handle, const StreamLogCallback &callback) noexcept override; + SwapchainCreationInfo create_swapchain(const SwapchainOption &option, uint64_t stream_handle) noexcept override; + ShaderCreationInfo create_shader(const ShaderOption &option, Function kernel) noexcept override; + ShaderCreationInfo create_shader(const ShaderOption &option, const ir::KernelModule *kernel) noexcept override; + ShaderCreationInfo create_shader(const ShaderOption &option, const ir_v2::KernelModule &kernel) noexcept override; + ShaderCreationInfo load_shader(luisa::string_view name, luisa::span arg_types) noexcept override; + Usage shader_argument_usage(uint64_t handle, size_t index) noexcept override; + void signal_event(uint64_t handle, uint64_t stream_handle, uint64_t fence_value) noexcept override; + void wait_event(uint64_t handle, uint64_t stream_handle, uint64_t fence_value) noexcept override; + bool is_event_completed(uint64_t handle, uint64_t fence_value) const noexcept override; + void synchronize_event(uint64_t handle, uint64_t fence_value) noexcept override; + ResourceCreationInfo create_mesh(const AccelOption &option) noexcept override; + ResourceCreationInfo create_procedural_primitive(const AccelOption &option) noexcept override; + void destroy_procedural_primitive(uint64_t handle) noexcept override; + ResourceCreationInfo create_curve(const AccelOption &option) noexcept override; + void destroy_curve(uint64_t handle) noexcept override; + ResourceCreationInfo create_motion_instance(const AccelMotionOption &option) noexcept override; + void destroy_motion_instance(uint64_t handle) noexcept override; + ResourceCreationInfo create_accel(const AccelOption &option) noexcept override; + string query(luisa::string_view property) noexcept override; + DeviceExtension *extension(luisa::string_view name) noexcept override; + void set_name(luisa::compute::Resource::Tag resource_tag, uint64_t resource_handle, luisa::string_view name) noexcept override; + SparseBufferCreationInfo create_sparse_buffer(const Type *element, size_t elem_count) noexcept override; + ResourceCreationInfo allocate_sparse_buffer_heap(size_t byte_size) noexcept override; + void deallocate_sparse_buffer_heap(uint64_t handle) noexcept override; + void update_sparse_resources(uint64_t stream_handle, vector &&textures_update) noexcept override; + void destroy_sparse_buffer(uint64_t handle) noexcept override; + ResourceCreationInfo allocate_sparse_texture_heap(size_t byte_size, bool is_compressed_type) noexcept override; + void deallocate_sparse_texture_heap(uint64_t handle) noexcept override; + SparseTextureCreationInfo create_sparse_texture(PixelFormat format, uint dimension, uint width, uint height, uint depth, uint mipmap_levels, bool simultaneous_access) noexcept override; + void destroy_sparse_texture(uint64_t handle) noexcept override; + ResourceCreationInfo create_bindless_array(size_t size) noexcept override; + ResourceCreationInfo create_event() noexcept override; +}; + +}// namespace luisa::compute::fallback diff --git a/src/backends/fallback/fallback_embree.h b/src/backends/fallback/fallback_embree.h new file mode 100644 index 000000000..442aea34f --- /dev/null +++ b/src/backends/fallback/fallback_embree.h @@ -0,0 +1,17 @@ +#pragma once + +#ifndef LUISA_COMPUTE_EMBREE_VERSION +#if __has_include() +#define LUISA_COMPUTE_EMBREE_VERSION 4 +#elif __has_include() +#define LUISA_COMPUTE_EMBREE_VERSION 3 +#else +#error "Embree not found." +#endif +#endif + +#if LUISA_COMPUTE_EMBREE_VERSION == 3 +#include +#else +#include +#endif diff --git a/src/backends/fallback/fallback_mesh.cpp b/src/backends/fallback/fallback_mesh.cpp new file mode 100644 index 000000000..0eda5f6a0 --- /dev/null +++ b/src/backends/fallback/fallback_mesh.cpp @@ -0,0 +1,56 @@ +// +// Created by Mike Smith on 2022/2/11. +// + +#include "fallback_mesh.h" + +namespace luisa::compute::fallback { + +FallbackMesh::FallbackMesh( + RTCDevice device, AccelUsageHint hint) noexcept + : _handle{rtcNewScene(device)}, + _geometry{rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE)}, _hint{hint} +{ +} + +FallbackMesh::~FallbackMesh() noexcept { + rtcReleaseScene(_handle); + rtcReleaseGeometry(_geometry); +} + +void FallbackMesh::commit(uint64_t v_buffer, size_t v_offset, size_t v_stride, size_t v_count, + uint64_t t_buffer, size_t t_offset, size_t t_count) noexcept { + _v_buffer = v_buffer; + _v_offset = v_offset; + _v_stride = v_stride; + _v_count = v_count; + _t_buffer = t_buffer; + _t_offset = t_offset; + _t_count = t_count; + + if (!_buffers_already_set.exchange(true)) [[unlikely]] { + rtcSetSharedGeometryBuffer( + _geometry, RTC_BUFFER_TYPE_VERTEX, 0u, RTC_FORMAT_FLOAT3, + reinterpret_cast(_v_buffer), + _v_offset, _v_stride, _v_count); + rtcSetSharedGeometryBuffer( + _geometry, RTC_BUFFER_TYPE_INDEX, 0u, RTC_FORMAT_UINT3, + reinterpret_cast(_t_buffer), + _t_offset, sizeof(Triangle), _t_count); + switch (_hint) { + case AccelUsageHint::FAST_TRACE: + rtcSetGeometryBuildQuality(_geometry, RTC_BUILD_QUALITY_HIGH); + break; + case AccelUsageHint::FAST_BUILD: + rtcSetGeometryBuildQuality(_geometry, RTC_BUILD_QUALITY_REFIT); + break; + } + rtcAttachGeometry(_handle, _geometry); + rtcSetSceneBuildQuality(_handle, RTC_BUILD_QUALITY_HIGH); + rtcSetSceneFlags(_handle, RTC_SCENE_FLAG_COMPACT); + } + rtcCommitGeometry(_geometry); + rtcCommitScene(_handle); +} + +}// namespace luisa::compute::llvm diff --git a/src/backends/fallback/fallback_mesh.h b/src/backends/fallback/fallback_mesh.h new file mode 100644 index 000000000..dc24a97a2 --- /dev/null +++ b/src/backends/fallback/fallback_mesh.h @@ -0,0 +1,37 @@ +// +// Created by Mike Smith on 2022/2/11. +// + +#pragma once + +#include +#include "fallback_embree.h" + +namespace luisa::compute::fallback { + +class FallbackMesh { + +private: + RTCScene _handle; + RTCGeometry _geometry; + uint64_t _v_buffer; + uint64_t _v_offset; + uint64_t _v_stride; + uint64_t _v_count; + uint64_t _t_buffer; + uint64_t _t_offset; + uint64_t _t_count; + AccelUsageHint _hint; + std::atomic_bool _buffers_already_set{false}; + +public: + FallbackMesh(RTCDevice device, AccelUsageHint hint) noexcept; + ~FallbackMesh() noexcept; + [[nodiscard]] auto vertex_buffer() const noexcept { return _v_buffer; } + [[nodiscard]] auto triangle_buffer() const noexcept { return _t_buffer; } + [[nodiscard]] auto handle() const noexcept { return _handle; } + void commit(uint64_t v_buffer, size_t v_offset, size_t v_stride, size_t v_count, + uint64_t t_buffer, size_t t_offset, size_t t_count) noexcept; +}; + +}// namespace luisa::compute::llvm diff --git a/src/backends/fallback/fallback_shader.cpp b/src/backends/fallback/fallback_shader.cpp new file mode 100644 index 000000000..0e4f8ddb5 --- /dev/null +++ b/src/backends/fallback/fallback_shader.cpp @@ -0,0 +1,327 @@ +// +// Created by swfly on 2024/11/21. +// + +#include "fallback_shader.h" + +#include "fallback_buffer.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fallback_codegen.h" +#include "fallback_texture.h" +#include "fallback_accel.h" +#include "fallback_bindless_array.h" +#include "thread_pool.h" + +using namespace luisa; +luisa::compute::fallback::FallbackShader::FallbackShader(const luisa::compute::ShaderOption &option, luisa::compute::Function kernel) noexcept { + + // build JIT engine + ::llvm::orc::LLJITBuilder jit_builder; + if (auto host = ::llvm::orc::JITTargetMachineBuilder::detectHost()) { + ::llvm::TargetOptions options; + options.AllowFPOpFusion = ::llvm::FPOpFusion::Fast; + options.UnsafeFPMath = true; + options.NoInfsFPMath = true; + options.NoNaNsFPMath = true; + options.NoTrappingFPMath = true; + options.NoSignedZerosFPMath = true; + options.ApproxFuncFPMath = true; + options.EnableIPRA = true; + options.StackSymbolOrdering = true; + options.EnableMachineFunctionSplitter = true; + options.EnableMachineOutliner = true; + options.NoTrapAfterNoreturn = true; + host->setOptions(options); + host->setCodeGenOptLevel(::llvm::CodeGenOptLevel::Aggressive); +#ifdef __aarch64__ + host->addFeatures({"+neon"}); +#else + host->addFeatures({"+avx2"}); +#endif + // LUISA_INFO("LLVM JIT target: triplet = {}, features = {}.", + // host->getTargetTriple().str(), + // host->getFeatures().getString()); + if (auto machine = host->createTargetMachine()) { + _target_machine = std::move(machine.get()); + } else { + ::llvm::handleAllErrors(machine.takeError(), [&](const ::llvm::ErrorInfoBase &e) { + LUISA_WARNING_WITH_LOCATION("JITTargetMachineBuilder::createTargetMachine(): {}.", e.message()); + }); + LUISA_ERROR_WITH_LOCATION("Failed to create target machine."); + } + jit_builder.setJITTargetMachineBuilder(std::move(*host)); + } else { + ::llvm::handleAllErrors(host.takeError(), [&](const ::llvm::ErrorInfoBase &e) { + LUISA_WARNING_WITH_LOCATION("JITTargetMachineBuilder::detectHost(): {}.", e.message()); + }); + LUISA_ERROR_WITH_LOCATION("Failed to detect host."); + } + + if (auto expected_jit = jit_builder.create()) { + _jit = std::move(expected_jit.get()); + } else { + ::llvm::handleAllErrors(expected_jit.takeError(), [](const ::llvm::ErrorInfoBase &err) { + LUISA_WARNING_WITH_LOCATION("LLJITBuilder::create(): {}", err.message()); + }); + LUISA_ERROR_WITH_LOCATION("Failed to create LLJIT."); + } + + // map symbols + llvm::orc::SymbolMap symbol_map{}; + auto map_symbol = [jit = _jit.get(), &symbol_map](const char *name, T *f) noexcept { + static_assert(std::is_function_v); + auto addr = llvm::orc::ExecutorAddr::fromPtr(f); + auto symbol = llvm::orc::ExecutorSymbolDef{addr, llvm::JITSymbolFlags::Exported}; + symbol_map.try_emplace(jit->mangleAndIntern(name), symbol); + }; + map_symbol("texture.write.2d.float", &texture_write_2d_float_wrapper); + map_symbol("texture.read.2d.float", &texture_read_2d_float_wrapper); + map_symbol("texture.write.2d.uint", &texture_write_2d_uint_wrapper); + map_symbol("texture.read.2d.uint", &texture_read_2d_uint_wrapper); + + map_symbol("intersect.closest", &intersect_closest_wrapper); + + map_symbol("bindless.buffer.read", &bindless_buffer_read); + if (auto error = _jit->getMainJITDylib().define( + ::llvm::orc::absoluteSymbols(std::move(symbol_map)))) { + ::llvm::handleAllErrors(std::move(error), [](const ::llvm::ErrorInfoBase &err) { + LUISA_WARNING_WITH_LOCATION("LLJIT::define(): {}", err.message()); + }); + LUISA_ERROR_WITH_LOCATION("Failed to define symbols."); + } + + if (auto generator = ::llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess( + _jit->getDataLayout().getGlobalPrefix())) { + _jit->getMainJITDylib().addGenerator(std::move(generator.get())); + } else { + ::llvm::handleAllErrors(generator.takeError(), [](const ::llvm::ErrorInfoBase &err) { + LUISA_WARNING_WITH_LOCATION("DynamicLibrarySearchGenerator::GetForCurrentProcess(): {}", err.message()); + }); + LUISA_ERROR_WITH_LOCATION("Failed to add generator."); + } + + _block_size = kernel.block_size(); + build_bound_arguments(kernel); + xir::Pool pool; + xir::PoolGuard guard{&pool}; + auto xir_module = xir::ast_to_xir_translate(kernel, {}); + xir_module->set_name(luisa::format("kernel_{:016x}", kernel.hash())); + if (!option.name.empty()) { xir_module->set_location(option.name); } + //LUISA_INFO("Kernel XIR:\n{}", xir::xir_to_text_translate(xir_module, true)); + + auto llvm_ctx = std::make_unique(); + auto llvm_module = luisa_fallback_backend_codegen(*llvm_ctx, xir_module); + if (!llvm_module) { + LUISA_ERROR_WITH_LOCATION("Failed to generate LLVM IR."); + } + //llvm_module->print(llvm::errs(), nullptr, true, true); + //llvm_module->print(llvm::outs(), nullptr, true, true); + if (llvm::verifyModule(*llvm_module, &llvm::errs())) { + LUISA_ERROR_WITH_LOCATION("LLVM module verification failed."); + } + + // optimize + llvm_module->setDataLayout(_target_machine->createDataLayout()); + llvm_module->setTargetTriple(_target_machine->getTargetTriple().str()); + + // optimize with the new pass manager + ::llvm::LoopAnalysisManager LAM; + ::llvm::FunctionAnalysisManager FAM; + ::llvm::CGSCCAnalysisManager CGAM; + ::llvm::ModuleAnalysisManager MAM; + ::llvm::PipelineTuningOptions PTO; + PTO.LoopInterleaving = true; + PTO.LoopVectorization = true; + PTO.SLPVectorization = true; + PTO.LoopUnrolling = true; + PTO.MergeFunctions = true; + ::llvm::PassBuilder PB{_target_machine.get(), PTO}; + FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); }); + PB.registerModuleAnalyses(MAM); + PB.registerCGSCCAnalyses(CGAM); + PB.registerFunctionAnalyses(FAM); + PB.registerLoopAnalyses(LAM); + PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); +#if LLVM_VERSION_MAJOR >= 19 + _target_machine->registerPassBuilderCallbacks(PB); +#else + _target_machine->registerPassBuilderCallbacks(PB, false); +#endif + Clock clk; + clk.tic(); + auto MPM = PB.buildPerModuleDefaultPipeline(::llvm::OptimizationLevel::O3); + MPM.run(*llvm_module, MAM); + LUISA_INFO("Optimized LLVM module in {} ms.", clk.toc()); + if (::llvm::verifyModule(*llvm_module, &::llvm::errs())) { + LUISA_ERROR_WITH_LOCATION("Failed to verify module."); + } + //llvm_module->print(llvm::outs(), nullptr, true, true); + + // compile to machine code + auto m = llvm::orc::ThreadSafeModule(std::move(llvm_module), std::move(llvm_ctx)); + if (auto error = _jit->addIRModule(std::move(m))) { + ::llvm::handleAllErrors(std::move(error), [](const ::llvm::ErrorInfoBase &err) { + LUISA_WARNING_WITH_LOCATION("LLJIT::addIRModule(): {}", err.message()); + }); + } + auto addr = _jit->lookup("kernel.main"); + if (!addr) { + ::llvm::handleAllErrors(addr.takeError(), [](const ::llvm::ErrorInfoBase &err) { + LUISA_WARNING_WITH_LOCATION("LLJIT::lookup(): {}", err.message()); + }); + } + LUISA_ASSERT(addr, "JIT compilation failed with error [{}]"); + _kernel_entry = addr->toPtr(); +} + +void compute::fallback::FallbackShader::dispatch(ThreadPool &pool, const compute::ShaderDispatchCommand *command) const noexcept { + thread_local std::array argument_buffer;// should be enough + + auto argument_buffer_offset = static_cast(0u); + auto allocate_argument = [&](size_t bytes) noexcept { + static constexpr auto alignment = 16u; + auto offset = (argument_buffer_offset + alignment - 1u) / alignment * alignment; + LUISA_ASSERT(offset + bytes <= argument_buffer.size(), + "Too many arguments in ShaderDispatchCommand"); + argument_buffer_offset = offset + bytes; + return argument_buffer.data() + offset; + }; + + auto encode_argument = [&allocate_argument, command](const auto &arg) noexcept { + using Tag = ShaderDispatchCommand::Argument::Tag; + switch (arg.tag) { + case Tag::BUFFER: { + //What is indirect? + // if (reinterpret_cast(arg.buffer.handle)->is_indirect()) + // { + // auto buffer = reinterpret_cast(arg.buffer.handle); + // auto binding = buffer->binding(arg.buffer.offset, arg.buffer.size); + // auto ptr = allocate_argument(sizeof(binding)); + // std::memcpy(ptr, &binding, sizeof(binding)); + // } + // else + { + auto buffer = reinterpret_cast(arg.buffer.handle); + auto buffer_view = buffer->view(arg.buffer.offset); + //auto binding = buffer->binding(arg.buffer.offset, arg.buffer.size); + auto ptr = allocate_argument(sizeof(buffer_view)); + std::memcpy(ptr, &buffer, sizeof(buffer_view)); + } + break; + } + case Tag::TEXTURE: { + auto texture = reinterpret_cast(arg.texture.handle); + auto view = texture->view(arg.texture.level); + auto ptr = allocate_argument(sizeof(view)); + FallbackTextureView *v = reinterpret_cast(ptr); + std::memcpy(ptr, &view, sizeof(view)); + break; + } + case Tag::UNIFORM: { + auto uniform = command->uniform(arg.uniform); + auto ptr = allocate_argument(uniform.size_bytes()); + std::memcpy(ptr, uniform.data(), uniform.size_bytes()); + break; + } + case Tag::BINDLESS_ARRAY: { + auto bindless = reinterpret_cast(arg.buffer.handle); + //auto binding = buffer->binding(arg.buffer.offset, arg.buffer.size); + auto ptr = allocate_argument(sizeof(bindless)); + std::memcpy(ptr, &bindless, sizeof(bindless)); + break; + } + case Tag::ACCEL: { + auto accel = reinterpret_cast(arg.accel.handle); + auto ptr = allocate_argument(sizeof(accel)); + std::memcpy(ptr, &accel, sizeof(accel)); + break; + } + } + }; + for (auto &&arg : _bound_arguments) { encode_argument(arg); } + for (auto &&arg : command->arguments()) { encode_argument(arg); } + struct LaunchConfig { + uint3 block_id; + uint3 dispatch_size; + uint3 block_size; + }; + // TODO: fill in true values + LaunchConfig config{ + .block_id = make_uint3(0u), + .dispatch_size = command->dispatch_size(), + .block_size = _block_size, + }; + + auto round_up_division = [](unsigned a, unsigned b) { + return (a + b - 1) / b; + }; + auto dispatch_counts = make_uint3( + round_up_division(config.dispatch_size.x, _block_size.x), + round_up_division(config.dispatch_size.y, _block_size.y), + round_up_division(config.dispatch_size.z, _block_size.z)); + + auto data = argument_buffer.data(); + + // for (int i = 0; i < dispatch_counts.x; ++i) { + // for (int j = 0; j < dispatch_counts.y; ++j) { + // for (int k = 0; k < dispatch_counts.z; ++k) { + // auto c = config; + // c.block_id = make_uint3(i, j, k); + // (*_kernel_entry)(data, &c); + // } + // } + // } + + pool.parallel(dispatch_counts.x, dispatch_counts.y, dispatch_counts.z, + [this, config, data](auto bx, auto by, auto bz) noexcept { + auto c = config; + c.block_id = make_uint3(bx, by, bz); + (*_kernel_entry)(data, &c); + }); + pool.barrier(); +} +void compute::fallback::FallbackShader::build_bound_arguments(compute::Function kernel) { + _bound_arguments.reserve(kernel.bound_arguments().size()); + for (auto &&arg : kernel.bound_arguments()) { + luisa::visit( + [&](T binding) noexcept { + ShaderDispatchCommand::Argument argument{}; + if constexpr (std::is_same_v) { + argument.tag = ShaderDispatchCommand::Argument::Tag::BUFFER; + argument.buffer.handle = binding.handle; + argument.buffer.offset = binding.offset; + argument.buffer.size = binding.size; + } else if constexpr (std::is_same_v) { + argument.tag = ShaderDispatchCommand::Argument::Tag::TEXTURE; + argument.texture.handle = binding.handle; + argument.texture.level = binding.level; + } else if constexpr (std::is_same_v) { + argument.tag = ShaderDispatchCommand::Argument::Tag::BINDLESS_ARRAY; + argument.bindless_array.handle = binding.handle; + } else if constexpr (std::is_same_v) { + argument.tag = ShaderDispatchCommand::Argument::Tag::ACCEL; + argument.accel.handle = binding.handle; + } else { + LUISA_ERROR_WITH_LOCATION("Unsupported binding type."); + } + _bound_arguments.emplace_back(argument); + }, + arg); + } +} diff --git a/src/backends/fallback/fallback_shader.h b/src/backends/fallback/fallback_shader.h new file mode 100644 index 000000000..dc9ca64b8 --- /dev/null +++ b/src/backends/fallback/fallback_shader.h @@ -0,0 +1,65 @@ +// +// Created by swfly on 2024/11/21. +// + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace llvm { +class LLVMContext; +class Module; +class ExecutionEngine; +}// namespace llvm + +namespace llvm::orc { +class LLJIT; +}// namespace llvm::orc +namespace luisa +{ + class ThreadPool; +} + +namespace luisa::compute::fallback { + +using luisa::compute::detail::FunctionBuilder; + +class FallbackShader { + +public: + using kernel_entry_t = void(const void *, const void *); + +private: + luisa::string _name; + luisa::unordered_map _argument_offsets; + kernel_entry_t *_kernel_entry{nullptr}; + size_t _argument_buffer_size{}; + //luisa::vector _callbacks; + size_t _shared_memory_size{}; + unique_ptr _module{}; + luisa::vector _bound_arguments; + + uint3 _block_size; + mutable std::unique_ptr<::llvm::orc::LLJIT> _jit; + std::unique_ptr<::llvm::TargetMachine> _target_machine; + + + void build_bound_arguments(Function kernel); +public: + + void dispatch(ThreadPool& pool, const ShaderDispatchCommand *command) const noexcept; + FallbackShader(const ShaderOption &option, Function kernel) noexcept; + ~FallbackShader() noexcept; + + [[nodiscard]] auto argument_buffer_size() const noexcept { return _argument_buffer_size; } + [[nodiscard]] auto shared_memory_size() const noexcept { return _shared_memory_size; } + [[nodiscard]] size_t argument_offset(uint uid) const noexcept; + //[[nodiscard]] auto callbacks() const noexcept { return _callbacks.data(); } +}; + +}// namespace luisa::compute::fallback diff --git a/src/backends/fallback/fallback_stream.cpp b/src/backends/fallback/fallback_stream.cpp new file mode 100644 index 000000000..92cfe7ab5 --- /dev/null +++ b/src/backends/fallback/fallback_stream.cpp @@ -0,0 +1,175 @@ +// +// Created by Mike Smith on 2022/2/7. +// + +#include +#include "fallback_stream.h" +#include "fallback_accel.h" +#include "fallback_bindless_array.h" +#include "fallback_mesh.h" +#include "fallback_texture.h" +#include "fallback_shader.h" + +namespace luisa::compute::fallback { + +using std::max; + +void FallbackStream::dispatch(CommandList &&cmd_list) noexcept { + + auto cmds = cmd_list.steal_commands(); + + for (auto &&cmd : cmds) + { + for (;;) { + auto n = _pool.task_count(); + if (n < _pool.size() * 4u) { break; } + using namespace std::chrono_literals; + std::this_thread::sleep_for(50us); + } + cmd->accept(*this); + } + _pool.barrier(); +} + +void FallbackStream::signal(LLVMEvent *event) noexcept { +// event->signal(_pool.async([] {})); +} + +void FallbackStream::wait(LLVMEvent *event) noexcept { +// _pool.async([future = event->future()] { future.wait(); }); +// _pool.barrier(); +} + +void FallbackStream::visit(const BufferUploadCommand *command) noexcept { + auto temp_buffer = luisa::make_shared>(command->size()); + std::memcpy(temp_buffer->data(), command->data(), command->size()); + _pool.async([src = std::move(temp_buffer), + buffer = command->handle(), offset = command->offset()] { + auto dst = reinterpret_cast(buffer + offset); + std::memcpy(dst, src->data(), src->size()); + }); + _pool.barrier(); +} + +void FallbackStream::visit(const BufferDownloadCommand *command) noexcept { + _pool.async([cmd = *command] { + auto src = reinterpret_cast(cmd.handle() + cmd.offset()); + std::memcpy(cmd.data(), src, cmd.size()); + }); + _pool.barrier(); +} + +void FallbackStream::visit(const BufferCopyCommand *command) noexcept { + _pool.async([cmd = *command] { + auto src = reinterpret_cast(cmd.src_handle() + cmd.src_offset()); + auto dst = reinterpret_cast(cmd.dst_handle() + cmd.dst_offset()); + std::memcpy(dst, src, cmd.size()); + }); + _pool.barrier(); +} + +void FallbackStream::visit(const BufferToTextureCopyCommand *command) noexcept { +// _pool.async([cmd = *command] { +// auto src = reinterpret_cast(cmd.buffer() + cmd.buffer_offset()); +// auto tex = reinterpret_cast(cmd.texture())->view(cmd.level()); +// tex.copy_from(src); +// }); +} + +//extern "C" void llvm_callback_dispatch(const CpuCallback *callbacks, void *arg, void *user_data, uint32_t callback_id) noexcept { +// callbacks[callback_id].callback(arg, user_data); +//} + +void FallbackStream::visit(const ShaderDispatchCommand *command) noexcept +{ + auto shader = reinterpret_cast(command->handle()); + shader->dispatch(_pool, command); +} + +void FallbackStream::visit(const TextureUploadCommand *command) noexcept { + + auto tex = reinterpret_cast(command->handle())->view(command->level()); + auto byte_size = pixel_storage_size(tex.storage(), tex.size3d()); + auto temp_buffer = luisa::make_shared>(byte_size); + std::memcpy(temp_buffer->data(), command->data(), byte_size); + _pool.async([cmd = *command, temp_buffer = std::move(temp_buffer)] { + auto tex = reinterpret_cast(cmd.handle())->view(cmd.level()); + auto byte_size = pixel_storage_size(tex.storage(), tex.size3d()); + std::memcpy(const_cast(tex.data()), temp_buffer->data(), byte_size); + }); + _pool.barrier(); +} + +void FallbackStream::visit(const TextureDownloadCommand *command) noexcept { + _pool.async([cmd = *command] { + auto tex = reinterpret_cast(cmd.handle())->view(cmd.level()); + tex.copy_to(cmd.data()); + }); + _pool.barrier(); +} + +void FallbackStream::visit(const TextureCopyCommand *command) noexcept { + _pool.async([cmd = *command] { + auto src_tex = reinterpret_cast(cmd.src_handle())->view(cmd.src_level()); + auto dst_tex = reinterpret_cast(cmd.dst_handle())->view(cmd.dst_level()); + dst_tex.copy_from(src_tex); + }); + _pool.barrier(); +} + +void FallbackStream::visit(const TextureToBufferCopyCommand *command) noexcept { + _pool.async([cmd = *command] { + auto tex = reinterpret_cast(cmd.texture())->view(cmd.level()); + auto dst = reinterpret_cast(cmd.buffer() + cmd.buffer_offset()); + tex.copy_to(dst); + }); +} + +void FallbackStream::visit(const AccelBuildCommand *command) noexcept { + auto accel = reinterpret_cast(command->handle()); + accel->build(_pool, command->instance_count(), command->modifications()); + _pool.barrier(); +} + +void FallbackStream::visit(const MeshBuildCommand *command) noexcept { + auto v_b = command->vertex_buffer(); + auto v_b_o = command->vertex_buffer_offset(); + auto v_s = command->vertex_stride(); + auto v_b_s = command->vertex_buffer_size(); + auto v_b_c = v_b_s/v_s; + auto t_b = command->triangle_buffer(); + auto t_b_o = command->triangle_buffer_offset(); + auto t_b_s = command->triangle_buffer_size(); + auto t_b_c = t_b_s/12u; + _pool.async([=,mesh = reinterpret_cast(command->handle())] + { + mesh->commit(v_b, v_b_o, v_s, v_b_c, t_b, t_b_o, t_b_c); + }); + _pool.barrier(); +} + +void FallbackStream::visit(const BindlessArrayUpdateCommand *command) noexcept { + + reinterpret_cast(command->handle())->update(_pool, command->modifications()); +} + +void FallbackStream::dispatch(luisa::move_only_function &&f) noexcept { +// auto ptr = new_with_allocator>(std::move(f)); +// _pool.async([ptr] { +// (*ptr)(); +// delete_with_allocator(ptr); +// }); +// _pool.barrier(); +} +FallbackStream::FallbackStream() noexcept { +} +void FallbackStream::visit(const CurveBuildCommand *command) noexcept { +} +void FallbackStream::visit(const ProceduralPrimitiveBuildCommand *command) noexcept { +} +void FallbackStream::visit(const MotionInstanceBuildCommand *command) noexcept { +} +void FallbackStream::visit(const CustomCommand *command) noexcept { +} + +}// namespace luisa::compute::llvm diff --git a/src/backends/fallback/fallback_stream.h b/src/backends/fallback/fallback_stream.h new file mode 100644 index 000000000..3d7641e76 --- /dev/null +++ b/src/backends/fallback/fallback_stream.h @@ -0,0 +1,54 @@ +// +// Created by Mike Smith on 2022/2/7. +// + +#pragma once + +#include "thread_pool.h" +#include + +namespace luisa::compute::fallback { + +class LLVMEvent; + +/** + * @brief Stream of LLVM + * + */ +class FallbackStream final : public CommandVisitor { + +private: + ThreadPool _pool; + +public: + FallbackStream() noexcept; + void synchronize() noexcept + { + _pool.synchronize(); + } + void dispatch(CommandList &&cmd_list) noexcept; + void dispatch(luisa::move_only_function &&f) noexcept; + void signal(LLVMEvent *event) noexcept; + void wait(LLVMEvent *event) noexcept; + +public: + void visit(const BufferUploadCommand *command) noexcept override; + void visit(const BufferDownloadCommand *command) noexcept override; + void visit(const BufferCopyCommand *command) noexcept override; + void visit(const BufferToTextureCopyCommand *command) noexcept override; + void visit(const ShaderDispatchCommand *command) noexcept override; + void visit(const TextureUploadCommand *command) noexcept override; + void visit(const TextureDownloadCommand *command) noexcept override; + void visit(const TextureCopyCommand *command) noexcept override; + void visit(const TextureToBufferCopyCommand *command) noexcept override; + void visit(const AccelBuildCommand *command) noexcept override; + void visit(const MeshBuildCommand *command) noexcept override; + void visit(const BindlessArrayUpdateCommand *command) noexcept override; + void visit(const CurveBuildCommand *command) noexcept override; + void visit(const ProceduralPrimitiveBuildCommand *command) noexcept override; + void visit(const MotionInstanceBuildCommand *command) noexcept override; + void visit(const CustomCommand *command) noexcept override; + ~FallbackStream() noexcept override = default; +}; + +}// namespace luisa::compute::llvm diff --git a/src/backends/fallback/fallback_texture.cpp b/src/backends/fallback/fallback_texture.cpp new file mode 100644 index 000000000..43b84d886 --- /dev/null +++ b/src/backends/fallback/fallback_texture.cpp @@ -0,0 +1,522 @@ +// +// Created by Mike Smith on 2022/6/8. +// + +#include +#include +#include "fallback_texture.h" + +#include "luisa/rust/api_types.hpp" + +namespace luisa::compute::fallback { + +namespace detail { +template +struct alignas(stride) Pixel : std::array {}; +}// namespace detail + +void FallbackTextureView::copy_from(const void *data) const noexcept { + auto LC_TEXTURE_COPY = [data, this]() mutable noexcept { + auto p = static_cast *>(data); + for (auto z = 0u; z < (dim == 2u ? 1u : _depth); z++) { + for (auto y = 0u; y < _height; y++) { + for (auto x = 0u; x < _width; x++) { + auto pp = p + ((z * _height + y) * _width + x); + if constexpr (dim == 2) { + auto pixel = reinterpret_cast *>( + _pixel2d(make_uint2(x, y))); + *pixel = *pp; + } else { + auto pixel = reinterpret_cast *>( + _pixel3d(make_uint3(x, y, z))); + *pixel = *pp; + } + } + } + } + }; + if (_dimension == 2u) { + switch (_pixel_stride_shift) { + case 0u: LC_TEXTURE_COPY.operator()<2u, 1u>(); break; + case 1u: LC_TEXTURE_COPY.operator()<2u, 2u>(); break; + case 2u: LC_TEXTURE_COPY.operator()<2u, 4u>(); break; + case 3u: LC_TEXTURE_COPY.operator()<2u, 8u>(); break; + case 4u: LC_TEXTURE_COPY.operator()<2u, 16u>(); break; + default: break; + } + } else { + switch (_pixel_stride_shift) { + case 0u: LC_TEXTURE_COPY.operator()<3u, 1u>(); break; + case 1u: LC_TEXTURE_COPY.operator()<3u, 2u>(); break; + case 2u: LC_TEXTURE_COPY.operator()<3u, 4u>(); break; + case 3u: LC_TEXTURE_COPY.operator()<3u, 8u>(); break; + case 4u: LC_TEXTURE_COPY.operator()<3u, 16u>(); break; + default: break; + } + } +} + +void FallbackTextureView::copy_to(void *data) const noexcept { + memcpy(data, this->_data, this->size_bytes()); +} + +void FallbackTextureView::copy_from(FallbackTextureView dst) const noexcept { + LUISA_ASSERT(size_bytes() == dst.size_bytes(), "Texture sizes must match."); + std::memcpy(dst._data, _data, size_bytes()); +} + +namespace detail { + +[[nodiscard]] inline auto decode_texture_view(int64_t t0, int64_t t1) noexcept { + return luisa::bit_cast(std::array{t0, t1}); +} + +// from tinyexr: https://github.com/syoyo/tinyexr/blob/master/tinyexr.h +float16_t float_to_half(float f) noexcept { +#if defined(LUISA_ARCH_ARM64) + return static_cast(f); +#elif defined(LUISA_ARCH_X86_64) + auto ss = _mm_set_ss(f); + auto ph = _mm_cvtps_ph(ss, 0); + return static_cast(_mm_cvtsi128_si32(ph)); +#else + auto bits = luisa::bit_cast(f); + auto fp32_sign = bits >> 31u; + auto fp32_exponent = (bits >> 23u) & 0xffu; + auto fp32_mantissa = bits & ((1u << 23u) - 1u); + auto make_fp16 = [](uint sign, uint exponent, uint mantissa) noexcept { + return static_cast((sign << 15u) | (exponent << 10u) | mantissa); + }; + // Signed zero/denormal (which will underflow) + if (fp32_exponent == 0u) { return make_fp16(fp32_sign, 0u, 0u); } + // Inf or NaN (all exponent bits set) + if (fp32_exponent == 255u) { + return make_fp16( + fp32_sign, 31u, + // NaN->qNaN and Inf->Inf + fp32_mantissa ? 0x200u : 0u); + } + // Exponent unbias the single, then bias the halfp + auto newexp = static_cast(fp32_exponent - 127u + 15u); + // Overflow, return signed infinity + if (newexp >= 31) { return make_fp16(fp32_sign, 31u, 0u); } + // Underflow + if (newexp <= 0) { + if ((14 - newexp) > 24) { return 0u; } + // Mantissa might be non-zero + unsigned int mant = fp32_mantissa | 0x800000u;// Hidden 1 bit + auto fp16 = make_fp16(fp32_sign, 0u, mant >> (14u - newexp)); + if ((mant >> (13u - newexp)) & 1u) { fp16++; }// Check for rounding + return fp16; + } + auto fp16 = make_fp16(fp32_sign, newexp, fp32_mantissa >> 13u); + if (fp32_mantissa & 0x1000u) { fp16++; }// Check for rounding + return fp16; +#endif +} + +float half_to_float(float16_t half) noexcept { +#if defined(LUISA_ARCH_ARM64) + return static_cast(half); +#elif defined(LUISA_ARCH_X86_64) + auto si = _mm_cvtsi32_si128(half); + auto ps = _mm_cvtph_ps(si); + return _mm_cvtss_f32(ps); +#else + static_assert(std::endian::native == std::endian::little, + "Only little endian is supported"); + auto h = static_cast(half); + union FP32 { + unsigned int u; + float f; + struct {// FIXME: assuming little endian here + unsigned int Mantissa : 23; + unsigned int Exponent : 8; + unsigned int Sign : 1; + } s; + }; + constexpr auto magic = FP32{113u << 23u}; + constexpr auto shifted_exp = 0x7c00u << 13u;// exponent mask after shift + auto o = FP32{(h & 0x7fffu) << 13u}; // exponent/mantissa bits + auto exp_ = shifted_exp & o.u; // just the exponent + o.u += (127u - 15u) << 23u; // exponent adjust + + // handle exponent special cases + if (exp_ == shifted_exp) { // Inf/NaN? + o.u += (128u - 16u) << 23u;// extra exp adjust + } else if (exp_ == 0u) { // Zero/Denormal? + o.u += 1u << 23u; // extra exp adjust + o.f -= magic.f; // renormalize + } + o.u |= (h & 0x8000u) << 16u;// sign bit + return o.f; +#endif +} + +// MIP-Map EWA filtering LUT from PBRT-v4 +static constexpr const std::array ewa_filter_weight_lut{ + 0.8646647330f, 0.8490400310f, 0.8336595300f, 0.8185192940f, 0.8036156300f, 0.78894478100f, 0.7745032310f, 0.7602872850f, + 0.7462934850f, 0.7325183150f, 0.7189583780f, 0.7056102750f, 0.6924707890f, 0.67953658100f, 0.6668044920f, 0.6542713050f, + 0.6419339780f, 0.6297893520f, 0.6178345080f, 0.6060665250f, 0.5944823620f, 0.58307915900f, 0.5718541740f, 0.5608045460f, + 0.5499275920f, 0.5392205720f, 0.5286808610f, 0.5183058380f, 0.5080928800f, 0.49803954400f, 0.4881432650f, 0.4784016010f, + 0.4688121680f, 0.4593725800f, 0.4500804540f, 0.4409335260f, 0.4319294690f, 0.42306613900f, 0.4143413310f, 0.4057527780f, + 0.3972984550f, 0.3889762160f, 0.3807840350f, 0.3727198840f, 0.3647816180f, 0.35696744900f, 0.3492754100f, 0.3417034750f, + 0.3342499140f, 0.3269128200f, 0.3196903470f, 0.3125807050f, 0.3055821660f, 0.29869294200f, 0.2919114230f, 0.2852358220f, + 0.2786645290f, 0.2721959350f, 0.2658283710f, 0.2595603470f, 0.2533901930f, 0.24731649500f, 0.2413376720f, 0.2354522790f, + 0.2296588570f, 0.2239559440f, 0.2183421400f, 0.2128160450f, 0.2073762860f, 0.20202152400f, 0.1967504470f, 0.1915617140f, + 0.1864540130f, 0.1814261530f, 0.1764768510f, 0.1716048870f, 0.1668090670f, 0.16208814100f, 0.1574410050f, 0.1528664680f, + 0.1483634260f, 0.1439307180f, 0.1395672710f, 0.1352720110f, 0.1310438660f, 0.12688179300f, 0.1227847190f, 0.1187516900f, + 0.1147816330f, 0.1108736400f, 0.1070266960f, 0.1032398790f, 0.0995122194f, 0.09584279360f, 0.0922307223f, 0.0886750817f, + 0.0851749927f, 0.0817295909f, 0.0783380121f, 0.0749994367f, 0.0717130303f, 0.06847797330f, 0.0652934611f, 0.0621587038f, + 0.0590728968f, 0.0560353249f, 0.0530452281f, 0.0501018465f, 0.0472044498f, 0.04435232280f, 0.0415447652f, 0.0387810767f, + 0.0360605568f, 0.0333825648f, 0.0307464004f, 0.0281514227f, 0.0255970061f, 0.02308247980f, 0.0206072628f, 0.0181707144f, + 0.0157722086f, 0.0134112090f, 0.0110870898f, 0.0087992847f, 0.0065472275f, 0.00433036685f, 0.0021481365f, 0.0000000000f}; + +}// namespace detail + +FallbackTexture::FallbackTexture(PixelStorage storage, uint dim, uint3 size, uint levels) noexcept + : _storage{storage}, _mip_levels{levels}, _dimension{dim} + { + if (_dimension == 2u) { + _pixel_stride_shift = std::bit_width(static_cast(pixel_storage_align(storage))) - 1u; + if (storage == PixelStorage::BC6 || storage == PixelStorage::BC7) { + _pixel_stride_shift = 0u; + } + _size[0] = size.x; + _size[1] = size.y; + _size[2] = 1u; + _mip_offsets[0] = 0u; + auto sz = make_uint2(size); + for (auto i = 1u; i < levels; i++) { + auto s = (sz + block_size - 1u) / block_size * block_size; + _mip_offsets[i] = _mip_offsets[i - 1u] + s.x * s.y; + sz = luisa::max(sz >> 1u, 1u); + } + auto s = (sz + block_size - 1u) / block_size * block_size; + auto size_pixels = _mip_offsets[levels - 1u] + s.x * s.y; + _data = luisa::allocate_with_allocator(static_cast(size_pixels) << _pixel_stride_shift); + } else { + _size[0] = size.x; + _size[1] = size.y; + _size[2] = size.z; + _mip_offsets[0] = 0u; + for (auto i = 1u; i < levels; i++) { + auto s = (size + block_size - 1u) / block_size * block_size; + _mip_offsets[i] = _mip_offsets[i - 1u] + s.x * s.y * s.z; + size = luisa::max(size >> 1u, 1u); + } + auto s = (size + block_size - 1u) / block_size * block_size; + auto size_pixels = _mip_offsets[levels - 1u] + s.x * s.y * s.z; + _data = luisa::allocate_with_allocator(static_cast(size_pixels) << _pixel_stride_shift); + } +} + +FallbackTexture::~FallbackTexture() noexcept { luisa::deallocate_with_allocator(_data); } + +FallbackTextureView FallbackTexture::view(uint level) const noexcept { + auto size = luisa::max(make_uint3(_size[0], _size[1], _size[2]) >> level, 1u); + return FallbackTextureView{_data + (static_cast(_mip_offsets[level]) << _pixel_stride_shift), + _dimension, size.x, size.y, size.z, _storage, _pixel_stride_shift}; +} + +//float4 FallbackTexture::read2d(uint level, uint2 uv) const noexcept { +// return view(level).read2d(uv); +//} +// +//float4 FallbackTexture::read3d(uint level, uint3 uvw) const noexcept { +// return view(level).read3d(uvw); +//} + +template +[[nodiscard]] inline auto texture_coord_point(Sampler::Address address, T uv, T s) noexcept { + switch (address) { + case Sampler::Address::EDGE: return luisa::clamp(uv, 0.0f, one_minus_epsilon) * s; + case Sampler::Address::REPEAT: return luisa::fract(uv) * s; + case Sampler::Address::MIRROR: { + uv = luisa::fmod(luisa::abs(uv), T{2.0f}); + uv = select(2.f - uv, uv, uv < T{1.f}); + return luisa::min(uv, one_minus_epsilon) * s; + } + case Sampler::Address::ZERO: return luisa::select(uv * s, T{65536.f}, uv < 0.f || uv >= 1.f); + } + return T{65536.f}; +} + + +[[nodiscard]] inline auto texture_coord_linear(Sampler::Address address, float3 uv, float3 size) noexcept { + auto s = make_float3(size); + auto inv_s = 1.f / s; + auto c_min = texture_coord_point(address, uv - .5f * inv_s, s); + auto c_max = texture_coord_point(address, uv + .5f * inv_s, s); + return std::make_pair(luisa::min(c_min, c_max), luisa::max(c_min, c_max)); +} + +[[nodiscard]] inline auto texture_sample_linear(FallbackTextureView view, Sampler::Address address, float3 uvw) noexcept { + auto size = make_float3(view.size3d()); + auto [st_min, st_max] = texture_coord_linear(address, uvw, size); + auto t = luisa::fract(st_max); + auto c0 = make_uint3(st_min); + auto c1 = make_uint3(st_max); + auto v000 = view.read3d(make_uint3(c0.x, c0.y, c0.z)); + auto v001 = view.read3d(make_uint3(c1.x, c0.y, c0.z)); + auto v010 = view.read3d(make_uint3(c0.x, c1.y, c0.z)); + auto v011 = view.read3d(make_uint3(c1.x, c1.y, c0.z)); + auto v100 = view.read3d(make_uint3(c0.x, c0.y, c1.z)); + auto v101 = view.read3d(make_uint3(c1.x, c0.y, c1.z)); + auto v110 = view.read3d(make_uint3(c0.x, c1.y, c1.z)); + auto v111 = view.read3d(make_uint3(c1.x, c1.y, c1.z)); + return luisa::lerp( + luisa::lerp(luisa::lerp(v000, v001, t.x), + luisa::lerp(v010, v011, t.x), t.y), + luisa::lerp(luisa::lerp(v100, v101, t.x), + luisa::lerp(v110, v111, t.x), t.y), + t.z); +} + +[[nodiscard]] inline auto texture_sample_point(FallbackTextureView view, Sampler::Address address, float2 uv) noexcept { + auto size = make_float2(view.size2d()); + auto c = make_uint2(texture_coord_point(address, uv, size)); + return view.read2d(c); +} + +[[nodiscard]] inline auto texture_sample_point(FallbackTextureView view, Sampler::Address address, float3 uvw) noexcept { + auto size = make_float3(view.size3d()); + auto c = make_uint3(texture_coord_point(address, uvw, size)); + return view.read3d(c); +} + +// from PBRT-v4 +[[nodiscard]] inline auto texture_sample_ewa(FallbackTextureView view, Sampler::Address address, + float2 uv, float2 dst0, float2 dst1) noexcept { + auto size = make_float2(view.size2d()); + auto st = uv * size - .5f; + dst0 = dst0 * size; + dst1 = dst1 * size; + + constexpr auto sqr = [](float x) noexcept { return x * x; }; + constexpr auto safe_sqrt = [](float x) noexcept { return luisa::select(std::sqrt(x), 0.f, x <= 0.f); }; + + // Find ellipse coefficients that bound EWA filter region + auto A = sqr(dst0.y) + sqr(dst1.y) + 1.f; + auto B = -2.f * (dst0.x * dst0.y + dst1.x * dst1.y); + auto C = sqr(dst0.x) + sqr(dst1.x) + 1.f; + auto inv_f = 1.f / (A * C - sqr(B) * 0.25f); + A *= inv_f; + B *= inv_f; + C *= inv_f; + + // Compute the ellipse's $(s,t)$ bounding box in texture space + auto det = -sqr(B) + 4.f * A * C; + auto inv_det = 1.f / det; + auto sqrt_u = safe_sqrt(det * C); + auto sqrt_v = safe_sqrt(A * det); + auto s_min = static_cast(std::ceil(st.x - 2.f * inv_det * sqrt_u)); + auto s_max = static_cast(std::floor(st.x + 2.f * inv_det * sqrt_u)); + auto t_min = static_cast(std::ceil(st.y - 2.f * inv_det * sqrt_v)); + auto t_max = static_cast(std::floor(st.y + 2.f * inv_det * sqrt_v)); + + // Scan over ellipse bound and evaluate quadratic equation to filter image + auto sum = make_float4(); + auto sum_w = 0.f; + auto inv_size = 1.f / size; + for (auto t = t_min; t <= t_max; t++) { + for (auto s = s_min; s <= s_max; s++) { + auto ss = static_cast(s) - st.x; + auto tt = static_cast(t) - st.y; + // Compute squared radius and filter texel if it is inside the ellipse + if (auto rr = A * sqr(ss) + B * ss * tt + C * sqr(tt); rr < 1.f) { + constexpr auto lut_size = static_cast(detail::ewa_filter_weight_lut.size()); + auto index = std::clamp(rr * lut_size, 0.f, lut_size - 1.f); + auto weight = detail::ewa_filter_weight_lut[static_cast(index)]; + auto p = texture_coord_point(address, uv + make_float2(ss, tt) * inv_size, size); + sum += weight * view.read2d(make_uint2(p)); + sum_w += weight; + } + } + } + return select(sum / sum_w, make_float4(0.f), sum_w <= 0.f); +} + +[[nodiscard]] inline auto texture_sample_ewa(FallbackTextureView view, Sampler::Address address, + float3 uvw, float3 ddx, float3 ddy) noexcept { + // FIXME: anisotropic filtering + return texture_sample_linear(view, address, uvw); +} + +//float4 FallbackTexture::sample2d(Sampler sampler, float2 uv) const noexcept { +// return sampler.filter() == Sampler::Filter::POINT ? +// texture_sample_point(view(0), sampler.address(), uv) : +// texture_sample_linear(view(0), sampler.address(), uv); +//} + +//float4 FallbackTexture::sample3d(Sampler sampler, float3 uvw) const noexcept { +// return sampler.filter() == Sampler::Filter::POINT ? +// texture_sample_point(view(0), sampler.address(), uvw) : +// texture_sample_linear(view(0), sampler.address(), uvw); +//} + +//float4 FallbackTexture::sample2d(Sampler sampler, float2 uv, float lod) const noexcept { +// auto filter = sampler.filter(); +// if (lod <= 0.f || _mip_levels == 0u || +// filter == Sampler::Filter::POINT) { +// return sample2d(sampler, uv); +// } +// auto level0 = std::min(static_cast(lod), +// _mip_levels - 1u); +// auto v0 = texture_sample_linear( +// view(level0), sampler.address(), uv); +// if (level0 == _mip_levels - 1u || +// filter == Sampler::Filter::LINEAR_POINT) { +// return v0; +// } +// auto v1 = texture_sample_linear( +// view(level0 + 1u), sampler.address(), uv); +// return luisa::lerp(v0, v1, luisa::fract(lod)); +//} + +//float4 FallbackTexture::sample3d(Sampler sampler, float3 uvw, float lod) const noexcept { +// auto filter = sampler.filter(); +// if (lod <= 0.f || _mip_levels == 0u || +// filter == Sampler::Filter::POINT) { +// return sample3d(sampler, uvw); +// } +// auto level0 = std::min(static_cast(lod), +// _mip_levels - 1u); +// auto v0 = texture_sample_linear( +// view(level0), sampler.address(), uvw); +// if (level0 == _mip_levels - 1u || +// filter == Sampler::Filter::LINEAR_POINT) { +// return v0; +// } +// auto v1 = texture_sample_linear( +// view(level0 + 1u), sampler.address(), uvw); +// return luisa::lerp(v0, v1, luisa::fract(lod)); +//} + +//float4 FallbackTexture::sample2d(Sampler sampler, float2 uv, float2 dpdx, float2 dpdy) const noexcept { +// constexpr auto ll = [](float2 v) noexcept { return dot(v, v); }; +// if (all(dpdx == 0.f) || all(dpdy == 0.f)) { return sample2d(sampler, uv); } +// if (sampler.filter() != Sampler::Filter::ANISOTROPIC) { +// auto s = make_float2(_size[0], _size[1]); +// auto level = .5f * std::log2(std::max(ll(dpdx * s), ll(dpdy * s))); +// return sample2d(sampler, uv, level); +// } +// auto longer = length(dpdx); +// auto shorter = length(dpdy); +// if (longer < shorter) { +// std::swap(longer, shorter); +// std::swap(dpdx, dpdy); +// } +// constexpr auto max_anisotropy = 16.f; +// if (auto s = shorter * max_anisotropy; s < longer) { +// auto scale = longer / s; +// dpdy *= scale; +// shorter *= scale; +// } +// auto last_level = static_cast(_mip_levels - 1u); +// auto level = std::clamp(last_level + std::log2(shorter), 0.f, last_level); +// auto level_uint = static_cast(level); +// auto v0 = texture_sample_ewa(view(level_uint), sampler.address(), uv, dpdx, dpdy); +// if (level == 0.f || level == last_level) { return v0; } +// auto v1 = texture_sample_ewa(view(level_uint + 1u), sampler.address(), uv, dpdx, dpdy); +// return luisa::lerp(v0, v1, luisa::fract(level)); +//} +// +//float4 FallbackTexture::sample3d(Sampler sampler, float3 uvw, float3 dpdx, float3 dpdy) const noexcept { +// constexpr auto ll = [](float3 v) noexcept { return dot(v, v); }; +// if (all(dpdx == 0.f) || all(dpdy == 0.f)) { return sample3d(sampler, uvw); } +// if (sampler.filter() != Sampler::Filter::ANISOTROPIC) { +// auto s = make_float3(_size[0], _size[1], _size[2]); +// auto level = .5f * std::log2(std::max(ll(dpdx * s), ll(dpdy * s))); +// return sample3d(sampler, uvw, level); +// } +// auto longer = length(dpdx); +// auto shorter = length(dpdy); +// if (longer < shorter) { +// std::swap(longer, shorter); +// std::swap(dpdx, dpdy); +// } +// constexpr auto max_anisotropy = 16.f; +// if (auto s = shorter * max_anisotropy; s < longer) { +// auto scale = longer / s; +// dpdy *= scale; +// shorter *= scale; +// } +// auto last_level = static_cast(_mip_levels - 1u); +// auto level = std::clamp(last_level + std::log2(shorter), 0.f, last_level); +// auto level_uint = static_cast(level); +// auto v0 = texture_sample_ewa(view(level_uint), sampler.address(), uvw, dpdx, dpdy); +// if (level == 0.f || level == last_level) { return v0; } +// auto v1 = texture_sample_ewa(view(level_uint + 1u), sampler.address(), uvw, dpdx, dpdy); +// return luisa::lerp(v0, v1, luisa::fract(level)); +//} + +void texture_write_2d_int(int64_t t0, int64_t t1, int64_t c0, int64_t c1, int64_t v0, int64_t v1) noexcept { + detail::decode_texture_view(t0, t1).write2d( + detail::decode_uint2(c0), detail::decode_int4(v0, v1)); +} + +void texture_write_3d_int(int64_t t0, int64_t t1, int64_t c0, int64_t c1, int64_t v0, int64_t v1) noexcept { + detail::decode_texture_view(t0, t1).write3d( + detail::decode_uint3(c0, c1), detail::decode_int4(v0, v1)); +} + +void texture_write_2d_uint(int64_t t0, int64_t t1, int64_t c0, int64_t c1, int64_t v0, int64_t v1) noexcept { + detail::decode_texture_view(t0, t1).write2d( + detail::decode_uint2(c0), + detail::decode_uint4(v0, v1)); +} + +void texture_write_3d_uint(int64_t t0, int64_t t1, int64_t c0, int64_t c1, int64_t v0, int64_t v1) noexcept { + detail::decode_texture_view(t0, t1).write3d( + detail::decode_uint3(c0, c1), detail::decode_uint4(v0, v1)); +} + +void texture_write_2d_float(int64_t t0, int64_t t1, int64_t c0, int64_t c1, int64_t v0, int64_t v1) noexcept { + detail::decode_texture_view(t0, t1).write2d( + detail::decode_uint2(c0), detail::decode_float4(v0, v1)); +} + +void texture_write_3d_float(int64_t t0, int64_t t1, int64_t c0, int64_t c1, int64_t v0, int64_t v1) noexcept { + detail::decode_texture_view(t0, t1).write3d( + detail::decode_uint3(c0, c1), detail::decode_float4(v0, v1)); +} + +float32x4_t texture_read_2d_int(int64_t t0, int64_t t1, int64_t c0, int64_t c1) noexcept { + return detail::encode_int4( + detail::decode_texture_view(t0, t1).read2d( + detail::decode_uint2(c0))); +} + +float32x4_t texture_read_3d_int(int64_t t0, int64_t t1, int64_t c0, int64_t c1) noexcept { + return detail::encode_int4( + detail::decode_texture_view(t0, t1).read3d( + detail::decode_uint3(c0, c1))); +} + +float32x4_t texture_read_2d_uint(int64_t t0, int64_t t1, int64_t c0, int64_t c1) noexcept { + return detail::encode_uint4( + detail::decode_texture_view(t0, t1).read2d( + detail::decode_uint2(c0))); +} + +float32x4_t texture_read_3d_uint(int64_t t0, int64_t t1, int64_t c0, int64_t c1) noexcept { + return detail::encode_uint4( + detail::decode_texture_view(t0, t1).read3d( + detail::decode_uint3(c0, c1))); +} + +float32x4_t texture_read_2d_float(int64_t t0, int64_t t1, int64_t c0, int64_t c1) noexcept { + return detail::encode_float4( + detail::decode_texture_view(t0, t1).read2d( + detail::decode_uint2(c0))); +} + +float32x4_t texture_read_3d_float(int64_t t0, int64_t t1, int64_t c0, int64_t c1) noexcept { + return detail::encode_float4( + detail::decode_texture_view(t0, t1).read3d( + detail::decode_uint3(c0, c1))); +} + + +}// namespace luisa::compute::fallback diff --git a/src/backends/fallback/fallback_texture.h b/src/backends/fallback/fallback_texture.h new file mode 100644 index 000000000..8e04a94f2 --- /dev/null +++ b/src/backends/fallback/fallback_texture.h @@ -0,0 +1,498 @@ +// +// Created by Mike Smith on 2022/6/8. +// + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include "llvm_abi.h" + +namespace luisa::compute::fallback +{ + namespace detail + { + [[nodiscard]] float16_t float_to_half(float f) noexcept; + + [[nodiscard]] float half_to_float(float16_t h) noexcept; + + template + [[nodiscard]] inline float scalar_to_float(T x) noexcept + { + if constexpr (std::is_same_v) + { + return x; + } + else if constexpr (std::is_same_v) + { + return x / 255.f; + } + else if constexpr (std::is_same_v) + { + return x / 65535.f; + } + else if constexpr (std::is_same_v) + { + return half_to_float(x); + } + else + { + return 0.f; + } + } + + template + [[nodiscard]] inline T float_to_scalar(float x) noexcept + { + if constexpr (std::is_same_v) + { + return x; + } + else if constexpr (std::is_same_v) + { + return static_cast(std::clamp(std::round(x * 255.f), 0.f, 255.f)); + } + else if constexpr (std::is_same_v) + { + return static_cast(std::clamp(std::round(x * 65535.f), 0.f, 65535.f)); + } + else if constexpr (std::is_same_v) + { + return static_cast(float_to_half(x)); + } + else + { + return static_cast(0); + } + } + + template + [[nodiscard]] inline uint scalar_to_int(T x) noexcept + { + return static_cast(x); + } + + template + [[nodiscard]] inline T int_to_scalar(uint x) noexcept + { + return static_cast(x); + } + + template + [[nodiscard]] inline float4 pixel_to_float4(const std::byte* pixel) noexcept + { + auto value = reinterpret_cast(pixel); + if constexpr (dim == 1u) + { + return make_float4( + scalar_to_float(value[0]), + 0.f, 0.0f, 0.f); + } + else if constexpr (dim == 2u) + { + return make_float4( + scalar_to_float(value[0]), + scalar_to_float(value[1]), + 0.0f, 0.f); + } + else if constexpr (dim == 4u) + { + return make_float4( + scalar_to_float(value[0]), + scalar_to_float(value[1]), + scalar_to_float(value[2]), + scalar_to_float(value[3])); + } + else + { + return make_float4(); + } + } + + template + inline void float4_to_pixel(std::byte* pixel, float4 v) noexcept + { + auto value = reinterpret_cast(pixel); + if constexpr (dim == 1u) + { + value[0] = float_to_scalar(v[0]); + } + else if constexpr (dim == 2u) + { + value[0] = float_to_scalar(v[0]); + value[1] = float_to_scalar(v[1]); + } + else if constexpr (dim == 4u) + { + value[0] = float_to_scalar(v[0]); + value[1] = float_to_scalar(v[1]); + value[2] = float_to_scalar(v[2]); + value[3] = float_to_scalar(v[3]); + } + } + + template + [[nodiscard]] inline uint4 pixel_to_int4(const std::byte* pixel) noexcept + { + auto value = reinterpret_cast(pixel); + if constexpr (dim == 1u) + { + return make_uint4( + scalar_to_int(value[0]), + 0u, 0u, 0u); + } + else if constexpr (dim == 2u) + { + return make_uint4( + scalar_to_int(value[0]), + scalar_to_int(value[1]), + 0u, 0u); + } + else if constexpr (dim == 4u) + { + return make_uint4( + scalar_to_int(value[0]), + scalar_to_int(value[1]), + scalar_to_int(value[2]), + scalar_to_int(value[3])); + } + else + { + return make_uint4(); + } + } + + template + inline void int4_to_pixel(std::byte* pixel, uint4 v) noexcept + { + auto value = reinterpret_cast(pixel); + if constexpr (dim == 1u) + { + value[0] = int_to_scalar(v[0]); + } + else if constexpr (dim == 2u) + { + value[0] = int_to_scalar(v[0]); + value[1] = int_to_scalar(v[1]); + } + else if constexpr (dim == 4u) + { + value[0] = int_to_scalar(v[0]); + value[1] = int_to_scalar(v[1]); + value[2] = int_to_scalar(v[2]); + value[3] = int_to_scalar(v[3]); + } + } + + template + [[nodiscard]] inline auto read_pixel(const std::byte* p) noexcept + { + if constexpr (std::is_same_v) + { + return pixel_to_float4(p); + } + else + { + static_assert(std::is_same_v || + std::is_same_v); + return luisa::bit_cast>( + pixel_to_int4(p)); + } + } + + template + [[nodiscard]] inline auto write_pixel(std::byte* p, Vector value) noexcept + { + if constexpr (std::is_same_v) + { + float4_to_pixel(p, value); + } + else + { + static_assert(std::is_same_v || + std::is_same_v); + int4_to_pixel( + p, luisa::bit_cast(value)); + } + } + + template + [[nodiscard]] inline Vector read_pixel(PixelStorage storage, const std::byte* p) noexcept + { + switch (storage) + { + case PixelStorage::BYTE1: return detail::read_pixel(p); + case PixelStorage::BYTE2: return detail::read_pixel(p); + case PixelStorage::BYTE4: return detail::read_pixel(p); + case PixelStorage::SHORT1: return detail::read_pixel(p); + case PixelStorage::SHORT2: return detail::read_pixel(p); + case PixelStorage::SHORT4: return detail::read_pixel(p); + case PixelStorage::INT1: return detail::read_pixel(p); + case PixelStorage::INT2: return detail::read_pixel(p); + case PixelStorage::INT4: return detail::read_pixel(p); + case PixelStorage::HALF1: return detail::read_pixel(p); + case PixelStorage::HALF2: return detail::read_pixel(p); + case PixelStorage::HALF4: return detail::read_pixel(p); + case PixelStorage::FLOAT1: return detail::read_pixel(p); + case PixelStorage::FLOAT2: return detail::read_pixel(p); + case PixelStorage::FLOAT4: return detail::read_pixel(p); + default: break; + } + return {}; + } + + template + inline void write_pixel(PixelStorage storage, std::byte* p, Vector v) noexcept + { + switch (storage) + { + case PixelStorage::BYTE1: detail::write_pixel(p, v); + break; + case PixelStorage::BYTE2: detail::write_pixel(p, v); + break; + case PixelStorage::BYTE4: detail::write_pixel(p, v); + break; + case PixelStorage::SHORT1: detail::write_pixel(p, v); + break; + case PixelStorage::SHORT2: detail::write_pixel(p, v); + break; + case PixelStorage::SHORT4: detail::write_pixel(p, v); + break; + case PixelStorage::INT1: detail::write_pixel(p, v); + break; + case PixelStorage::INT2: detail::write_pixel(p, v); + break; + case PixelStorage::INT4: detail::write_pixel(p, v); + break; + case PixelStorage::HALF1: detail::write_pixel(p, v); + break; + case PixelStorage::HALF2: detail::write_pixel(p, v); + break; + case PixelStorage::HALF4: detail::write_pixel(p, v); + break; + case PixelStorage::FLOAT1: detail::write_pixel(p, v); + break; + case PixelStorage::FLOAT2: detail::write_pixel(p, v); + break; + case PixelStorage::FLOAT4: detail::write_pixel(p, v); + break; + default: break; + } + } + } // namespace detail + + class FallbackTexture; + class FallbackTextureView; + + class alignas(16u) FallbackTexture + { + public: + static constexpr auto block_size = 4u; + + private: + std::byte* _data{nullptr}; // 8B + std::array _size{}; // 14B + PixelStorage _storage: 16u; // 16B + uint _pixel_stride_shift: 8u; // 18B + uint _mip_levels: 8u; // 19B + uint _dimension: 8u; // 20B + std::array _mip_offsets{}; // 80B + + public: + FallbackTexture(PixelStorage storage, uint dim, uint3 size, uint levels) noexcept; + + ~FallbackTexture() noexcept; + + FallbackTexture(FallbackTexture&&) noexcept = delete; + + FallbackTexture(const FallbackTexture&) noexcept = delete; + + FallbackTexture& operator=(FallbackTexture&&) noexcept = delete; + + FallbackTexture& operator=(const FallbackTexture&) noexcept = delete; + + [[nodiscard]] FallbackTextureView view(uint level) const noexcept; + + [[nodiscard]] auto storage() const noexcept { return _storage; } + [[nodiscard]] auto mip_levels() const noexcept { return _mip_levels; } + + // reading + // [[nodiscard]] float4 read2d(uint level, uint2 uv) const noexcept; + // [[nodiscard]] float4 read3d(uint level, uint3 uvw) const noexcept; + // + // // sampling + // [[nodiscard]] float4 sample2d(Sampler sampler, float2 uv) const noexcept; + // [[nodiscard]] float4 sample3d(Sampler sampler, float3 uvw) const noexcept; + // [[nodiscard]] float4 sample2d(Sampler sampler, float2 uv, float lod) const noexcept; + // [[nodiscard]] float4 sample3d(Sampler sampler, float3 uvw, float lod) const noexcept; + // [[nodiscard]] float4 sample2d(Sampler sampler, float2 uv, float2 dpdx, float2 dpdy) const noexcept; + // [[nodiscard]] float4 sample3d(Sampler sampler, float3 uvw, float3 dpdx, float3 dpdy) const noexcept; + }; + + class alignas(16u) FallbackTextureView + { + private: + std::byte* _data; // 8B + uint _width: 16u; // 10B + uint _height: 16u; // 12B + uint _depth: 16u; // 14B + PixelStorage _storage: 8u; // 15B + uint _dimension: 4u; + uint _pixel_stride_shift: 4u; // 16B + + public: + static constexpr auto block_size = FallbackTexture::block_size; + const std::byte* data() const noexcept { return _data; } + const PixelStorage storage() const noexcept { return _storage; } + + private: + [[nodiscard]] inline std::byte* _pixel2d(uint2 xy) const noexcept + { + auto idx = xy.x + xy.y * _width; + return _data + (static_cast(idx) << _pixel_stride_shift); + } + + [[nodiscard]] inline std::byte* _pixel3d(uint3 xyz) const noexcept + { + auto idx = xyz.x + xyz.y * _width + xyz.z * _width * _height; + return _data + (static_cast(idx) << _pixel_stride_shift); + } + + [[nodiscard]] inline auto _out_of_bounds(uint2 xy) const noexcept + { + return !(xy[0] < _width & xy[1] < _height); + } + + [[nodiscard]] inline auto _out_of_bounds(uint3 xyz) const noexcept + { + return !(xyz[0] < _width & xyz[1] < _height & xyz[2] < _depth); + } + + private: + friend class FallbackTexture; + + FallbackTextureView(std::byte* data, uint dim, uint w, uint h, uint d, + PixelStorage storage, uint pixel_stride_shift) noexcept + : _data(data), _width{w}, _height{h}, _depth{d}, _storage(storage), + _dimension{dim}, _pixel_stride_shift(pixel_stride_shift) + { + } + + public: + template + [[nodiscard]] inline Vector read2d(uint2 xy) const noexcept + { + if (_out_of_bounds(xy)) [[unlikely]] { return {}; } + return detail::read_pixel(_storage, _pixel2d(xy)); + } + + template + [[nodiscard]] inline Vector read3d(uint3 xyz) const noexcept + { + if (_out_of_bounds(xyz)) [[unlikely]] { return {}; } + return detail::read_pixel(_storage, _pixel3d(xyz)); + } + + template + inline void write2d(uint2 xy, Vector value) const noexcept + { + if (_out_of_bounds(xy)) [[unlikely]] { return; } + detail::write_pixel(_storage, _pixel2d(xy), value); + } + + template + inline void write3d(uint3 xyz, Vector value) const noexcept + { + if (_out_of_bounds(xyz)) [[unlikely]] { return; } + detail::write_pixel(_storage, _pixel3d(xyz), value); + } + + [[nodiscard]] auto size2d() const noexcept { return make_uint2(_width, _height); } + [[nodiscard]] auto size3d() const noexcept { return make_uint3(_width, _height, _depth); } + [[nodiscard]] auto size_bytes() const noexcept { return (_width * _height * _depth) << _pixel_stride_shift; } + + void copy_from(const void* data) const noexcept; + + void copy_to(void* data) const noexcept; + + void copy_from(FallbackTextureView dst) const noexcept; + }; + + static_assert(sizeof(FallbackTextureView) == 16u); + + void texture_write_2d_float_wrapper(void* ptr, uint x, uint y, void* val); + void texture_read_2d_float_wrapper(void* ptr, uint x, uint y, void* out); + void texture_write_2d_uint_wrapper(void* ptr, uint x, uint y, void* val); + void texture_read_2d_uint_wrapper(void* ptr, uint x, uint y, void* out); + + // [[nodiscard]] float32x4_t texture_read_2d_int(int64_t t0, int64_t t1, int64_t c0, int64_t c1) noexcept; + // [[nodiscard]] float32x4_t texture_read_3d_int(int64_t t0, int64_t t1, int64_t c0, int64_t c1) noexcept; + // [[nodiscard]] float32x4_t texture_read_2d_uint(int64_t t0, int64_t t1, int64_t c0, int64_t c1) noexcept; + // [[nodiscard]] float32x4_t texture_read_3d_uint(int64_t t0, int64_t t1, int64_t c0, int64_t c1) noexcept; + // [[nodiscard]] float32x4_t texture_read_2d_float(int64_t t0, int64_t t1, int64_t c0, int64_t c1) noexcept; + // [[nodiscard]] float32x4_t texture_read_3d_float(int64_t t0, int64_t t1, int64_t c0, int64_t c1) noexcept; + // void texture_write_2d_int(int64_t t0, int64_t t1, int64_t c0, int64_t c1, int64_t v0, int64_t v1) noexcept; + // void texture_write_3d_int(int64_t t0, int64_t t1, int64_t c0, int64_t c1, int64_t v0, int64_t v1) noexcept; + // void texture_write_2d_uint(int64_t t0, int64_t t1, int64_t c0, int64_t c1, int64_t v0, int64_t v1) noexcept; + // void texture_write_3d_uint(int64_t t0, int64_t t1, int64_t c0, int64_t c1, int64_t v0, int64_t v1) noexcept; + // void texture_write_2d_float(int64_t t0, int64_t t1, int64_t c0, int64_t c1, int64_t v0, int64_t v1) noexcept; + // void texture_write_3d_float(int64_t t0, int64_t t1, int64_t c0, int64_t c1, int64_t v0, int64_t v1) noexcept; + + //swfly tries to write the accessors again + [[nodiscard]] int4 texture_read_2d_int(const FallbackTextureView* tex, uint x, uint y) noexcept; + + [[nodiscard]] int4 texture_read_3d_int(const FallbackTextureView* tex, uint x, uint y, uint z) noexcept; + + [[nodiscard]] uint4 texture_read_2d_uint(const FallbackTextureView* tex, uint x, uint y) noexcept; + + [[nodiscard]] uint4 texture_read_3d_uint(const FallbackTextureView* tex, uint x, uint y, uint z) noexcept; + + [[nodiscard]] float4 texture_read_2d_float(const FallbackTextureView* tex, uint x, uint y) noexcept; + + [[nodiscard]] float4 texture_read_3d_float(const FallbackTextureView* tex, uint x, uint y, uint z) noexcept; + + // + // + [[nodiscard]] void texture_write_2d_int(const FallbackTextureView* tex, uint x, uint y, int4 val) noexcept; + + [[nodiscard]] void texture_write_3d_int(const FallbackTextureView* tex, uint x, uint y, uint z, int4 val) noexcept; + + [[nodiscard]] void texture_write_2d_uint(const FallbackTextureView* tex, uint x, uint y, uint4 val) noexcept; + + [[nodiscard]] void texture_write_3d_uint(const FallbackTextureView* tex, uint x, uint y, uint z, + uint4 val) noexcept; + + [[nodiscard]] void texture_write_2d_float(const FallbackTextureView* tex, uint x, uint y, float4 val) noexcept; + + [[nodiscard]] void texture_write_3d_float(const FallbackTextureView* tex, uint x, uint y, uint z, + float4 val) noexcept; + + // + [[nodiscard]] float4 bindless_texture_2d_read(const FallbackTexture* tex, uint level, uint x, uint y) noexcept; + + [[nodiscard]] float4 bindless_texture_3d_read(const FallbackTexture* tex, uint level, uint x, uint y, + uint z) noexcept; + + [[nodiscard]] float4 + bindless_texture_2d_sample(const FallbackTexture* tex, uint sampler, float u, float v) noexcept; + + [[nodiscard]] float4 bindless_texture_3d_sample(const FallbackTexture* tex, uint sampler, float u, float v, + float w) noexcept; + + [[nodiscard]] float4 bindless_texture_2d_sample_level(const FallbackTexture* tex, uint sampler, float u, float v, + float lod) noexcept; + + [[nodiscard]] float4 bindless_texture_3d_sample_level(const FallbackTexture* tex, uint sampler, float u, float v, + float w, float lod) noexcept; + + [[nodiscard]] float4 bindless_texture_2d_sample_grad(const FallbackTexture* tex, uint sampler, float u, float v, + int64_t dpdx, int64_t dpdy) noexcept; + + [[nodiscard]] float4 bindless_texture_3d_sample_grad(const FallbackTexture* tex, uint sampler, float u, float v, + float w, int64_t dudxy, int64_t dvdxy, int64_t dwdxy) noexcept; +} // namespace luisa::compute::llvm diff --git a/src/backends/fallback/fallback_texture_bc.cpp b/src/backends/fallback/fallback_texture_bc.cpp new file mode 100644 index 000000000..6bb3c99af --- /dev/null +++ b/src/backends/fallback/fallback_texture_bc.cpp @@ -0,0 +1,2555 @@ +// +// Created by swfly on 2024/11/16. +// + +#include "fallback_texture_bc.h" + +namespace luisa::compute::fallback::bc { + +// Partition, Shape, Pixel (index into 4x4 block) +const uint8_t g_aPartitionTable[3][64][16] = + { + {// 1 Region case has no subsets (all 0) + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + { + // BC6HBlock/BC7 Partition Set for 2 Subsets + {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1},// Shape 0 + {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1},// Shape 1 + {0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1},// Shape 2 + {0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1},// Shape 3 + {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1},// Shape 4 + {0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1},// Shape 5 + {0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1},// Shape 6 + {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1},// Shape 7 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1},// Shape 8 + {0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},// Shape 9 + {0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1},// Shape 10 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1},// Shape 11 + {0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},// Shape 12 + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1},// Shape 13 + {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},// Shape 14 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1},// Shape 15 + {0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1},// Shape 16 + {0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},// Shape 17 + {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0},// Shape 18 + {0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0},// Shape 19 + {0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},// Shape 20 + {0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0},// Shape 21 + {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0},// Shape 22 + {0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1},// Shape 23 + {0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0},// Shape 24 + {0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0},// Shape 25 + {0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0},// Shape 26 + {0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0},// Shape 27 + {0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0},// Shape 28 + {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0},// Shape 29 + {0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0},// Shape 30 + {0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0},// Shape 31 + + // BC7 Partition Set for 2 Subsets (second-half) + {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1},// Shape 32 + {0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1},// Shape 33 + {0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0},// Shape 34 + {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0},// Shape 35 + {0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0},// Shape 36 + {0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0},// Shape 37 + {0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1},// Shape 38 + {0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1},// Shape 39 + {0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0},// Shape 40 + {0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0},// Shape 41 + {0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0},// Shape 42 + {0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0},// Shape 43 + {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0},// Shape 44 + {0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1},// Shape 45 + {0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1},// Shape 46 + {0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0},// Shape 47 + {0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0},// Shape 48 + {0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0},// Shape 49 + {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0},// Shape 50 + {0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0},// Shape 51 + {0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1},// Shape 52 + {0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1},// Shape 53 + {0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0},// Shape 54 + {0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0},// Shape 55 + {0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1},// Shape 56 + {0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1},// Shape 57 + {0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1},// Shape 58 + {0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1},// Shape 59 + {0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1},// Shape 60 + {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0},// Shape 61 + {0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0},// Shape 62 + {0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1} // Shape 63 + }, + + { + // BC7 Partition Set for 3 Subsets + {0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 1, 2, 2, 2, 2},// Shape 0 + {0, 0, 0, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1},// Shape 1 + {0, 0, 0, 0, 2, 0, 0, 1, 2, 2, 1, 1, 2, 2, 1, 1},// Shape 2 + {0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 1, 0, 1, 1, 1},// Shape 3 + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2},// Shape 4 + {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 2, 2},// Shape 5 + {0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1},// Shape 6 + {0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1},// Shape 7 + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2},// Shape 8 + {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2},// Shape 9 + {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2},// Shape 10 + {0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2},// Shape 11 + {0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2},// Shape 12 + {0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2},// Shape 13 + {0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2},// Shape 14 + {0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0, 2, 2, 2, 0},// Shape 15 + {0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2},// Shape 16 + {0, 1, 1, 1, 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0},// Shape 17 + {0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2},// Shape 18 + {0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1},// Shape 19 + {0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2},// Shape 20 + {0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 1, 2, 2, 2, 1},// Shape 21 + {0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2},// Shape 22 + {0, 0, 0, 0, 1, 1, 0, 0, 2, 2, 1, 0, 2, 2, 1, 0},// Shape 23 + {0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1, 0, 0, 0, 0},// Shape 24 + {0, 0, 1, 2, 0, 0, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2},// Shape 25 + {0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1, 0, 1, 1, 0},// Shape 26 + {0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1},// Shape 27 + {0, 0, 2, 2, 1, 1, 0, 2, 1, 1, 0, 2, 0, 0, 2, 2},// Shape 28 + {0, 1, 1, 0, 0, 1, 1, 0, 2, 0, 0, 2, 2, 2, 2, 2},// Shape 29 + {0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1},// Shape 30 + {0, 0, 0, 0, 2, 0, 0, 0, 2, 2, 1, 1, 2, 2, 2, 1},// Shape 31 + {0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 2, 2, 2},// Shape 32 + {0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 2, 0, 0, 1, 1},// Shape 33 + {0, 0, 1, 1, 0, 0, 1, 2, 0, 0, 2, 2, 0, 2, 2, 2},// Shape 34 + {0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0},// Shape 35 + {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0},// Shape 36 + {0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0},// Shape 37 + {0, 1, 2, 0, 2, 0, 1, 2, 1, 2, 0, 1, 0, 1, 2, 0},// Shape 38 + {0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1},// Shape 39 + {0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1},// Shape 40 + {0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2},// Shape 41 + {0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1},// Shape 42 + {0, 0, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2, 1, 1, 2, 2},// Shape 43 + {0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1},// Shape 44 + {0, 2, 2, 0, 1, 2, 2, 1, 0, 2, 2, 0, 1, 2, 2, 1},// Shape 45 + {0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 1},// Shape 46 + {0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1},// Shape 47 + {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2},// Shape 48 + {0, 2, 2, 2, 0, 1, 1, 1, 0, 2, 2, 2, 0, 1, 1, 1},// Shape 49 + {0, 0, 0, 2, 1, 1, 1, 2, 0, 0, 0, 2, 1, 1, 1, 2},// Shape 50 + {0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2},// Shape 51 + {0, 2, 2, 2, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2},// Shape 52 + {0, 0, 0, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2},// Shape 53 + {0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2},// Shape 54 + {0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2},// Shape 55 + {0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2},// Shape 56 + {0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2},// Shape 57 + {0, 0, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2},// Shape 58 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2},// Shape 59 + {0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1},// Shape 60 + {0, 2, 2, 2, 1, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 2},// Shape 61 + {0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},// Shape 62 + {0, 1, 1, 1, 2, 0, 1, 1, 2, 2, 0, 1, 2, 2, 2, 0} // Shape 63 + }}; + +// Partition, Shape, Fixup +const uint8_t g_aFixUp[3][64][3] = + { + {// No fix-ups for 1st subset for BC6HBlock or BC7 + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + + {// BC6HBlock/BC7 Partition Set Fixups for 2 Subsets + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 2, 0}, + {0, 8, 0}, + {0, 2, 0}, + {0, 2, 0}, + {0, 8, 0}, + {0, 8, 0}, + {0, 15, 0}, + {0, 2, 0}, + {0, 8, 0}, + {0, 2, 0}, + {0, 2, 0}, + {0, 8, 0}, + {0, 8, 0}, + {0, 2, 0}, + {0, 2, 0}, + + // BC7 Partition Set Fixups for 2 Subsets (second-half) + {0, 15, 0}, + {0, 15, 0}, + {0, 6, 0}, + {0, 8, 0}, + {0, 2, 0}, + {0, 8, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 2, 0}, + {0, 8, 0}, + {0, 2, 0}, + {0, 2, 0}, + {0, 2, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 6, 0}, + {0, 6, 0}, + {0, 2, 0}, + {0, 6, 0}, + {0, 8, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 2, 0}, + {0, 2, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 2, 0}, + {0, 2, 0}, + {0, 15, 0}}, + + {// BC7 Partition Set Fixups for 3 Subsets + {0, 3, 15}, + {0, 3, 8}, + {0, 15, 8}, + {0, 15, 3}, + {0, 8, 15}, + {0, 3, 15}, + {0, 15, 3}, + {0, 15, 8}, + {0, 8, 15}, + {0, 8, 15}, + {0, 6, 15}, + {0, 6, 15}, + {0, 6, 15}, + {0, 5, 15}, + {0, 3, 15}, + {0, 3, 8}, + {0, 3, 15}, + {0, 3, 8}, + {0, 8, 15}, + {0, 15, 3}, + {0, 3, 15}, + {0, 3, 8}, + {0, 6, 15}, + {0, 10, 8}, + {0, 5, 3}, + {0, 8, 15}, + {0, 8, 6}, + {0, 6, 10}, + {0, 8, 15}, + {0, 5, 15}, + {0, 15, 10}, + {0, 15, 8}, + {0, 8, 15}, + {0, 15, 3}, + {0, 3, 15}, + {0, 5, 10}, + {0, 6, 10}, + {0, 10, 8}, + {0, 8, 9}, + {0, 15, 10}, + {0, 15, 6}, + {0, 3, 15}, + {0, 15, 8}, + {0, 5, 15}, + {0, 15, 3}, + {0, 15, 6}, + {0, 15, 6}, + {0, 15, 8}, + {0, 3, 15}, + {0, 15, 3}, + {0, 5, 15}, + {0, 5, 15}, + {0, 5, 15}, + {0, 8, 15}, + {0, 5, 15}, + {0, 10, 15}, + {0, 5, 15}, + {0, 10, 15}, + {0, 8, 15}, + {0, 13, 15}, + {0, 15, 3}, + {0, 12, 15}, + {0, 3, 15}, + {0, 3, 8}}}; + +const int g_aWeights2[] = {0, 21, 43, 64}; +const int g_aWeights3[] = {0, 9, 18, 27, 37, 46, 55, 64}; +const int g_aWeights4[] = {0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64}; + +const BC7Block::ModeInfo BC7Block::ms_aInfo[BC7Block::c_NumModes] = + { + {2, 4, 6, 0, 0, 3, 0, LDRColorA(4, 4, 4, 0), LDRColorA(5, 5, 5, 0)}, + // Mode 0: Color only, 3 Subsets, RGBP 4441 (unique P-bit), 3-bit indecies, 16 partitions + {1, 6, 2, 0, 0, 3, 0, LDRColorA(6, 6, 6, 0), LDRColorA(7, 7, 7, 0)}, + // Mode 1: Color only, 2 Subsets, RGBP 6661 (shared P-bit), 3-bit indecies, 64 partitions + {2, 6, 0, 0, 0, 2, 0, LDRColorA(5, 5, 5, 0), LDRColorA(5, 5, 5, 0)}, + // Mode 2: Color only, 3 Subsets, RGB 555, 2-bit indecies, 64 partitions + {1, 6, 4, 0, 0, 2, 0, LDRColorA(7, 7, 7, 0), LDRColorA(8, 8, 8, 0)}, + // Mode 3: Color only, 2 Subsets, RGBP 7771 (unique P-bit), 2-bits indecies, 64 partitions + {0, 0, 0, 2, 1, 2, 3, LDRColorA(5, 5, 5, 6), LDRColorA(5, 5, 5, 6)}, + // Mode 4: Color w/ Separate Alpha, 1 Subset, RGB 555, A6, 16x2/16x3-bit indices, 2-bit rotation, 1-bit index selector + {0, 0, 0, 2, 0, 2, 2, LDRColorA(7, 7, 7, 8), LDRColorA(7, 7, 7, 8)}, + // Mode 5: Color w/ Separate Alpha, 1 Subset, RGB 777, A8, 16x2/16x2-bit indices, 2-bit rotation + {0, 0, 2, 0, 0, 4, 0, LDRColorA(7, 7, 7, 7), LDRColorA(8, 8, 8, 8)}, + // Mode 6: Color+Alpha, 1 Subset, RGBAP 77771 (unique P-bit), 16x4-bit indecies + {1, 6, 4, 0, 0, 2, 0, LDRColorA(5, 5, 5, 5), LDRColorA(6, 6, 6, 6)} + // Mode 7: Color+Alpha, 2 Subsets, RGBAP 55551 (unique P-bit), 2-bit indices, 64 partitions +}; +inline HDRColorA::HDRColorA(const LDRColorA &c) noexcept { + r = float(c.r) * (1.0f / 255.0f); + g = float(c.g) * (1.0f / 255.0f); + b = float(c.b) * (1.0f / 255.0f); + a = float(c.a) * (1.0f / 255.0f); +} + +void FillWithErrorColors(HDRColorA *pOut) noexcept { + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) { +#ifdef _DEBUG + // Use Magenta in debug as a highly-visible error color + pOut[i] = HDRColorA(1.0f, 0.0f, 1.0f, 1.0f); +#else + // In production use, default to black + pOut[i] = HDRColorA(0.0f, 0.0f, 0.0f, 1.0f); +#endif + } +} +inline bool IsFixUpOffset(size_t uPartitions, size_t uShape, size_t uOffset) noexcept { + assert(uPartitions < 3 && uShape < 64 && uOffset < 16); + LUISA_ASSUME(uPartitions < 3 && uShape < 64 && uOffset < 16); + for (size_t p = 0; p <= uPartitions; p++) { + if (uOffset == g_aFixUp[uPartitions][uShape][p]) { + return true; + } + } + return false; +} +void BC7Block::Decode(HDRColorA *pOut) const noexcept { + assert(pOut); + + size_t uFirst = 0; + while (uFirst < 128 && !GetBit(uFirst)) {} + const uint8_t uMode = uint8_t(uFirst - 1); + + if (uMode < 8) { + const uint8_t uPartitions = ms_aInfo[uMode].uPartitions; + assert(uPartitions < BC7_MAX_REGIONS); + LUISA_ASSUME(uPartitions < BC7_MAX_REGIONS); + + auto const uNumEndPts = static_cast((unsigned(uPartitions) + 1u) << 1); + const uint8_t uIndexPrec = ms_aInfo[uMode].uIndexPrec; + const uint8_t uIndexPrec2 = ms_aInfo[uMode].uIndexPrec2; + size_t i; + size_t uStartBit = size_t(uMode) + 1; + uint8_t P[6]; + const uint8_t uShape = GetBits(uStartBit, ms_aInfo[uMode].uPartitionBits); + assert(uShape < BC7_MAX_SHAPES); + LUISA_ASSUME(uShape < BC7_MAX_SHAPES); + + const uint8_t uRotation = GetBits(uStartBit, ms_aInfo[uMode].uRotationBits); + assert(uRotation < 4); + + const uint8_t uIndexMode = GetBits(uStartBit, ms_aInfo[uMode].uIndexModeBits); + assert(uIndexMode < 2); + + LDRColorA c[BC7_MAX_REGIONS << 1]; + const LDRColorA RGBAPrec = ms_aInfo[uMode].RGBAPrec; + const LDRColorA RGBAPrecWithP = ms_aInfo[uMode].RGBAPrecWithP; + + assert(uNumEndPts <= (BC7_MAX_REGIONS << 1)); + + // Red channel + for (i = 0; i < uNumEndPts; i++) { + if (uStartBit + RGBAPrec.r > 128) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + + c[i].r = GetBits(uStartBit, RGBAPrec.r); + } + + // Green channel + for (i = 0; i < uNumEndPts; i++) { + if (uStartBit + RGBAPrec.g > 128) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + + c[i].g = GetBits(uStartBit, RGBAPrec.g); + } + + // Blue channel + for (i = 0; i < uNumEndPts; i++) { + if (uStartBit + RGBAPrec.b > 128) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + + c[i].b = GetBits(uStartBit, RGBAPrec.b); + } + + // Alpha channel + for (i = 0; i < uNumEndPts; i++) { + if (uStartBit + RGBAPrec.a > 128) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + + c[i].a = RGBAPrec.a ? GetBits(uStartBit, RGBAPrec.a) : 255u; + } + + // P-bits + assert(ms_aInfo[uMode].uPBits <= 6); + LUISA_ASSUME(ms_aInfo[uMode].uPBits <= 6); + for (i = 0; i < ms_aInfo[uMode].uPBits; i++) { + if (uStartBit > 127) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + + P[i] = GetBit(uStartBit); + } + + if (ms_aInfo[uMode].uPBits) { + for (i = 0; i < uNumEndPts; i++) { + size_t pi = i * ms_aInfo[uMode].uPBits / uNumEndPts; + for (uint8_t ch = 0; ch < BC7_NUM_CHANNELS; ch++) { + if (RGBAPrec[ch] != RGBAPrecWithP[ch]) { + c[i][ch] = static_cast((unsigned(c[i][ch]) << 1) | P[pi]); + } + } + } + } + + for (i = 0; i < uNumEndPts; i++) { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif + c[i] = Unquantize(c[i], RGBAPrecWithP); +#ifdef __GNUC_ +#pragma GCC diagnostic pop +#endif + } + + uint8_t w1[NUM_PIXELS_PER_BLOCK], w2[NUM_PIXELS_PER_BLOCK]; + + // read color indices + for (i = 0; i < NUM_PIXELS_PER_BLOCK; i++) { + const size_t uNumBits = IsFixUpOffset(ms_aInfo[uMode].uPartitions, uShape, i) ? uIndexPrec - 1u : uIndexPrec; + if (uStartBit + uNumBits > 128) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + w1[i] = GetBits(uStartBit, uNumBits); + } + + // read alpha indices + if (uIndexPrec2) { + for (i = 0; i < NUM_PIXELS_PER_BLOCK; i++) { + const size_t uNumBits = i ? uIndexPrec2 : uIndexPrec2 - 1u; + if (uStartBit + uNumBits > 128) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + w2[i] = GetBits(uStartBit, uNumBits); + } + } + + for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) { + const uint8_t uRegion = g_aPartitionTable[uPartitions][uShape][i]; + LDRColorA outPixel; + if (uIndexPrec2 == 0) { + LDRColorA::Interpolate(c[uRegion << 1], c[(uRegion << 1) + 1], w1[i], w1[i], uIndexPrec, uIndexPrec, outPixel); + } else { + if (uIndexMode == 0) { + LDRColorA::Interpolate(c[uRegion << 1], c[(uRegion << 1) + 1], w1[i], w2[i], uIndexPrec, uIndexPrec2, outPixel); + } else { + LDRColorA::Interpolate(c[uRegion << 1], c[(uRegion << 1) + 1], w2[i], w1[i], uIndexPrec2, uIndexPrec, outPixel); + } + } + + switch (uRotation) { + case 1: std::swap(outPixel.r, outPixel.a); break; + case 2: std::swap(outPixel.g, outPixel.a); break; + case 3: std::swap(outPixel.b, outPixel.a); break; + default: break; + } + + pOut[i] = HDRColorA(outPixel); + } + } else { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Reserved mode 8 encountered during decoding\n"); +#endif + // Per the BC7 format spec, we must return transparent black + memset(pOut, 0, sizeof(HDRColorA) * NUM_PIXELS_PER_BLOCK); + } +} + +void ZeroOutPixel(float *pix) { + pix[0] = 0.f; + pix[1] = 0.f; + pix[2] = 0.f; + pix[3] = 0.f; +} + +void BC7Block::Decode(int x, int y, float *out) const noexcept { + assert(out); + unsigned pos = x + y * 4; + + size_t uFirst = 0; + while (uFirst < 128 && !GetBit(uFirst)) {} + const uint8_t uMode = uint8_t(uFirst - 1); + + if (uMode < 8) { + const uint8_t uPartitions = ms_aInfo[uMode].uPartitions; + assert(uPartitions < BC7_MAX_REGIONS); + LUISA_ASSUME(uPartitions < BC7_MAX_REGIONS); + + auto const uNumEndPts = static_cast((unsigned(uPartitions) + 1u) << 1); + const uint8_t uIndexPrec = ms_aInfo[uMode].uIndexPrec; + const uint8_t uIndexPrec2 = ms_aInfo[uMode].uIndexPrec2; + size_t uStartBit = size_t(uMode) + 1; + uint8_t P[6]; + const uint8_t uShape = GetBits(uStartBit, ms_aInfo[uMode].uPartitionBits); + assert(uShape < BC7_MAX_SHAPES); + LUISA_ASSUME(uShape < BC7_MAX_SHAPES); + + const uint8_t uRotation = GetBits(uStartBit, ms_aInfo[uMode].uRotationBits); + assert(uRotation < 4); + + const uint8_t uIndexMode = GetBits(uStartBit, ms_aInfo[uMode].uIndexModeBits); + assert(uIndexMode < 2); + + LDRColorA c[BC7_MAX_REGIONS << 1]; + const LDRColorA RGBAPrec = ms_aInfo[uMode].RGBAPrec; + const LDRColorA RGBAPrecWithP = ms_aInfo[uMode].RGBAPrecWithP; + + assert(uNumEndPts <= (BC7_MAX_REGIONS << 1)); + + // Red channel + for (unsigned i = 0; i < uNumEndPts; i++) { + if (uStartBit + RGBAPrec.r > 128) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + ZeroOutPixel(out); + return; + } + + c[i].r = GetBits(uStartBit, RGBAPrec.r); + } + + // Green channel + for (unsigned i = 0; i < uNumEndPts; i++) { + if (uStartBit + RGBAPrec.g > 128) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + ZeroOutPixel(out); + return; + } + + c[i].g = GetBits(uStartBit, RGBAPrec.g); + } + + // Blue channel + for (unsigned i = 0; i < uNumEndPts; i++) { + if (uStartBit + RGBAPrec.b > 128) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + ZeroOutPixel(out); + return; + } + + c[i].b = GetBits(uStartBit, RGBAPrec.b); + } + + // Alpha channel + for (unsigned i = 0; i < uNumEndPts; i++) { + if (uStartBit + RGBAPrec.a > 128) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + ZeroOutPixel(out); + return; + } + + c[i].a = RGBAPrec.a ? GetBits(uStartBit, RGBAPrec.a) : 255u; + } + + // P-bits + assert(ms_aInfo[uMode].uPBits <= 6); + LUISA_ASSUME(ms_aInfo[uMode].uPBits <= 6); + for (unsigned i = 0; i < ms_aInfo[uMode].uPBits; i++) { + if (uStartBit > 127) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + ZeroOutPixel(out); + return; + } + + P[i] = GetBit(uStartBit); + } + + if (ms_aInfo[uMode].uPBits) { + for (unsigned i = 0; i < uNumEndPts; i++) { + size_t pi = i * ms_aInfo[uMode].uPBits / uNumEndPts; + for (uint8_t ch = 0; ch < BC7_NUM_CHANNELS; ch++) { + if (RGBAPrec[ch] != RGBAPrecWithP[ch]) { + c[i][ch] = static_cast((unsigned(c[i][ch]) << 1) | P[pi]); + } + } + } + } + + for (unsigned i = 0; i < uNumEndPts; i++) { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif + c[i] = Unquantize(c[i], RGBAPrecWithP); +#ifdef __GNUC_ +#pragma GCC diagnostic pop +#endif + } + + uint8_t w1, w2; + + // read color indices + const size_t uNumBits = IsFixUpOffset(ms_aInfo[uMode].uPartitions, uShape, pos) ? uIndexPrec - 1u : uIndexPrec; + if (uStartBit + uNumBits > 128) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + ZeroOutPixel(out); + return; + } + w1 = GetBits(uStartBit, uNumBits); + + // read alpha indices + if (uIndexPrec2) { + const size_t uNumBits = pos ? uIndexPrec2 : uIndexPrec2 - 1u; + if (uStartBit + uNumBits > 128) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + ZeroOutPixel(out); + return; + } + w2 = GetBits(uStartBit, uNumBits); + } + + const uint8_t uRegion = g_aPartitionTable[uPartitions][uShape][pos]; + LDRColorA outPixel; + if (uIndexPrec2 == 0) { + LDRColorA::Interpolate(c[uRegion << 1], c[(uRegion << 1) + 1], w1, w1, uIndexPrec, uIndexPrec, outPixel); + } else { + if (uIndexMode == 0) { + LDRColorA::Interpolate(c[uRegion << 1], c[(uRegion << 1) + 1], w1, w2, uIndexPrec, uIndexPrec2, outPixel); + } else { + LDRColorA::Interpolate(c[uRegion << 1], c[(uRegion << 1) + 1], w2, w1, uIndexPrec2, uIndexPrec, outPixel); + } + } + + switch (uRotation) { + case 1: std::swap(outPixel.r, outPixel.a); break; + case 2: std::swap(outPixel.g, outPixel.a); break; + case 3: std::swap(outPixel.b, outPixel.a); break; + default: break; + } + + out[0] = outPixel.r * (1.0f / 255.0f); + out[1] = outPixel.g * (1.0f / 255.0f); + out[2] = outPixel.b * (1.0f / 255.0f); + out[3] = outPixel.a * (1.0f / 255.0f); + } else { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC7: Reserved mode 8 encountered during decoding\n"); +#endif + ZeroOutPixel(out); + } +} + +using HALF = uint16_t; +class INTColor { +public: + int r, g, b; + int pad; + INTColor() = default; + INTColor(int nr, int ng, int nb) noexcept : r(nr), g(ng), b(nb), pad(0) {} + + INTColor(INTColor const &) = default; + INTColor &operator=(const INTColor &) = default; + + INTColor(INTColor &&) = default; + INTColor &operator=(INTColor &&) = default; + + INTColor &operator+=(const INTColor &c) noexcept { + r += c.r; + g += c.g; + b += c.b; + return *this; + } + + INTColor &operator-=(const INTColor &c) noexcept { + r -= c.r; + g -= c.g; + b -= c.b; + return *this; + } + + INTColor &operator&=(const INTColor &c) noexcept { + r &= c.r; + g &= c.g; + b &= c.b; + return *this; + } + + int &operator[](uint8_t i) noexcept { + assert(i < sizeof(INTColor) / sizeof(int)); + LUISA_ASSUME(i < sizeof(INTColor) / sizeof(int)); + return reinterpret_cast(this)[i]; + } + + INTColor &Clamp(int iMin, int iMax) noexcept { + r = std::min(iMax, std::max(iMin, r)); + g = std::min(iMax, std::max(iMin, g)); + b = std::min(iMax, std::max(iMin, b)); + return *this; + } + + INTColor &SignExtend(const LDRColorA &Prec) noexcept { + r = SIGN_EXTEND(r, int(Prec.r)); + g = SIGN_EXTEND(g, int(Prec.g)); + b = SIGN_EXTEND(b, int(Prec.b)); + return *this; + } + + void ToF16(HALF aF16[3], bool bSigned) const noexcept { + aF16[0] = INT2F16(r, bSigned); + aF16[1] = INT2F16(g, bSigned); + aF16[2] = INT2F16(b, bSigned); + } + +private: + + static HALF INT2F16(int input, bool bSigned) noexcept { + HALF h; + uint16_t out; + if (bSigned) { + int s = 0; + if (input < 0) { + s = F16S_MASK; + input = -input; + } + out = uint16_t(s | input); + } else { + assert(input >= 0 && input <= F16MAX); + out = static_cast(input); + } + + *reinterpret_cast(&h) = out; + return h; + } +}; +struct INTEndPntPair { + INTColor A; + INTColor B; +}; +inline void TransformInverse(INTEndPntPair aEndPts[], const LDRColorA &Prec, bool bSigned) noexcept { + const INTColor WrapMask((1 << Prec.r) - 1, (1 << Prec.g) - 1, (1 << Prec.b) - 1); + aEndPts[0].B += aEndPts[0].A; + aEndPts[0].B &= WrapMask; + aEndPts[1].A += aEndPts[0].A; + aEndPts[1].A &= WrapMask; + aEndPts[1].B += aEndPts[0].A; + aEndPts[1].B &= WrapMask; + if (bSigned) { + aEndPts[0].B.SignExtend(Prec); + aEndPts[1].A.SignExtend(Prec); + aEndPts[1].B.SignExtend(Prec); + } +} +inline float XMConvertHalfToFloat(HALF Value) noexcept { +#if defined(_XM_F16C_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) + __m128i V1 = _mm_cvtsi32_si128(static_cast(Value)); + __m128 V2 = _mm_cvtph_ps(V1); + return _mm_cvtss_f32(V2); +#elif defined(_XM_ARM_NEON_INTRINSICS_) && (defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__) && !defined(_XM_NO_INTRINSICS_) && (!defined(__GNUC__) || (__ARM_FP & 2)) + uint16x4_t vHalf = vdup_n_u16(Value); + float32x4_t vFloat = vcvt_f32_f16(vreinterpret_f16_u16(vHalf)); + return vgetq_lane_f32(vFloat, 0); +#else + auto Mantissa = static_cast(Value & 0x03FF); + + uint32_t Exponent = (Value & 0x7C00); + if (Exponent == 0x7C00)// INF/NAN + { + Exponent = 0x8f; + } else if (Exponent != 0)// The value is normalized + { + Exponent = static_cast((static_cast(Value) >> 10) & 0x1F); + } else if (Mantissa != 0)// The value is denormalized + { + // Normalize the value in the resulting float + Exponent = 1; + + do { + Exponent--; + Mantissa <<= 1; + } while ((Mantissa & 0x0400) == 0); + + Mantissa &= 0x03FF; + } else// The value is zero + { + Exponent = static_cast(-112); + } + + uint32_t Result = + ((static_cast(Value) & 0x8000) << 16)// Sign + | ((Exponent + 112) << 23) // Exponent + | (Mantissa << 13); // Mantissa + + return reinterpret_cast(&Result)[0]; +#endif// !_XM_F16C_INTRINSICS_ +} +void BC6HBlock::Decode(bool bSigned, HDRColorA *pOut) const noexcept { + assert(pOut); + + size_t uStartBit = 0; + uint8_t uMode = GetBits(uStartBit, 2u); + if (uMode != 0x00 && uMode != 0x01) { + uMode = static_cast((unsigned(GetBits(uStartBit, 3)) << 2) | uMode); + } + + assert(uMode < c_NumModeInfo); + LUISA_ASSUME(uMode < c_NumModeInfo); + + if (ms_aModeToInfo[uMode] >= 0) { + assert(static_cast(ms_aModeToInfo[uMode]) < c_NumModes); + LUISA_ASSUME(ms_aModeToInfo[uMode] < c_NumModes); + const ModeDescriptor *desc = ms_aDesc[ms_aModeToInfo[uMode]]; + const ModeInfo &info = ms_aInfo[ms_aModeToInfo[uMode]]; + + INTEndPntPair aEndPts[BC6H_MAX_REGIONS] = {}; + uint32_t uShape = 0; + + // Read header + const size_t uHeaderBits = info.uPartitions > 0 ? 82u : 65u; + while (uStartBit < uHeaderBits) { + const size_t uCurBit = uStartBit; + if (GetBit(uStartBit)) { + switch (desc[uCurBit].m_eField) { + case D: uShape |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RW: aEndPts[0].A.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RX: aEndPts[0].B.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RY: aEndPts[1].A.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RZ: aEndPts[1].B.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GW: aEndPts[0].A.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GX: aEndPts[0].B.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GY: aEndPts[1].A.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GZ: aEndPts[1].B.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BW: aEndPts[0].A.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BX: aEndPts[0].B.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BY: aEndPts[1].A.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BZ: aEndPts[1].B.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + default: { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC6HBlock: Invalid header bits encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + } + } + } + + assert(uShape < 64); + LUISA_ASSUME(uShape < 64); + + // Sign extend necessary end points + if (bSigned) { + aEndPts[0].A.SignExtend(info.RGBAPrec[0][0]); + } + if (bSigned || info.bTransformed) { + assert(info.uPartitions < BC6H_MAX_REGIONS); + LUISA_ASSUME(info.uPartitions < BC6H_MAX_REGIONS); + for (size_t p = 0; p <= info.uPartitions; ++p) { + if (p != 0) { + aEndPts[p].A.SignExtend(info.RGBAPrec[p][0]); + } + aEndPts[p].B.SignExtend(info.RGBAPrec[p][1]); + } + } + + // Inverse transform the end points + if (info.bTransformed) { + TransformInverse(aEndPts, info.RGBAPrec[0][0], bSigned); + } + + // Read indices + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) { + const size_t uNumBits = IsFixUpOffset(info.uPartitions, uShape, i) ? info.uIndexPrec - 1u : info.uIndexPrec; + if (uStartBit + uNumBits > 128) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC6HBlock: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + const uint8_t uIndex = GetBits(uStartBit, uNumBits); + + if (uIndex >= ((info.uPartitions > 0) ? 8 : 16)) { +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugStringA("BC6HBlock: Invalid index encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + + const size_t uRegion = g_aPartitionTable[info.uPartitions][uShape][i]; + assert(uRegion < BC6H_MAX_REGIONS); + LUISA_ASSUME(uRegion < BC6H_MAX_REGIONS); + + // Unquantize endpoints and interpolate + const int r1 = Unquantize(aEndPts[uRegion].A.r, info.RGBAPrec[0][0].r, bSigned); + const int g1 = Unquantize(aEndPts[uRegion].A.g, info.RGBAPrec[0][0].g, bSigned); + const int b1 = Unquantize(aEndPts[uRegion].A.b, info.RGBAPrec[0][0].b, bSigned); + const int r2 = Unquantize(aEndPts[uRegion].B.r, info.RGBAPrec[0][0].r, bSigned); + const int g2 = Unquantize(aEndPts[uRegion].B.g, info.RGBAPrec[0][0].g, bSigned); + const int b2 = Unquantize(aEndPts[uRegion].B.b, info.RGBAPrec[0][0].b, bSigned); + const int *aWeights = info.uPartitions > 0 ? g_aWeights3 : g_aWeights4; + INTColor fc; + fc.r = FinishUnquantize((r1 * (BC67_WEIGHT_MAX - aWeights[uIndex]) + r2 * aWeights[uIndex] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT, bSigned); + fc.g = FinishUnquantize((g1 * (BC67_WEIGHT_MAX - aWeights[uIndex]) + g2 * aWeights[uIndex] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT, bSigned); + fc.b = FinishUnquantize((b1 * (BC67_WEIGHT_MAX - aWeights[uIndex]) + b2 * aWeights[uIndex] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT, bSigned); + + HALF rgb[3]; + fc.ToF16(rgb, bSigned); + + pOut[i].r = XMConvertHalfToFloat(rgb[0]); + pOut[i].g = XMConvertHalfToFloat(rgb[1]); + pOut[i].b = XMConvertHalfToFloat(rgb[2]); + pOut[i].a = 1.0f; + } + } else { +#if defined(_WIN32) && defined(_DEBUG) + const char *warnstr = "BC6HBlock: Invalid mode encountered during decoding\n"; + switch (uMode) { + case 0x13: warnstr = "BC6HBlock: Reserved mode 10011 encountered during decoding\n"; break; + case 0x17: warnstr = "BC6HBlock: Reserved mode 10111 encountered during decoding\n"; break; + case 0x1B: warnstr = "BC6HBlock: Reserved mode 11011 encountered during decoding\n"; break; + case 0x1F: warnstr = "BC6HBlock: Reserved mode 11111 encountered during decoding\n"; break; + default: break; + } + OutputDebugStringA(warnstr); +#endif + // Per the BC6HBlock format spec, we must return opaque black + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) { + pOut[i] = HDRColorA(0.0f, 0.0f, 0.0f, 1.0f); + } + } +} + +int BC6HBlock::Quantize(int iValue, int prec, bool bSigned) noexcept { + assert(prec > 1);// didn't bother to make it work for 1 + int q, s = 0; + if (bSigned) { + assert(iValue >= -F16MAX && iValue <= F16MAX); + if (iValue < 0) { + s = 1; + iValue = -iValue; + } + q = (prec >= 16) ? iValue : (iValue << (prec - 1)) / (F16MAX + 1); + if (s) + q = -q; + assert(q > -(1 << (prec - 1)) && q < (1 << (prec - 1))); + } else { + assert(iValue >= 0 && iValue <= F16MAX); + q = (prec >= 15) ? iValue : (iValue << prec) / (F16MAX + 1); + assert(q >= 0 && q < (1 << prec)); + } + + return q; +} + +int BC6HBlock::Unquantize(int comp, uint8_t uBitsPerComp, bool bSigned) noexcept { + int unq = 0, s = 0; + if (bSigned) { + if (uBitsPerComp >= 16) { + unq = comp; + } else { + if (comp < 0) { + s = 1; + comp = -comp; + } + + if (comp == 0) + unq = 0; + else if (comp >= ((1 << (uBitsPerComp - 1)) - 1)) + unq = 0x7FFF; + else + unq = ((comp << 15) + 0x4000) >> (uBitsPerComp - 1); + + if (s) unq = -unq; + } + } else { + if (uBitsPerComp >= 15) + unq = comp; + else if (comp == 0) + unq = 0; + else if (comp == ((1 << uBitsPerComp) - 1)) + unq = 0xFFFF; + else + unq = ((comp << 16) + 0x8000) >> uBitsPerComp; + } + + return unq; +} + +int BC6HBlock::FinishUnquantize(int comp, bool bSigned) noexcept { + if (bSigned) { + return (comp < 0) ? -(((-comp) * 31) >> 5) : (comp * 31) >> 5;// scale the magnitude by 31/32 + } else { + return (comp * 31) >> 6;// scale the magnitude by 31/64 + } +} +const int BC6HBlock::ms_aModeToInfo[BC6HBlock::c_NumModeInfo] = + { + 0, // Mode 1 - 0x00 + 1, // Mode 2 - 0x01 + 2, // Mode 3 - 0x02 + 10,// Mode 11 - 0x03 + -1,// Invalid - 0x04 + -1,// Invalid - 0x05 + 3, // Mode 4 - 0x06 + 11,// Mode 12 - 0x07 + -1,// Invalid - 0x08 + -1,// Invalid - 0x09 + 4, // Mode 5 - 0x0a + 12,// Mode 13 - 0x0b + -1,// Invalid - 0x0c + -1,// Invalid - 0x0d + 5, // Mode 6 - 0x0e + 13,// Mode 14 - 0x0f + -1,// Invalid - 0x10 + -1,// Invalid - 0x11 + 6, // Mode 7 - 0x12 + -1,// Reserved - 0x13 + -1,// Invalid - 0x14 + -1,// Invalid - 0x15 + 7, // Mode 8 - 0x16 + -1,// Reserved - 0x17 + -1,// Invalid - 0x18 + -1,// Invalid - 0x19 + 8, // Mode 9 - 0x1a + -1,// Reserved - 0x1b + -1,// Invalid - 0x1c + -1,// Invalid - 0x1d + 9, // Mode 10 - 0x1e + -1,// Resreved - 0x1f +}; +const BC6HBlock::ModeDescriptor BC6HBlock::ms_aDesc[BC6HBlock::c_NumModes][82] = + { + { + // Mode 1 (0x00) - 10 5 5 5 + {M, 0}, + {M, 1}, + {GY, 4}, + {BY, 4}, + {BZ, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {GZ, 4}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {BZ, 0}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BZ, 1}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {BZ, 2}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {BZ, 3}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 2 (0x01) - 7 6 6 6 + {M, 0}, + {M, 1}, + {GY, 5}, + {GZ, 4}, + {GZ, 5}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {BZ, 0}, + {BZ, 1}, + {BY, 4}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {BY, 5}, + {BZ, 2}, + {GY, 4}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BZ, 3}, + {BZ, 5}, + {BZ, 4}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {RX, 5}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {GX, 5}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BX, 5}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {RY, 5}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {RZ, 5}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 3 (0x02) - 11 5 4 4 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {RW, 10}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GW, 10}, + {BZ, 0}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BW, 10}, + {BZ, 1}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {BZ, 2}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {BZ, 3}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 4 (0x06) - 11 4 5 4 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RW, 10}, + {GZ, 4}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {GW, 10}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BW, 10}, + {BZ, 1}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {BZ, 0}, + {BZ, 2}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {GY, 4}, + {BZ, 3}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 5 (0x0a) - 11 4 4 5 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RW, 10}, + {BY, 4}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GW, 10}, + {BZ, 0}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BW, 10}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {BZ, 1}, + {BZ, 2}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {BZ, 4}, + {BZ, 3}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 6 (0x0e) - 9 5 5 5 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {BY, 4}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GY, 4}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BZ, 4}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {GZ, 4}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {BZ, 0}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BZ, 1}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {BZ, 2}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {BZ, 3}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 7 (0x12) - 8 6 5 5 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {GZ, 4}, + {BY, 4}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {BZ, 2}, + {GY, 4}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BZ, 3}, + {BZ, 4}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {RX, 5}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {BZ, 0}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BZ, 1}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {RY, 5}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {RZ, 5}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 8 (0x16) - 8 5 6 5 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {BZ, 0}, + {BY, 4}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GY, 5}, + {GY, 4}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {GZ, 5}, + {BZ, 4}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {GZ, 4}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {GX, 5}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BZ, 1}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {BZ, 2}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {BZ, 3}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 9 (0x1a) - 8 5 5 6 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {BZ, 1}, + {BY, 4}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {BY, 5}, + {GY, 4}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BZ, 5}, + {BZ, 4}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {GZ, 4}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {BZ, 0}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BX, 5}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {BZ, 2}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {BZ, 3}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 10 (0x1e) - 6 6 6 6 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {GZ, 4}, + {BZ, 0}, + {BZ, 1}, + {BY, 4}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GY, 5}, + {BY, 5}, + {BZ, 2}, + {GY, 4}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {GZ, 5}, + {BZ, 3}, + {BZ, 5}, + {BZ, 4}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {RX, 5}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {GX, 5}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BX, 5}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {RY, 5}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {RZ, 5}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 11 (0x03) - 10 10 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {RX, 5}, + {RX, 6}, + {RX, 7}, + {RX, 8}, + {RX, 9}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {GX, 5}, + {GX, 6}, + {GX, 7}, + {GX, 8}, + {GX, 9}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BX, 5}, + {BX, 6}, + {BX, 7}, + {BX, 8}, + {BX, 9}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + }, + + { + // Mode 12 (0x07) - 11 9 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {RX, 5}, + {RX, 6}, + {RX, 7}, + {RX, 8}, + {RW, 10}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {GX, 5}, + {GX, 6}, + {GX, 7}, + {GX, 8}, + {GW, 10}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BX, 5}, + {BX, 6}, + {BX, 7}, + {BX, 8}, + {BW, 10}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + }, + + { + // Mode 13 (0x0b) - 12 8 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {RX, 5}, + {RX, 6}, + {RX, 7}, + {RW, 11}, + {RW, 10}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {GX, 5}, + {GX, 6}, + {GX, 7}, + {GW, 11}, + {GW, 10}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BX, 5}, + {BX, 6}, + {BX, 7}, + {BW, 11}, + {BW, 10}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + }, + + { + // Mode 14 (0x0f) - 16 4 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RW, 15}, + {RW, 14}, + {RW, 13}, + {RW, 12}, + {RW, 11}, + {RW, 10}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GW, 15}, + {GW, 14}, + {GW, 13}, + {GW, 12}, + {GW, 11}, + {GW, 10}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BW, 15}, + {BW, 14}, + {BW, 13}, + {BW, 12}, + {BW, 11}, + {BW, 10}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + }, +}; + +// Mode, Partitions, Transformed, IndexPrec, RGBAPrec +const BC6HBlock::ModeInfo BC6HBlock::ms_aInfo[BC6HBlock::c_NumModes] = + { + {0x00, 1, true, 3, {{LDRColorA(10, 10, 10, 0), LDRColorA(5, 5, 5, 0)}, {LDRColorA(5, 5, 5, 0), LDRColorA(5, 5, 5, 0)}}}, // Mode 1 + {0x01, 1, true, 3, {{LDRColorA(7, 7, 7, 0), LDRColorA(6, 6, 6, 0)}, {LDRColorA(6, 6, 6, 0), LDRColorA(6, 6, 6, 0)}}}, // Mode 2 + {0x02, 1, true, 3, {{LDRColorA(11, 11, 11, 0), LDRColorA(5, 4, 4, 0)}, {LDRColorA(5, 4, 4, 0), LDRColorA(5, 4, 4, 0)}}}, // Mode 3 + {0x06, 1, true, 3, {{LDRColorA(11, 11, 11, 0), LDRColorA(4, 5, 4, 0)}, {LDRColorA(4, 5, 4, 0), LDRColorA(4, 5, 4, 0)}}}, // Mode 4 + {0x0a, 1, true, 3, {{LDRColorA(11, 11, 11, 0), LDRColorA(4, 4, 5, 0)}, {LDRColorA(4, 4, 5, 0), LDRColorA(4, 4, 5, 0)}}}, // Mode 5 + {0x0e, 1, true, 3, {{LDRColorA(9, 9, 9, 0), LDRColorA(5, 5, 5, 0)}, {LDRColorA(5, 5, 5, 0), LDRColorA(5, 5, 5, 0)}}}, // Mode 6 + {0x12, 1, true, 3, {{LDRColorA(8, 8, 8, 0), LDRColorA(6, 5, 5, 0)}, {LDRColorA(6, 5, 5, 0), LDRColorA(6, 5, 5, 0)}}}, // Mode 7 + {0x16, 1, true, 3, {{LDRColorA(8, 8, 8, 0), LDRColorA(5, 6, 5, 0)}, {LDRColorA(5, 6, 5, 0), LDRColorA(5, 6, 5, 0)}}}, // Mode 8 + {0x1a, 1, true, 3, {{LDRColorA(8, 8, 8, 0), LDRColorA(5, 5, 6, 0)}, {LDRColorA(5, 5, 6, 0), LDRColorA(5, 5, 6, 0)}}}, // Mode 9 + {0x1e, 1, false, 3, {{LDRColorA(6, 6, 6, 0), LDRColorA(6, 6, 6, 0)}, {LDRColorA(6, 6, 6, 0), LDRColorA(6, 6, 6, 0)}}}, // Mode 10 + {0x03, 0, false, 4, {{LDRColorA(10, 10, 10, 0), LDRColorA(10, 10, 10, 0)}, {LDRColorA(0, 0, 0, 0), LDRColorA(0, 0, 0, 0)}}},// Mode 11 + {0x07, 0, true, 4, {{LDRColorA(11, 11, 11, 0), LDRColorA(9, 9, 9, 0)}, {LDRColorA(0, 0, 0, 0), LDRColorA(0, 0, 0, 0)}}}, // Mode 12 + {0x0b, 0, true, 4, {{LDRColorA(12, 12, 12, 0), LDRColorA(8, 8, 8, 0)}, {LDRColorA(0, 0, 0, 0), LDRColorA(0, 0, 0, 0)}}}, // Mode 13 + {0x0f, 0, true, 4, {{LDRColorA(16, 16, 16, 0), LDRColorA(4, 4, 4, 0)}, {LDRColorA(0, 0, 0, 0), LDRColorA(0, 0, 0, 0)}}}, // Mode 14 +}; +void BC6HBlock::Decode(bool bSigned, int x, int y, float *out) const noexcept { + LUISA_ASSUME(out); + const int pos = x + y * 4; + size_t uStartBit = 0; + uint8_t uMode = GetBits(uStartBit, 2u); + if (uMode != 0x00 && uMode != 0x01) { + uMode = static_cast((unsigned(GetBits(uStartBit, 3)) << 2) | uMode); + } + + LUISA_ASSUME(uMode < c_NumModeInfo); + if (ms_aModeToInfo[uMode] >= 0) { + LUISA_ASSUME(static_cast(ms_aModeToInfo[uMode]) < c_NumModes); + const ModeDescriptor *desc = ms_aDesc[ms_aModeToInfo[uMode]]; + const ModeInfo &info = ms_aInfo[ms_aModeToInfo[uMode]]; + + INTEndPntPair aEndPts[BC6H_MAX_REGIONS] = {}; + uint32_t uShape = 0; + + // Read header + const size_t uHeaderBits = info.uPartitions > 0 ? 82u : 65u; + while (uStartBit < uHeaderBits) { + const size_t uCurBit = uStartBit; + if (GetBit(uStartBit)) { + switch (desc[uCurBit].m_eField) { + case D: uShape |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RW: aEndPts[0].A.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RX: aEndPts[0].B.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RY: aEndPts[1].A.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RZ: aEndPts[1].B.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GW: aEndPts[0].A.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GX: aEndPts[0].B.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GY: aEndPts[1].A.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GZ: aEndPts[1].B.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BW: aEndPts[0].A.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BX: aEndPts[0].B.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BY: aEndPts[1].A.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BZ: aEndPts[1].B.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + default: { + ZeroOutPixel(out); + return; + } + } + } + } + + LUISA_ASSUME(uShape < 64); + + // Sign extend necessary end points + if (bSigned) { + aEndPts[0].A.SignExtend(info.RGBAPrec[0][0]); + } + if (bSigned || info.bTransformed) { + LUISA_ASSUME(info.uPartitions < BC6H_MAX_REGIONS); + for (size_t p = 0; p <= info.uPartitions; ++p) { + if (p != 0) { + aEndPts[p].A.SignExtend(info.RGBAPrec[p][0]); + } + aEndPts[p].B.SignExtend(info.RGBAPrec[p][1]); + } + } + + // Inverse transform the end points + if (info.bTransformed) { + TransformInverse(aEndPts, info.RGBAPrec[0][0], bSigned); + } + + // Read indices + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) { + const size_t uNumBits = IsFixUpOffset(info.uPartitions, uShape, i) ? info.uIndexPrec - 1u : info.uIndexPrec; + if (uStartBit + uNumBits > 128) { + ZeroOutPixel(out); + return; + } + const uint8_t uIndex = GetBits(uStartBit, uNumBits); + + if (uIndex >= ((info.uPartitions > 0) ? 8 : 16)) { + ZeroOutPixel(out); + return; + } + if (i == pos) { + const size_t uRegion = g_aPartitionTable[info.uPartitions][uShape][i]; + LUISA_ASSUME(uRegion < BC6H_MAX_REGIONS); + // Unquantize endpoints and interpolate + const int r1 = Unquantize(aEndPts[uRegion].A.r, info.RGBAPrec[0][0].r, bSigned); + const int g1 = Unquantize(aEndPts[uRegion].A.g, info.RGBAPrec[0][0].g, bSigned); + const int b1 = Unquantize(aEndPts[uRegion].A.b, info.RGBAPrec[0][0].b, bSigned); + const int r2 = Unquantize(aEndPts[uRegion].B.r, info.RGBAPrec[0][0].r, bSigned); + const int g2 = Unquantize(aEndPts[uRegion].B.g, info.RGBAPrec[0][0].g, bSigned); + const int b2 = Unquantize(aEndPts[uRegion].B.b, info.RGBAPrec[0][0].b, bSigned); + const int *aWeights = info.uPartitions > 0 ? g_aWeights3 : g_aWeights4; + INTColor fc; + fc.r = FinishUnquantize((r1 * (BC67_WEIGHT_MAX - aWeights[uIndex]) + r2 * aWeights[uIndex] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT, bSigned); + fc.g = FinishUnquantize((g1 * (BC67_WEIGHT_MAX - aWeights[uIndex]) + g2 * aWeights[uIndex] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT, bSigned); + fc.b = FinishUnquantize((b1 * (BC67_WEIGHT_MAX - aWeights[uIndex]) + b2 * aWeights[uIndex] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT, bSigned); + + HALF rgb[3]; + fc.ToF16(rgb, bSigned); + + out[0] = XMConvertHalfToFloat(rgb[0]); + out[1] = XMConvertHalfToFloat(rgb[1]); + out[2] = XMConvertHalfToFloat(rgb[2]); + out[3] = 1.0f; + break; + } + } + } else { + ZeroOutPixel(out); + } +} + +}// namespace luisa::compute::fallback::bc diff --git a/src/backends/fallback/fallback_texture_bc.h b/src/backends/fallback/fallback_texture_bc.h new file mode 100644 index 000000000..b59e01d39 --- /dev/null +++ b/src/backends/fallback/fallback_texture_bc.h @@ -0,0 +1,429 @@ +// +// Created by swfly on 2024/11/16. +// + +#pragma once + +#include +#include + +namespace luisa::compute::fallback::bc { +extern const int g_aWeights2[]; +extern const int g_aWeights3[]; +extern const int g_aWeights4[]; + +//------------------------------------------------------------------------------------- +// Constants +//------------------------------------------------------------------------------------- +constexpr uint16_t BC6H_MAX_REGIONS = 2; +constexpr uint16_t BC6H_MAX_INDICES = 16; +constexpr uint16_t BC7_MAX_REGIONS = 3; +constexpr uint16_t BC7_MAX_INDICES = 16; +constexpr uint16_t NUM_PIXELS_PER_BLOCK = 16; + +constexpr uint16_t F16S_MASK = 0x8000; // f16 sign mask +constexpr uint16_t F16EM_MASK = 0x7fff;// f16 exp & mantissa mask +constexpr uint16_t F16MAX = 0x7bff; // MAXFLT bit pattern for XMHALF + +constexpr size_t BC6H_NUM_CHANNELS = 3; +constexpr size_t BC6H_MAX_SHAPES = 32; + +constexpr size_t BC7_NUM_CHANNELS = 4; +constexpr size_t BC7_MAX_SHAPES = 64; + +constexpr int32_t BC67_WEIGHT_MAX = 64; +constexpr uint32_t BC67_WEIGHT_SHIFT = 6; +constexpr int32_t BC67_WEIGHT_ROUND = 32; + +constexpr float fEpsilon = (0.25f / 64.0f) * (0.25f / 64.0f); +constexpr float pC3[] = {2.0f / 2.0f, 1.0f / 2.0f, 0.0f / 2.0f}; +constexpr float pD3[] = {0.0f / 2.0f, 1.0f / 2.0f, 2.0f / 2.0f}; +constexpr float pC4[] = {3.0f / 3.0f, 2.0f / 3.0f, 1.0f / 3.0f, 0.0f / 3.0f}; +constexpr float pD4[] = {0.0f / 3.0f, 1.0f / 3.0f, 2.0f / 3.0f, 3.0f / 3.0f}; + +#define SIGN_EXTEND(x, nb) ((((x) & (1 << ((nb) - 1))) ? ((~0) ^ ((1 << (nb)) - 1)) : 0) | (x)) +class HDRColorA; +class LDRColorA; + +template +class CBits { +public: + uint8_t GetBit(size_t &uStartBit) const noexcept { + LUISA_ASSUME(uStartBit < 128); + const size_t uIndex = uStartBit >> 3; + auto const ret = static_cast((m_uBits[uIndex] >> (uStartBit - (uIndex << 3))) & 0x01); + uStartBit++; + return ret; + } + + uint8_t GetBits(size_t &uStartBit, size_t uNumBits) const noexcept { + if (uNumBits == 0) return 0; + LUISA_ASSUME(uStartBit + uNumBits <= 128 && uNumBits <= 8); + uint8_t ret; + const size_t uIndex = uStartBit >> 3; + const size_t uBase = uStartBit - (uIndex << 3); + if (uBase + uNumBits > 8) { + const size_t uFirstIndexBits = 8 - uBase; + const size_t uNextIndexBits = uNumBits - uFirstIndexBits; + ret = static_cast((unsigned(m_uBits[uIndex]) >> uBase) | ((unsigned(m_uBits[uIndex + 1]) & ((1u << uNextIndexBits) - 1)) << uFirstIndexBits)); + } else { + ret = static_cast((m_uBits[uIndex] >> uBase) & ((1 << uNumBits) - 1)); + } + LUISA_ASSUME(ret < (1 << uNumBits)); + uStartBit += uNumBits; + return ret; + } + + void SetBit(size_t &uStartBit, uint8_t uValue) noexcept { + LUISA_ASSUME(uStartBit < 128 && uValue < 2); + size_t uIndex = uStartBit >> 3; + const size_t uBase = uStartBit - (uIndex << 3); + m_uBits[uIndex] &= ~(1 << uBase); + m_uBits[uIndex] |= uValue << uBase; + uStartBit++; + } + + void SetBits(size_t &uStartBit, size_t uNumBits, uint8_t uValue) noexcept { + if (uNumBits == 0) + return; + LUISA_ASSUME(uStartBit + uNumBits <= 128 && uNumBits <= 8); + LUISA_ASSUME(uValue < (1 << uNumBits)); + size_t uIndex = uStartBit >> 3; + const size_t uBase = uStartBit - (uIndex << 3); + if (uBase + uNumBits > 8) { + const size_t uFirstIndexBits = 8 - uBase; + const size_t uNextIndexBits = uNumBits - uFirstIndexBits; + m_uBits[uIndex] &= ~(((1 << uFirstIndexBits) - 1) << uBase); + m_uBits[uIndex] |= uValue << uBase; + m_uBits[uIndex + 1] &= ~((1 << uNextIndexBits) - 1); + m_uBits[uIndex + 1] |= uValue >> uFirstIndexBits; + } else { + m_uBits[uIndex] &= ~(((1 << uNumBits) - 1) << uBase); + m_uBits[uIndex] |= uValue << uBase; + } + uStartBit += uNumBits; + } + +private: + uint8_t m_uBits[SizeInBytes]; +}; +class HDRColorA { +public: + float r, g, b, a; + +public: + HDRColorA() = default; + HDRColorA(float _r, float _g, float _b, float _a) noexcept : r(_r), g(_g), b(_b), a(_a) {} + + HDRColorA(HDRColorA const &) = default; + HDRColorA &operator=(const HDRColorA &) = default; + + HDRColorA(HDRColorA &&) = default; + HDRColorA &operator=(HDRColorA &&) = default; + + // binary operators + HDRColorA operator+(const HDRColorA &c) const noexcept { + return HDRColorA(r + c.r, g + c.g, b + c.b, a + c.a); + } + + HDRColorA operator-(const HDRColorA &c) const noexcept { + return HDRColorA(r - c.r, g - c.g, b - c.b, a - c.a); + } + + HDRColorA operator*(float f) const noexcept { + return HDRColorA(r * f, g * f, b * f, a * f); + } + + HDRColorA operator/(float f) const noexcept { + const float fInv = 1.0f / f; + return HDRColorA(r * fInv, g * fInv, b * fInv, a * fInv); + } + + float operator*(const HDRColorA &c) const noexcept { + return r * c.r + g * c.g + b * c.b + a * c.a; + } + + // assignment operators + HDRColorA &operator+=(const HDRColorA &c) noexcept { + r += c.r; + g += c.g; + b += c.b; + a += c.a; + return *this; + } + + HDRColorA &operator-=(const HDRColorA &c) noexcept { + r -= c.r; + g -= c.g; + b -= c.b; + a -= c.a; + return *this; + } + + HDRColorA &operator*=(float f) noexcept { + r *= f; + g *= f; + b *= f; + a *= f; + return *this; + } + + HDRColorA &operator/=(float f) noexcept { + const float fInv = 1.0f / f; + r *= fInv; + g *= fInv; + b *= fInv; + a *= fInv; + return *this; + } + + HDRColorA &Clamp(float fMin, float fMax) noexcept { + r = std::min(fMax, std::max(fMin, r)); + g = std::min(fMax, std::max(fMin, g)); + b = std::min(fMax, std::max(fMin, b)); + a = std::min(fMax, std::max(fMin, a)); + return *this; + } + + HDRColorA(const LDRColorA &c) noexcept; + HDRColorA &operator=(const LDRColorA &c) noexcept; + LDRColorA ToLDRColorA() const noexcept; +}; + +inline HDRColorA *HDRColorALerp(HDRColorA *pOut, const HDRColorA *pC1, const HDRColorA *pC2, float s) noexcept { + pOut->r = pC1->r + s * (pC2->r - pC1->r); + pOut->g = pC1->g + s * (pC2->g - pC1->g); + pOut->b = pC1->b + s * (pC2->b - pC1->b); + pOut->a = pC1->a + s * (pC2->a - pC1->a); + return pOut; +} + +#pragma pack(push, 1) +// BC1/DXT1 compression (4 bits per texel) +struct D3DX_BC1 { + uint16_t rgb[2];// 565 colors + uint32_t bitmap;// 2bpp rgb bitmap +}; + +// BC2/DXT2/3 compression (8 bits per texel) +struct D3DX_BC2 { + uint32_t bitmap[2];// 4bpp alpha bitmap + D3DX_BC1 bc1; // BC1 rgb data +}; + +// BC3/DXT4/5 compression (8 bits per texel) +struct D3DX_BC3 { + uint8_t alpha[2]; // alpha values + uint8_t bitmap[6];// 3bpp alpha bitmap + D3DX_BC1 bc1; // BC1 rgb data +}; +class LDRColorA { +public: + uint8_t r, g, b, a; + + LDRColorA() = default; + LDRColorA(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a) noexcept : r(_r), g(_g), b(_b), a(_a) {} + + LDRColorA(LDRColorA const &) = default; + LDRColorA &operator=(const LDRColorA &) = default; + + LDRColorA(LDRColorA &&) = default; + LDRColorA &operator=(LDRColorA &&) = default; + + const uint8_t &operator[](size_t uElement) const noexcept { + switch (uElement) { + case 0: return r; + case 1: return g; + case 2: return b; + case 3: return a; + default: LUISA_ASSUME(false); return r; + } + } + + uint8_t &operator[](size_t uElement) noexcept { + switch (uElement) { + case 0: return r; + case 1: return g; + case 2: return b; + case 3: return a; + default: LUISA_ASSUME(false); return r; + } + } + + LDRColorA operator=(const HDRColorA &c) noexcept { + LDRColorA ret; + HDRColorA tmp(c); + tmp = tmp.Clamp(0.0f, 1.0f) * 255.0f; + ret.r = uint8_t(tmp.r + 0.001f); + ret.g = uint8_t(tmp.g + 0.001f); + ret.b = uint8_t(tmp.b + 0.001f); + ret.a = uint8_t(tmp.a + 0.001f); + return ret; + } + + static void InterpolateRGB(const LDRColorA &c0, const LDRColorA &c1, size_t wc, size_t wcprec, LDRColorA &out) noexcept { + const int *aWeights = nullptr; + switch (wcprec) { + case 2: + aWeights = g_aWeights2; + LUISA_ASSUME(wc < 4); + break; + case 3: + aWeights = g_aWeights3; + LUISA_ASSUME(wc < 8); + break; + case 4: + aWeights = g_aWeights4; + LUISA_ASSUME(wc < 16); + break; + default: + LUISA_ASSUME(false); + out.r = out.g = out.b = 0; + return; + } + out.r = uint8_t((uint32_t(c0.r) * uint32_t(BC67_WEIGHT_MAX - aWeights[wc]) + uint32_t(c1.r) * uint32_t(aWeights[wc]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT); + out.g = uint8_t((uint32_t(c0.g) * uint32_t(BC67_WEIGHT_MAX - aWeights[wc]) + uint32_t(c1.g) * uint32_t(aWeights[wc]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT); + out.b = uint8_t((uint32_t(c0.b) * uint32_t(BC67_WEIGHT_MAX - aWeights[wc]) + uint32_t(c1.b) * uint32_t(aWeights[wc]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT); + } + + static void InterpolateA(const LDRColorA &c0, const LDRColorA &c1, size_t wa, size_t waprec, LDRColorA &out) noexcept { + const int *aWeights = nullptr; + switch (waprec) { + case 2: + aWeights = g_aWeights2; + LUISA_ASSUME(wa < 4); + break; + case 3: + aWeights = g_aWeights3; + LUISA_ASSUME(wa < 8); + break; + case 4: + aWeights = g_aWeights4; + LUISA_ASSUME(wa < 16); + break; + default: + LUISA_ASSUME(false); + out.a = 0; + return; + } + out.a = uint8_t((uint32_t(c0.a) * uint32_t(BC67_WEIGHT_MAX - aWeights[wa]) + uint32_t(c1.a) * uint32_t(aWeights[wa]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT); + } + + static void Interpolate(const LDRColorA &c0, const LDRColorA &c1, size_t wc, size_t wa, size_t wcprec, size_t waprec, LDRColorA &out) noexcept { + InterpolateRGB(c0, c1, wc, wcprec, out); + InterpolateA(c0, c1, wa, waprec, out); + } +}; +struct LDREndPntPair { + LDRColorA A; + LDRColorA B; +}; +class BC6HBlock : private CBits<16> { +public: + void Decode(bool bSigned, HDRColorA *pOut) const noexcept; + void Decode(bool bSigned, int x, int y, float *out) const noexcept; +private: +#pragma warning(push) +#pragma warning(disable : 4480) + enum EField : uint8_t { + NA,// N/A + M, // Mode + D, // Shape + RW, + RX, + RY, + RZ, + GW, + GX, + GY, + GZ, + BW, + BX, + BY, + BZ, + }; +#pragma warning(pop) + + struct ModeDescriptor { + EField m_eField; + uint8_t m_uBit; + }; + + struct ModeInfo { + uint8_t uMode; + uint8_t uPartitions; + bool bTransformed; + uint8_t uIndexPrec; + LDRColorA RGBAPrec[BC6H_MAX_REGIONS][2]; + }; + + static int Quantize(int iValue, int prec, bool bSigned) noexcept; + static int Unquantize(int comp, uint8_t uBitsPerComp, bool bSigned) noexcept; + static int FinishUnquantize(int comp, bool bSigned) noexcept; + +private: + static constexpr uint8_t c_NumModes = 14; + static constexpr uint8_t c_NumModeInfo = 32; + + static const ModeDescriptor ms_aDesc[c_NumModes][82]; + static const ModeInfo ms_aInfo[c_NumModes]; + static const int ms_aModeToInfo[c_NumModeInfo]; +}; + +class BC7Block : private CBits<16> { +public: + void Decode(HDRColorA *pOut) const noexcept; + void Decode(int x, int y, float *out) const noexcept; +private: + struct ModeInfo { + uint8_t uPartitions; + uint8_t uPartitionBits; + uint8_t uPBits; + uint8_t uRotationBits; + uint8_t uIndexModeBits; + uint8_t uIndexPrec; + uint8_t uIndexPrec2; + LDRColorA RGBAPrec; + LDRColorA RGBAPrecWithP; + }; + + static uint8_t Quantize(uint8_t comp, uint8_t uPrec) noexcept { + LUISA_ASSUME(0 < uPrec && uPrec <= 8); + const uint8_t rnd = std::min(255u, static_cast(unsigned(comp) + (1u << (7 - uPrec)))); + return uint8_t(rnd >> (8u - uPrec)); + } + + static LDRColorA Quantize(const LDRColorA &c, const LDRColorA &RGBAPrec) noexcept { + LDRColorA q; + q.r = Quantize(c.r, RGBAPrec.r); + q.g = Quantize(c.g, RGBAPrec.g); + q.b = Quantize(c.b, RGBAPrec.b); + if (RGBAPrec.a) + q.a = Quantize(c.a, RGBAPrec.a); + else + q.a = 255; + return q; + } + + static uint8_t Unquantize(uint8_t comp, size_t uPrec) noexcept { + LUISA_ASSUME(0 < uPrec && uPrec <= 8); + comp = static_cast(unsigned(comp) << (8 - uPrec)); + return uint8_t(comp | (comp >> uPrec)); + } + + static LDRColorA Unquantize(const LDRColorA &c, const LDRColorA &RGBAPrec) noexcept { + LDRColorA q; + q.r = Unquantize(c.r, RGBAPrec.r); + q.g = Unquantize(c.g, RGBAPrec.g); + q.b = Unquantize(c.b, RGBAPrec.b); + q.a = RGBAPrec.a > 0 ? Unquantize(c.a, RGBAPrec.a) : 255u; + return q; + } + +private: + static constexpr uint8_t c_NumModes = 8; + + static const ModeInfo ms_aInfo[c_NumModes]; +}; + +}// namespace luisa::compute::fallback::bc diff --git a/src/backends/fallback/fallback_texture_sampling.cpp b/src/backends/fallback/fallback_texture_sampling.cpp new file mode 100644 index 000000000..ebc3152b0 --- /dev/null +++ b/src/backends/fallback/fallback_texture_sampling.cpp @@ -0,0 +1,404 @@ +// +// Created by swfly on 2024/11/16. +// + +#include "fallback_texture.h" +#include "fallback_texture_bc.h" +#include "llvm_abi.h" + +//swfly tries to write more about sampling bc textures +namespace luisa::compute::fallback +{ + void texture_write_2d_float_wrapper(void* ptr, uint x, uint y, void* val) + { + auto b = static_cast(val); + auto view = reinterpret_cast(ptr); + texture_write_2d_float(reinterpret_cast(ptr), x, y, *(float4 *) val); + } + + void texture_read_2d_float_wrapper(void* ptr, uint x, uint y, void* out) + { + *(float4 *) out = texture_read_2d_float(reinterpret_cast(ptr), x, y); + } + + void texture_write_2d_uint_wrapper(void* ptr, uint x, uint y, void* val) + { + auto b = static_cast(val); + auto view = reinterpret_cast(ptr); + texture_write_2d_uint(reinterpret_cast(ptr), x, y, *(uint4 *) val); + } + + void texture_read_2d_uint_wrapper(void* ptr, uint x, uint y, void* out) + { + *(uint4 *) out = texture_read_2d_uint(reinterpret_cast(ptr), x, y); + } + + void luisa_bc7_read(const FallbackTextureView* tex, uint x, uint y, float4& out) noexcept + { + auto block_pos = make_uint2(x / 4, y / 4); + auto block_per_row = tex->size2d().x / 4; + const bc::BC7Block* bc_block = reinterpret_cast(tex->data()) + ( + block_pos.x + block_pos.y * block_per_row); + bc_block->Decode(x % 4, y % 4, reinterpret_cast(&out)); + } + + void luisa_bc6h_read(const FallbackTextureView* tex, int x, int y, float4& out) noexcept + { + auto block_pos = make_uint2(x / 4, y / 4); + auto block_per_row = tex->size2d().x / 4; + const bc::BC6HBlock* bc_block = reinterpret_cast(tex->data()) + ( + block_pos.x + block_pos.y * block_per_row); + bc_block->Decode(false, x % 4, y % 4, reinterpret_cast(&out)); + } + + int4 fallback::texture_read_2d_int(const FallbackTextureView* tex, uint x, uint y) noexcept + { + switch (tex->storage()) + { + case PixelStorage::BC7: + { + float4 out; + luisa_bc7_read(tex, x, y, out); + return make_int4(out.x * 255.f, out.y * 255.f, out.z * 255.f, out.w * 255.f); + } + case PixelStorage::BC6: + { + float4 out; + luisa_bc6h_read(tex, x, y, out); + return make_int4(out.x * 255.f, out.y * 255.f, out.z * 255.f, out.w * 255.f); + } + default: + return tex->read2d(make_uint2(x, y)); + } + } + + int4 fallback::texture_read_3d_int(const FallbackTextureView* tex, uint x, uint y, uint z) noexcept + { + switch (tex->storage()) + { + case PixelStorage::BC7: + { + LUISA_ERROR("Block compression doesn't work for 3D texture"); + return make_int4(0); + } + case PixelStorage::BC6: + { + LUISA_ERROR("Block compression doesn't work for 3D texture"); + return make_int4(0); + } + default: + return tex->read2d(make_uint2(x, y)); + } + } + + uint4 fallback::texture_read_2d_uint(const FallbackTextureView* tex, uint x, uint y) noexcept + { + switch (tex->storage()) + { + case PixelStorage::BC7: + { + float4 out; + luisa_bc7_read(tex, x, y, out); + return make_uint4(out.x * 255.f, out.y * 255.f, out.z * 255.f, out.w * 255.f); + } + case PixelStorage::BC6: + { + float4 out; + luisa_bc6h_read(tex, x, y, out); + return make_uint4(out.x * 255.f, out.y * 255.f, out.z * 255.f, out.w * 255.f); + } + default: + return tex->read2d(make_uint2(x, y)); + } + } + + uint4 fallback::texture_read_3d_uint(const FallbackTextureView* tex, uint x, uint y, uint z) noexcept + { + switch (tex->storage()) + { + case PixelStorage::BC7: + { + LUISA_ERROR("Block compression doesn't work for 3D texture"); + return make_uint4(0); + } + case PixelStorage::BC6: + { + LUISA_ERROR("Block compression doesn't work for 3D texture"); + return make_uint4(0); + } + default: + return tex->read3d(make_uint3(x, y, z)); + } + } + + float4 fallback::texture_read_2d_float(const FallbackTextureView* tex, uint x, uint y) noexcept + { + switch (tex->storage()) + { + case PixelStorage::BC7: + { + float4 out; + luisa_bc7_read(tex, x, y, out); + return out; + } + case PixelStorage::BC6: + { + float4 out; + luisa_bc6h_read(tex, x, y, out); + return out; + } + default: + return tex->read2d(make_uint2(x, y)); + } + } + + void fallback::texture_write_2d_float(const FallbackTextureView* tex, uint x, uint y, float4 value) noexcept + { + switch (tex->storage()) + { + case PixelStorage::BC7: + { + LUISA_ERROR("cannot write to BC texture"); + break; + } + case PixelStorage::BC6: + { + LUISA_ERROR("cannot write to BC texture"); + break; + } + default: + return tex->write2d(make_uint2(x, y), value); + } + } + void fallback::texture_write_2d_uint(const FallbackTextureView* tex, uint x, uint y, uint4 value) noexcept + { + switch (tex->storage()) + { + case PixelStorage::BC7: + { + LUISA_ERROR("cannot write to BC texture"); + break; + } + case PixelStorage::BC6: + { + LUISA_ERROR("cannot write to BC texture"); + break; + } + default: + return tex->write2d(make_uint2(x, y), value); + } + } + + float4 fallback::texture_read_3d_float(const FallbackTextureView* tex, uint x, uint y, uint z) noexcept + { + switch (tex->storage()) + { + case PixelStorage::BC7: + { + LUISA_ERROR("Block compression doesn't work for 3D texture"); + return make_float4(0.f); + } + case PixelStorage::BC6: + { + LUISA_ERROR("Block compression doesn't work for 3D texture"); + return make_float4(0.f); + } + default: + return tex->read3d(make_uint3(x, y, z)); + } + } + + + float4 fallback::bindless_texture_2d_read(const FallbackTexture* tex, uint level, uint x, uint y) noexcept + { + auto view = tex->view(level); + return texture_read_2d_float(&view, x, y); + } + + float4 fallback::bindless_texture_3d_read(const FallbackTexture* tex, uint level, uint x, uint y, uint z) noexcept + { + auto view = tex->view(level); + return texture_read_3d_float(&view, x, y, z); + } + + + //2D sampling + template + [[nodiscard]] inline auto texture_coord_point(Sampler::Address address, const T& uv, T s) noexcept + { + switch (address) + { + case Sampler::Address::EDGE: return luisa::clamp(uv, 0.0f, one_minus_epsilon) * s; + case Sampler::Address::REPEAT: return luisa::fract(uv) * s; + case Sampler::Address::MIRROR: + { + auto uv0 = luisa::fmod(luisa::abs(uv), T{2.0f}); + uv0 = select(2.f - uv, uv, uv < T{1.f}); + return luisa::min(uv, one_minus_epsilon) * s; + } + case Sampler::Address::ZERO: return luisa::select(uv * s, T{65536.f}, uv < 0.f || uv >= 1.f); + } + return T{65536.f}; + } + + [[nodiscard]] inline auto texture_sample_point(FallbackTextureView* view, Sampler::Address address, + const float2& uv) noexcept + { + auto size = make_float2(view->size2d()); + auto c = make_uint2(texture_coord_point(address, uv, size)); + return texture_read_2d_float(view, c.x, c.y); + } + + [[nodiscard]] inline auto texture_coord_linear(Sampler::Address address, float2 uv, const float2& size) noexcept + { + auto s = make_float2(size); + auto inv_s = 1.f / s; + auto c_min = texture_coord_point(address, uv - .5f * inv_s, s); + auto c_max = texture_coord_point(address, uv + .5f * inv_s, s); + return std::make_pair(luisa::min(c_min, c_max), luisa::max(c_min, c_max)); + } + + [[nodiscard]] inline auto texture_sample_linear(FallbackTextureView* view, Sampler::Address address, + const float2& uv) noexcept + { + auto size = make_float2(view->size2d()); + auto [st_min, st_max] = texture_coord_linear(address, uv, size); + auto t = luisa::fract(st_max); + auto c0 = make_uint2(st_min); + auto c1 = make_uint2(st_max); + auto v00 = texture_read_2d_float(view, c0.x, c0.y); + auto v01 = texture_read_2d_float(view, c1.x, c0.y); + auto v10 = texture_read_2d_float(view, c0.x, c1.y); + auto v11 = texture_read_2d_float(view, c1.x, c1.y); + return luisa::lerp(luisa::lerp(v00, v01, t.x), + luisa::lerp(v10, v11, t.x), t.y); + } + + float4 fallback::bindless_texture_2d_sample(const FallbackTexture* tex, uint sampler, float u, float v) noexcept + { + auto s = Sampler::decode(sampler); + auto view = tex->view(0); + return s.filter() == Sampler::Filter::POINT + ? texture_sample_point(&view, s.address(), make_float2(u, v)) + : texture_sample_linear(&view, s.address(), make_float2(u, v)); + } + + float4 bindless_texture_2d_sample_level(const FallbackTexture* tex, uint sampler, float u, float v, + float lod) noexcept + { + auto s = Sampler::decode(sampler); + auto filter = s.filter(); + if (lod <= 0.f || tex->mip_levels() == 0u || + filter == Sampler::Filter::POINT) + { + return bindless_texture_2d_sample(tex, sampler, u, v); + } + auto level0 = std::min(static_cast(lod), + tex->mip_levels() - 1u); + auto view0 = tex->view(level0); + auto v0 = texture_sample_linear( + &view0, s.address(), make_float2(u, v)); + if (level0 == tex->mip_levels() - 1u || + filter == Sampler::Filter::LINEAR_POINT) + { + return v0; + } + auto view1 = tex->view(level0 + 1); + auto v1 = texture_sample_linear( + &view1, s.address(), make_float2(u, v)); + return luisa::lerp(v0, v1, luisa::fract(lod)); + } + + //swfly: im too lazy to do this. complete it someday + float4 bindless_texture_2d_sample_grad(const FallbackTexture* tex, uint sampler, float u, float v, int64_t dpdx, + int64_t dpdy) noexcept + { + return bindless_texture_2d_sample(tex, sampler, u, v); + } + + //3D sampling + [[nodiscard]] inline auto texture_sample_point(FallbackTextureView* view, Sampler::Address address, + float3 uv) noexcept + { + auto size = make_float3(view->size3d()); + auto c = make_uint3(texture_coord_point(address, uv, size)); + return texture_read_3d_float(view, c.x, c.y, c.z); + } + + [[nodiscard]] inline auto texture_coord_linear(Sampler::Address address, float3 uv, float3 size) noexcept + { + auto s = make_float3(size); + auto inv_s = 1.f / s; + auto c_min = texture_coord_point(address, uv - .5f * inv_s, s); + auto c_max = texture_coord_point(address, uv + .5f * inv_s, s); + return std::make_pair(luisa::min(c_min, c_max), luisa::max(c_min, c_max)); + } + + [[nodiscard]] inline auto texture_sample_linear(FallbackTextureView* view, Sampler::Address address, + float3 uvw) noexcept + { + auto size = make_float3(view->size3d()); + auto [st_min, st_max] = texture_coord_linear(address, uvw, size); + auto t = luisa::fract(st_max); + auto c0 = make_uint3(st_min); + auto c1 = make_uint3(st_max); + auto v000 = texture_read_3d_float(view, c0.x, c0.y, c0.z); + auto v001 = texture_read_3d_float(view, c1.x, c0.y, c0.z); + auto v010 = texture_read_3d_float(view, c0.x, c1.y, c0.z); + auto v011 = texture_read_3d_float(view, c1.x, c1.y, c0.z); + auto v100 = texture_read_3d_float(view, c0.x, c0.y, c1.z); + auto v101 = texture_read_3d_float(view, c1.x, c0.y, c1.z); + auto v110 = texture_read_3d_float(view, c0.x, c1.y, c1.z); + auto v111 = texture_read_3d_float(view, c1.x, c1.y, c1.z); + return luisa::lerp( + luisa::lerp(luisa::lerp(v000, v001, t.x), + luisa::lerp(v010, v011, t.x), t.y), + luisa::lerp(luisa::lerp(v100, v101, t.x), + luisa::lerp(v110, v111, t.x), t.y), + t.z); + } + + float4 fallback::bindless_texture_3d_sample(const FallbackTexture* tex, uint sampler, float u, float v, + float w) noexcept + { + auto s = Sampler::decode(sampler); + auto view = tex->view(0); + return s.filter() == Sampler::Filter::POINT + ? texture_sample_point(&view, s.address(), make_float3(u, v, w)) + : texture_sample_linear(&view, s.address(), make_float3(u, v, w)); + } + + float4 bindless_texture_3d_sample_level(const FallbackTexture* tex, uint sampler, float u, float v, float w, + float lod) noexcept + { + auto s = Sampler::decode(sampler); + auto filter = s.filter(); + if (lod <= 0.f || tex->mip_levels() == 0u || + filter == Sampler::Filter::POINT) + { + return bindless_texture_3d_sample(tex, sampler, u, v, w); + } + auto level0 = std::min(static_cast(lod), + tex->mip_levels() - 1u); + auto view0 = tex->view(level0); + auto v0 = texture_sample_linear( + &view0, s.address(), make_float3(u, v, w)); + if (level0 == tex->mip_levels() - 1u || + filter == Sampler::Filter::LINEAR_POINT) + { + return v0; + } + auto view1 = tex->view(level0 + 1); + auto v1 = texture_sample_linear( + &view1, s.address(), make_float3(u, v, w)); + return luisa::lerp(v0, v1, luisa::fract(lod)); + } + + + //swfly: im too lazy to do this. complete it someday + float4 bindless_texture_3d_sample_grad(const FallbackTexture* tex, uint sampler, float u, float v, float w, + int64_t dudxy, int64_t dvdxy, int64_t dwdxy) noexcept + { + return bindless_texture_3d_sample(tex, sampler, u, v, w); + } +} // namespace luisa::compute::fallback diff --git a/src/backends/fallback/llvm_abi.h b/src/backends/fallback/llvm_abi.h new file mode 100644 index 000000000..e812e777d --- /dev/null +++ b/src/backends/fallback/llvm_abi.h @@ -0,0 +1,48 @@ +// +// Created by mike on 22-6-9. +// + +#pragma once + +#include +#include + +namespace luisa::compute::fallback::detail { + +[[nodiscard]] inline auto decode_float4(int64_t v0, int64_t v1) noexcept { + return luisa::bit_cast(std::array{v0, v1}); +} + +[[nodiscard]] inline auto decode_int4(int64_t v0, int64_t v1) noexcept { + return luisa::bit_cast(std::array{v0, v1}); +} + +[[nodiscard]] inline auto decode_uint4(int64_t v0, int64_t v1) noexcept { + return luisa::bit_cast(std::array{v0, v1}); +} + +[[nodiscard]] inline auto decode_uint3(int64_t v0, int64_t v1) noexcept { + return luisa::bit_cast(std::array{v0, v1}); +} + +[[nodiscard]] inline auto decode_uint2(int64_t x) noexcept { + return luisa::bit_cast(x); +} + +[[nodiscard]] inline auto decode_float2(int64_t x) noexcept { + return luisa::bit_cast(x); +} + +[[nodiscard]] inline auto encode_int4(int4 x) noexcept { + return luisa::bit_cast(x); +} + +[[nodiscard]] inline auto encode_uint4(uint4 x) noexcept { + return luisa::bit_cast(x); +} + +[[nodiscard]] inline auto encode_float4(float4 x) noexcept { + return luisa::bit_cast(x); +} + +}// namespace luisa::compute::llvm::detail diff --git a/src/backends/fallback/llvm_codegen.cpp b/src/backends/fallback/llvm_codegen.cpp new file mode 100644 index 000000000..7afe3e056 --- /dev/null +++ b/src/backends/fallback/llvm_codegen.cpp @@ -0,0 +1,38 @@ +// +// Created by Mike Smith on 2022/5/23. +// + +#include "llvm_codegen.h" + +namespace luisa::compute::fallback { + +LLVMCodegen::LLVMCodegen(::llvm::LLVMContext &ctx) noexcept + : _context{ctx} {} + +std::unique_ptr<::llvm::Module> LLVMCodegen::emit(Function f) noexcept { + auto module_name = luisa::format("module_{:016x}", f.hash()); + auto module = std::make_unique<::llvm::Module>( + ::llvm::StringRef{module_name.data(), module_name.size()}, _context); + _module = module.get(); + static_cast(_create_function(f)); + for (auto &&func : _module->functions()) { + for (auto &&bb : func) { + for (auto &&inst : bb) { + if (::llvm::isa<::llvm::FPMathOperator>(&inst)) { + inst.setFast(true); + } + } + } + } + _module = nullptr; + _constants.clear(); + _struct_types.clear(); + return module; +} + +LLVMCodegen::FunctionContext *LLVMCodegen::_current_context() noexcept { + LUISA_ASSERT(!_function_stack.empty(), "Empty function context stack."); + return _function_stack.back().get(); +} + +}// namespace luisa::compute::llvm diff --git a/src/backends/fallback/llvm_codegen.h b/src/backends/fallback/llvm_codegen.h new file mode 100644 index 000000000..4ceb5c982 --- /dev/null +++ b/src/backends/fallback/llvm_codegen.h @@ -0,0 +1,345 @@ +// +// Created by Mike Smith on 2022/5/23. +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LLVM_VERSION_MAJOR >= 14 +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include + +namespace luisa::compute::llvm { + +class LLVMCodegen : public StmtVisitor { + +public: + static constexpr auto accel_handle_size = sizeof(LLVMAccel::Handle); + static constexpr auto buffer_handle_size = sizeof(const void *); + static constexpr auto texture_handle_size = sizeof(LLVMTextureView); + static constexpr auto bindless_array_handle_size = sizeof(const void *); + +private: + struct FunctionContext { + Function function; + ::llvm::Function *ir; + ::llvm::Value *ret; + ::llvm::BasicBlock *exit_block; + luisa::unique_ptr<::llvm::IRBuilder<>> builder; + luisa::unordered_map variables; + luisa::vector<::llvm::BasicBlock *> break_targets; + luisa::vector<::llvm::BasicBlock *> continue_targets; + luisa::vector<::llvm::SwitchInst *> switch_stack; + ::llvm::BasicBlock *coro_cleanup; + ::llvm::BasicBlock *coro_suspend; + FunctionContext(Function f, ::llvm::Function *ir, ::llvm::Value *ret, + ::llvm::BasicBlock *exit_block, + luisa::unique_ptr<::llvm::IRBuilder<>> builder, + luisa::unordered_map variables, + ::llvm::BasicBlock *coro_cleanup = nullptr, + ::llvm::BasicBlock *coro_suspend = nullptr) noexcept + : function{f}, ir{ir}, ret{ret}, exit_block{exit_block}, + builder{std::move(builder)}, variables{std::move(variables)}, + coro_cleanup{coro_cleanup}, coro_suspend{coro_suspend} {} + }; + +private: + struct LLVMStruct { + ::llvm::StructType *type; + luisa::vector member_indices; + }; + +private: + ::llvm::LLVMContext &_context; + ::llvm::Module *_module{nullptr}; + luisa::unordered_map _struct_types; + luisa::unordered_map _constants; + luisa::vector> _function_stack; + +private: + void _emit_function() noexcept; + [[nodiscard]] luisa::string _variable_name(Variable v) const noexcept; + [[nodiscard]] luisa::string _function_name(Function f) const noexcept; + [[nodiscard]] ::llvm::Function *_create_function(Function f) noexcept; + [[nodiscard]] luisa::unique_ptr _create_kernel_program(Function f) noexcept; + [[nodiscard]] luisa::unique_ptr _create_kernel_context(Function f) noexcept; + [[nodiscard]] luisa::unique_ptr _create_callable_context(Function f) noexcept; + [[nodiscard]] ::llvm::Type *_create_type(const Type *t) noexcept; + [[nodiscard]] ::llvm::Type *_bindless_item_type() noexcept; + [[nodiscard]] ::llvm::Type *_bindless_texture_type() noexcept; + [[nodiscard]] ::llvm::Value *_create_expr(const Expression *expr) noexcept; + [[nodiscard]] ::llvm::Value *_create_unary_expr(const UnaryExpr *expr) noexcept; + [[nodiscard]] ::llvm::Value *_create_binary_expr(const BinaryExpr *expr) noexcept; + [[nodiscard]] ::llvm::Value *_create_member_expr(const MemberExpr *expr) noexcept; + [[nodiscard]] ::llvm::Value *_create_access_expr(const AccessExpr *expr) noexcept; + [[nodiscard]] ::llvm::Value *_create_literal_expr(const LiteralExpr *expr) noexcept; + [[nodiscard]] ::llvm::Value *_create_ref_expr(const RefExpr *expr) noexcept; + [[nodiscard]] ::llvm::Value *_create_constant_expr(const ConstantExpr *expr) noexcept; + [[nodiscard]] ::llvm::Value *_create_call_expr(const CallExpr *expr) noexcept; + [[nodiscard]] ::llvm::Value *_create_cast_expr(const CastExpr *expr) noexcept; + [[nodiscard]] ::llvm::Value *_create_custom_op_expr(const CpuCustomOpExpr * expr) noexcept; + [[nodiscard]] ::llvm::Value *_create_alloca(::llvm::Type *t, luisa::string_view name) noexcept; + [[nodiscard]] ::llvm::Value *_create_stack_variable(::llvm::Value *v, luisa::string_view name = "") noexcept; + [[nodiscard]] FunctionContext *_current_context() noexcept; + void _create_assignment(const Type *dst_type, const Type *src_type, ::llvm::Value *p_dst, ::llvm::Value *p_src) noexcept; + + // built-in make_vector functions + [[nodiscard]] ::llvm::Value *_make_int2(::llvm::Value *px, ::llvm::Value *py) noexcept; + [[nodiscard]] ::llvm::Value *_make_int3(::llvm::Value *px, ::llvm::Value *py, ::llvm::Value *pz) noexcept; + [[nodiscard]] ::llvm::Value *_make_int4(::llvm::Value *px, ::llvm::Value *py, ::llvm::Value *pz, ::llvm::Value *pw) noexcept; + [[nodiscard]] ::llvm::Value *_make_bool2(::llvm::Value *px, ::llvm::Value *py) noexcept; + [[nodiscard]] ::llvm::Value *_make_bool3(::llvm::Value *px, ::llvm::Value *py, ::llvm::Value *pz) noexcept; + [[nodiscard]] ::llvm::Value *_make_bool4(::llvm::Value *px, ::llvm::Value *py, ::llvm::Value *pz, ::llvm::Value *pw) noexcept; + [[nodiscard]] ::llvm::Value *_make_float2(::llvm::Value *px, ::llvm::Value *py) noexcept; + [[nodiscard]] ::llvm::Value *_make_float3(::llvm::Value *px, ::llvm::Value *py, ::llvm::Value *pz) noexcept; + [[nodiscard]] ::llvm::Value *_make_float4(::llvm::Value *px, ::llvm::Value *py, ::llvm::Value *pz, ::llvm::Value *pw) noexcept; + [[nodiscard]] ::llvm::Value *_make_float2x2(::llvm::Value *p0, ::llvm::Value *p1) noexcept; + [[nodiscard]] ::llvm::Value *_make_float3x3(::llvm::Value *p0, ::llvm::Value *p1, ::llvm::Value *p2) noexcept; + [[nodiscard]] ::llvm::Value *_make_float4x4(::llvm::Value *p0, ::llvm::Value *p1, ::llvm::Value *p2, ::llvm::Value *p3) noexcept; + + // literals + [[nodiscard]] ::llvm::Value *_literal(int x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(uint x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(bool x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(float x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(int2 x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(uint2 x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(bool2 x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(float2 x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(int3 x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(uint3 x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(bool3 x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(float3 x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(int4 x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(uint4 x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(bool4 x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(float4 x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(float2x2 x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(float3x3 x) noexcept; + [[nodiscard]] ::llvm::Value *_literal(float4x4 x) noexcept; + + // constant data + [[nodiscard]] ::llvm::Value *_create_constant(ConstantData c) noexcept; + + // built-in short-cut logical operators + [[nodiscard]] ::llvm::Value *_short_circuit_and(const Expression *lhs, const Expression *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_short_circuit_or(const Expression *lhs, const Expression *rhs) noexcept; + + // built-in operators + [[nodiscard]] ::llvm::Value *_builtin_unary_plus(const Type *t, ::llvm::Value *p) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_unary_minus(const Type *t, ::llvm::Value *p) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_unary_not(const Type *t, ::llvm::Value *p) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_unary_bit_not(const Type *t, ::llvm::Value *p) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_and(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_or(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_xor(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_add(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_sub(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_mul(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_div(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_mod(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_lt(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_le(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_gt(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_ge(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_eq(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_ne(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_shl(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_shr(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_add_matrix_scalar( + const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_add_scalar_matrix( + const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_add_matrix_matrix( + const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_sub_matrix_scalar( + const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_sub_scalar_matrix( + const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_sub_matrix_matrix( + const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_mul_matrix_scalar( + const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_mul_scalar_matrix( + const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_mul_matrix_matrix( + const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_mul_matrix_vector( + const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_div_matrix_scalar( + const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_div_scalar_matrix( + const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept; + + // built-in cast operators + [[nodiscard]] ::llvm::Value *_builtin_static_cast(const Type *t_dst, const Type *t_src, ::llvm::Value *p) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_bitwise_cast(const Type *t_dst, const Type *t_src, ::llvm::Value *p) noexcept; + [[nodiscard]] ::llvm::Value *_scalar_to_bool(const Type *src_type, ::llvm::Value *p_src) noexcept; + [[nodiscard]] ::llvm::Value *_scalar_to_float(const Type *src_type, ::llvm::Value *p_src) noexcept; + [[nodiscard]] ::llvm::Value *_scalar_to_int(const Type *src_type, ::llvm::Value *p_src) noexcept; + [[nodiscard]] ::llvm::Value *_scalar_to_uint(const Type *src_type, ::llvm::Value *p_src) noexcept; + [[nodiscard]] ::llvm::Value *_scalar_to_vector(const Type *dst_type, const Type *src_type, ::llvm::Value *p_src) noexcept; + [[nodiscard]] ::llvm::Value *_vector_to_vector(const Type *dst_type, const Type *src_type, ::llvm::Value *p_src) noexcept; + [[nodiscard]] ::llvm::Value *_vector_to_bool_vector(const Type *src_type, ::llvm::Value *p_src) noexcept; + [[nodiscard]] ::llvm::Value *_vector_to_float_vector(const Type *src_type, ::llvm::Value *p_src) noexcept; + [[nodiscard]] ::llvm::Value *_vector_to_int_vector(const Type *src_type, ::llvm::Value *p_src) noexcept; + [[nodiscard]] ::llvm::Value *_vector_to_uint_vector(const Type *src_type, ::llvm::Value *p_src) noexcept; + [[nodiscard]] ::llvm::Value *_scalar_to_matrix(const Type *dst_type, const Type *src_type, ::llvm::Value *p_src) noexcept; + [[nodiscard]] ::llvm::Value *_matrix_to_matrix(const Type *dst_type, const Type *src_type, ::llvm::Value *p_src) noexcept; + + // built-in functions + [[nodiscard]] ::llvm::Value *_create_builtin_call_expr(const Type *ret_type, CallOp op, luisa::span args) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_all(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_any(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_select(const Type *t_pred, const Type *t_value, ::llvm::Value *pred, + ::llvm::Value *v_true, ::llvm::Value *v_false) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_clamp(const Type *t, ::llvm::Value *v, ::llvm::Value *lo, ::llvm::Value *hi) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_saturate(const Type *t, ::llvm::Value *x) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_lerp(const Type *t, ::llvm::Value *a, ::llvm::Value *b, ::llvm::Value *x) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_step(const Type *t, ::llvm::Value *edge, ::llvm::Value *x) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_abs(const Type *t, ::llvm::Value *x) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_min(const Type *t, ::llvm::Value *x, ::llvm::Value *y) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_max(const Type *t, ::llvm::Value *x, ::llvm::Value *y) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_fma(const Type *t, ::llvm::Value *a, ::llvm::Value *b, ::llvm::Value *c) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_clz(const Type *t, ::llvm::Value *p) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_ctz(const Type *t, ::llvm::Value *p) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_popcount(const Type *t, ::llvm::Value *p) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_reverse(const Type *t, ::llvm::Value *p) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_isinf(const Type *t, ::llvm::Value *p) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_isnan(const Type *t, ::llvm::Value *p) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_buffer_read(const Type *t_value, ::llvm::Value *buffer, ::llvm::Value *p_index) noexcept; + void _builtin_buffer_write(const Type *t_value, ::llvm::Value *buffer, ::llvm::Value *p_index, ::llvm::Value *p_value) noexcept; + void _builtin_assume(::llvm::Value *p) noexcept; + void _builtin_unreachable() noexcept; + [[nodiscard]] ::llvm::Value *_builtin_texture_read(const Type *t, ::llvm::Value *texture, + const Type *t_coord, ::llvm::Value *p_coord) noexcept; + void _builtin_texture_write(const Type *t, ::llvm::Value *texture, const Type *t_coord, + ::llvm::Value *p_coord, ::llvm::Value *p_value) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_sqrt(const Type *t, ::llvm::Value *x) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_rsqrt(const Type *t, ::llvm::Value *x) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_dot(const Type *t, ::llvm::Value *a, ::llvm::Value *b) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_length_squared(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_normalize(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_floor(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_fract(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_ceil(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_trunc(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_round(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_sin(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_cos(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_tan(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_sinh(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_cosh(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_tanh(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_asinh(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_acosh(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_atanh(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_exp(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_exp2(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_exp10(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_log(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_log2(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_log10(const Type *t, ::llvm::Value *v) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_pow(const Type *t, ::llvm::Value *x, ::llvm::Value *y) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_copysign(const Type *t, ::llvm::Value *x, ::llvm::Value *y) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_faceforward( + const Type *t, ::llvm::Value *n, ::llvm::Value *i, ::llvm::Value *nref) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_cross(const Type *t, ::llvm::Value *a, ::llvm::Value *b) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_make_vector2_overloaded(const Type *t_vec, luisa::span args) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_make_vector3_overloaded(const Type *t_vec, luisa::span args) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_make_vector4_overloaded(const Type *t_vec, luisa::span args) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_make_matrix2_overloaded(luisa::span args) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_make_matrix3_overloaded(luisa::span args) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_make_matrix4_overloaded(luisa::span args) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_atomic_exchange( + const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_desired) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_atomic_compare_exchange( + const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_expected, ::llvm::Value *p_desired) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_atomic_fetch_add( + const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_value) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_atomic_fetch_sub( + const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_value) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_atomic_fetch_and( + const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_value) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_atomic_fetch_or( + const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_value) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_atomic_fetch_xor( + const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_value) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_atomic_fetch_min( + const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_value) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_atomic_fetch_max( + const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_value) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_inverse(const Type *t, ::llvm::Value *pm) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_determinant(const Type *t, ::llvm::Value *pm) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_transpose(const Type *t, ::llvm::Value *pm) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_trace_closest(::llvm::Value *accel, ::llvm::Value *p_ray) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_trace_any(::llvm::Value *accel, ::llvm::Value *p_ray) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_instance_transform(::llvm::Value *accel, ::llvm::Value *p_index) noexcept; + void _builtin_set_instance_transform(::llvm::Value *accel, ::llvm::Value *p_index, ::llvm::Value *p_mat) noexcept; + void _builtin_set_instance_visibility(::llvm::Value *accel, ::llvm::Value *p_index, ::llvm::Value *p_vis) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_bindless_texture_size2d(::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_level) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_bindless_texture_size3d(::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_level) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_bindless_buffer_read(const Type *t, ::llvm::Value *p_items, + ::llvm::Value *p_buffer_index, ::llvm::Value *p_elem_index) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_bindless_texture_read2d( + ::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_level, ::llvm::Value *p_uv) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_bindless_texture_read3d( + ::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_level, ::llvm::Value *p_uvw) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_bindless_texture_sample2d( + ::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_uv) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_bindless_texture_sample3d( + ::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_uvw) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_bindless_texture_sample2d_level( + ::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_uv, ::llvm::Value *p_lod) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_bindless_texture_sample3d_level( + ::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_uvw, ::llvm::Value *p_lod) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_bindless_texture_sample2d_grad( + ::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_uv, ::llvm::Value *p_dpdx, ::llvm::Value *p_dpdy) noexcept; + [[nodiscard]] ::llvm::Value *_builtin_bindless_texture_sample3d_grad( + ::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_uvw, ::llvm::Value *p_dpdx, ::llvm::Value *p_dpdy) noexcept; + void _builtin_synchronize_block() noexcept; + +public: + explicit LLVMCodegen(::llvm::LLVMContext &ctx) noexcept; + void visit(const BreakStmt *stmt) override; + void visit(const ContinueStmt *stmt) override; + void visit(const ReturnStmt *stmt) override; + void visit(const ScopeStmt *stmt) override; + void visit(const IfStmt *stmt) override; + void visit(const LoopStmt *stmt) override; + void visit(const ExprStmt *stmt) override; + void visit(const SwitchStmt *stmt) override; + void visit(const SwitchCaseStmt *stmt) override; + void visit(const SwitchDefaultStmt *stmt) override; + void visit(const AssignStmt *stmt) override; + void visit(const ForStmt *stmt) override; + void visit(const CommentStmt *stmt) override; + [[nodiscard]] std::unique_ptr<::llvm::Module> emit(Function f) noexcept; +}; + +}// namespace luisa::compute::llvm diff --git a/src/backends/fallback/llvm_codegen_builtin.cpp b/src/backends/fallback/llvm_codegen_builtin.cpp new file mode 100644 index 000000000..9ba591833 --- /dev/null +++ b/src/backends/fallback/llvm_codegen_builtin.cpp @@ -0,0 +1,2976 @@ +// +// Created by Mike Smith on 2022/5/23. +// + +#include + +#include +#include +#include + +namespace luisa::compute::fallback { + +[[nodiscard]] static Function float2x2_inverse() noexcept { + static Callable inverse = [](Float2x2 m) noexcept { + auto inv_det = 1.0f / (m[0][0] * m[1][1] - m[1][0] * m[0][1]); + return inv_det * make_float2x2(m[1][1], -m[0][1], -m[1][0], +m[0][0]); + }; + return inverse.function(); +} + +[[nodiscard]] static Function float3x3_inverse() noexcept { + static Callable inverse = [](Float3x3 m) noexcept { + auto inv_det = 1.0f / + (m[0].x * (m[1].y * m[2].z - m[2].y * m[1].z) - + m[1].x * (m[0].y * m[2].z - m[2].y * m[0].z) + + m[2].x * (m[0].y * m[1].z - m[1].y * m[0].z)); + auto mm = make_float3x3( + m[1].y * m[2].z - m[2].y * m[1].z, + m[2].y * m[0].z - m[0].y * m[2].z, + m[0].y * m[1].z - m[1].y * m[0].z, + m[2].x * m[1].z - m[1].x * m[2].z, + m[0].x * m[2].z - m[2].x * m[0].z, + m[1].x * m[0].z - m[0].x * m[1].z, + m[1].x * m[2].y - m[2].x * m[1].y, + m[2].x * m[0].y - m[0].x * m[2].y, + m[0].x * m[1].y - m[1].x * m[0].y); + return inv_det * mm; + }; + return inverse.function(); +} + +[[nodiscard]] static Function float4x4_inverse() noexcept { + static Callable inverse = [](Float4x4 m) noexcept { + auto coef00 = m[2].z * m[3].w - m[3].z * m[2].w; + auto coef02 = m[1].z * m[3].w - m[3].z * m[1].w; + auto coef03 = m[1].z * m[2].w - m[2].z * m[1].w; + auto coef04 = m[2].y * m[3].w - m[3].y * m[2].w; + auto coef06 = m[1].y * m[3].w - m[3].y * m[1].w; + auto coef07 = m[1].y * m[2].w - m[2].y * m[1].w; + auto coef08 = m[2].y * m[3].z - m[3].y * m[2].z; + auto coef10 = m[1].y * m[3].z - m[3].y * m[1].z; + auto coef11 = m[1].y * m[2].z - m[2].y * m[1].z; + auto coef12 = m[2].x * m[3].w - m[3].x * m[2].w; + auto coef14 = m[1].x * m[3].w - m[3].x * m[1].w; + auto coef15 = m[1].x * m[2].w - m[2].x * m[1].w; + auto coef16 = m[2].x * m[3].z - m[3].x * m[2].z; + auto coef18 = m[1].x * m[3].z - m[3].x * m[1].z; + auto coef19 = m[1].x * m[2].z - m[2].x * m[1].z; + auto coef20 = m[2].x * m[3].y - m[3].x * m[2].y; + auto coef22 = m[1].x * m[3].y - m[3].x * m[1].y; + auto coef23 = m[1].x * m[2].y - m[2].x * m[1].y; + auto fac0 = make_float4(coef00, coef00, coef02, coef03); + auto fac1 = make_float4(coef04, coef04, coef06, coef07); + auto fac2 = make_float4(coef08, coef08, coef10, coef11); + auto fac3 = make_float4(coef12, coef12, coef14, coef15); + auto fac4 = make_float4(coef16, coef16, coef18, coef19); + auto fac5 = make_float4(coef20, coef20, coef22, coef23); + auto Vec0 = make_float4(m[1].x, m[0].x, m[0].x, m[0].x); + auto Vec1 = make_float4(m[1].y, m[0].y, m[0].y, m[0].y); + auto Vec2 = make_float4(m[1].z, m[0].z, m[0].z, m[0].z); + auto Vec3 = make_float4(m[1].w, m[0].w, m[0].w, m[0].w); + auto inv0 = Vec1 * fac0 - Vec2 * fac1 + Vec3 * fac2; + auto inv1 = Vec0 * fac0 - Vec2 * fac3 + Vec3 * fac4; + auto inv2 = Vec0 * fac1 - Vec1 * fac3 + Vec3 * fac5; + auto inv3 = Vec0 * fac2 - Vec1 * fac4 + Vec2 * fac5; + auto sign_a = make_float4(+1.0f, -1.0f, +1.0f, -1.0f); + auto sign_b = make_float4(-1.0f, +1.0f, -1.0f, +1.0f); + auto inv_0 = inv0 * sign_a; + auto inv_1 = inv1 * sign_b; + auto inv_2 = inv2 * sign_a; + auto inv_3 = inv3 * sign_b; + auto dot0 = m[0] * make_float4(inv_0.x, inv_1.x, inv_2.x, inv_3.x); + auto dot1 = dot0.x + dot0.y + dot0.z + dot0.w; + auto inv_det = 1.0f / dot1; + return inv_det * make_float4x4(inv_0, inv_1, inv_2, inv_3); + }; + return inverse.function(); +} + +[[nodiscard]] static Function float2x2_det() noexcept { + static Callable inverse = [](Float2x2 m) noexcept { + return m[0][0] * m[1][1] - m[1][0] * m[0][1]; + }; + return inverse.function(); +} + +[[nodiscard]] static Function float3x3_det() noexcept { + static Callable inverse = [](Float3x3 m) noexcept { + return m[0].x * (m[1].y * m[2].z - m[2].y * m[1].z) - + m[1].x * (m[0].y * m[2].z - m[2].y * m[0].z) + + m[2].x * (m[0].y * m[1].z - m[1].y * m[0].z); + }; + return inverse.function(); +} + +[[nodiscard]] static Function float4x4_det() noexcept { + static Callable inverse = [](Float4x4 m) noexcept { + auto coef00 = m[2].z * m[3].w - m[3].z * m[2].w; + auto coef02 = m[1].z * m[3].w - m[3].z * m[1].w; + auto coef03 = m[1].z * m[2].w - m[2].z * m[1].w; + auto coef04 = m[2].y * m[3].w - m[3].y * m[2].w; + auto coef06 = m[1].y * m[3].w - m[3].y * m[1].w; + auto coef07 = m[1].y * m[2].w - m[2].y * m[1].w; + auto coef08 = m[2].y * m[3].z - m[3].y * m[2].z; + auto coef10 = m[1].y * m[3].z - m[3].y * m[1].z; + auto coef11 = m[1].y * m[2].z - m[2].y * m[1].z; + auto coef12 = m[2].x * m[3].w - m[3].x * m[2].w; + auto coef14 = m[1].x * m[3].w - m[3].x * m[1].w; + auto coef15 = m[1].x * m[2].w - m[2].x * m[1].w; + auto coef16 = m[2].x * m[3].z - m[3].x * m[2].z; + auto coef18 = m[1].x * m[3].z - m[3].x * m[1].z; + auto coef19 = m[1].x * m[2].z - m[2].x * m[1].z; + auto coef20 = m[2].x * m[3].y - m[3].x * m[2].y; + auto coef22 = m[1].x * m[3].y - m[3].x * m[1].y; + auto coef23 = m[1].x * m[2].y - m[2].x * m[1].y; + auto fac0 = make_float4(coef00, coef00, coef02, coef03); + auto fac1 = make_float4(coef04, coef04, coef06, coef07); + auto fac2 = make_float4(coef08, coef08, coef10, coef11); + auto fac3 = make_float4(coef12, coef12, coef14, coef15); + auto fac4 = make_float4(coef16, coef16, coef18, coef19); + auto fac5 = make_float4(coef20, coef20, coef22, coef23); + auto Vec0 = make_float4(m[1].x, m[0].x, m[0].x, m[0].x); + auto Vec1 = make_float4(m[1].y, m[0].y, m[0].y, m[0].y); + auto Vec2 = make_float4(m[1].z, m[0].z, m[0].z, m[0].z); + auto Vec3 = make_float4(m[1].w, m[0].w, m[0].w, m[0].w); + auto inv0 = Vec1 * fac0 - Vec2 * fac1 + Vec3 * fac2; + auto inv1 = Vec0 * fac0 - Vec2 * fac3 + Vec3 * fac4; + auto inv2 = Vec0 * fac1 - Vec1 * fac3 + Vec3 * fac5; + auto inv3 = Vec0 * fac2 - Vec1 * fac4 + Vec2 * fac5; + auto sign_a = make_float4(+1.0f, -1.0f, +1.0f, -1.0f); + auto sign_b = make_float4(-1.0f, +1.0f, -1.0f, +1.0f); + auto inv_0 = inv0 * sign_a; + auto inv_1 = inv1 * sign_b; + auto inv_2 = inv2 * sign_a; + auto inv_3 = inv3 * sign_b; + auto dot0 = m[0] * make_float4(inv_0.x, inv_1.x, inv_2.x, inv_3.x); + return dot0.x + dot0.y + dot0.z + dot0.w; + }; + return inverse.function(); +} + +[[nodiscard]] static Function float2x2_transpose() noexcept { + static Callable inverse = [](Float2x2 m) noexcept { + return make_float2x2(m[0].x, m[1].x, m[0].y, m[1].y); + }; + return inverse.function(); +} + +[[nodiscard]] static Function float3x3_transpose() noexcept { + static Callable inverse = [](Float3x3 m) noexcept { + return make_float3x3( + m[0].x, m[1].x, m[2].x, + m[0].y, m[1].y, m[2].y, + m[0].z, m[1].z, m[2].z); + }; + return inverse.function(); +} + +[[nodiscard]] static Function float4x4_transpose() noexcept { + static Callable inverse = [](Float4x4 m) noexcept { + return make_float4x4( + m[0].x, m[1].x, m[2].x, m[3].x, + m[0].y, m[1].y, m[2].y, m[3].y, + m[0].z, m[1].z, m[2].z, m[3].z, + m[0].w, m[1].w, m[2].w, m[3].w); + }; + return inverse.function(); +} + +::llvm::Value *LLVMCodegen::_builtin_inverse(const Type *t, ::llvm::Value *pm) noexcept { + LUISA_ASSERT(t->is_matrix(), "Expected matrix type."); + auto ast = [t] { + if (t->dimension() == 2u) { return float2x2_inverse(); } + if (t->dimension() == 3u) { return float3x3_inverse(); } + if (t->dimension() == 4u) { return float4x4_inverse(); } + LUISA_ERROR_WITH_LOCATION("Invalid matrix dimension {}.", t->dimension()); + }(); + auto func = _create_function(ast); + auto b = _current_context()->builder.get(); + auto m = b->CreateLoad(_create_type(t), pm, "inverse.m"); + auto ret = b->CreateCall(func->getFunctionType(), func, m, "inverse.ret"); + return _create_stack_variable(ret, "inverse.ret.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_determinant(const Type *t, ::llvm::Value *pm) noexcept { + LUISA_ASSERT(t->is_matrix(), "Expected matrix type."); + auto ast = [t] { + if (t->dimension() == 2u) { return float2x2_det(); } + if (t->dimension() == 3u) { return float3x3_det(); } + if (t->dimension() == 4u) { return float4x4_det(); } + LUISA_ERROR_WITH_LOCATION("Invalid matrix dimension {}.", t->dimension()); + }(); + auto func = _create_function(ast); + auto b = _current_context()->builder.get(); + auto m = b->CreateLoad(_create_type(t), pm, "determinant.m"); + auto ret = b->CreateCall(func->getFunctionType(), func, m, "determinant.ret"); + return _create_stack_variable(ret, "determinant.ret.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_transpose(const Type *t, ::llvm::Value *pm) noexcept { + LUISA_ASSERT(t->is_matrix(), "Expected matrix type."); + auto ast = [t] { + if (t->dimension() == 2u) { return float2x2_transpose(); } + if (t->dimension() == 3u) { return float3x3_transpose(); } + if (t->dimension() == 4u) { return float4x4_transpose(); } + LUISA_ERROR_WITH_LOCATION("Invalid matrix dimension {}.", t->dimension()); + }(); + auto func = _create_function(ast); + auto b = _current_context()->builder.get(); + auto m = b->CreateLoad(_create_type(t), pm, "transpose.m"); + auto ret = b->CreateCall(func->getFunctionType(), func, m, "transpose.ret"); + return _create_stack_variable(ret, "transpose.ret.addr"); +} + +[[nodiscard]] ::llvm::Function *_declare_external_math_function( + ::llvm::Module *module, luisa::string_view name, size_t n_args) noexcept { + auto func_name = luisa::format("{}f", name); + auto f = module->getFunction(::llvm::StringRef{func_name.data(), func_name.size()}); + auto ir_type = ::llvm::Type::getFloatTy(module->getContext()); + if (f == nullptr) { + ::llvm::SmallVector<::llvm::Type *, 2u> arg_types(n_args, ir_type); + f = ::llvm::Function::Create( + ::llvm::FunctionType::get(ir_type, arg_types, false), + ::llvm::Function::ExternalLinkage, + ::llvm::StringRef{func_name.data(), func_name.size()}, + module); + f->setNoSync(); + f->setWillReturn(); + f->setDoesNotThrow(); + f->setMustProgress(); + f->setSpeculatable(); + f->setDoesNotAccessMemory(); + f->setDoesNotFreeMemory(); + } + return f; +} + +#pragma clang diagnostic push +#pragma ide diagnostic ignored "cppcoreguidelines-pro-type-static-cast-downcast" +[[nodiscard]] ::llvm::Value *_call_external_math_function( + ::llvm::Module *module, ::llvm::IRBuilder<> *builder, const Type *t, luisa::string_view name, + ::llvm::SmallVector<::llvm::Type *, 2u> t_args, ::llvm::SmallVector<::llvm::Value *, 2u> p_args) noexcept { + auto f = _declare_external_math_function(module, name, p_args.size()); + ::llvm::SmallVector<::llvm::Value *, 2u> args; + for (auto i = 0u; i < p_args.size(); i++) { + auto value_name = luisa::format("{}.arg{}", name, i); + args.emplace_back(builder->CreateLoad( + t_args[i], p_args[i], + ::llvm::StringRef{value_name.data(), value_name.size()})); + } + // TODO: vectorize... + if (t->is_vector()) { + ::llvm::SmallVector<::llvm::Value *, 4u> v; + for (auto i = 0u; i < t->dimension(); i++) { + ::llvm::SmallVector<::llvm::Value *, 2u> args_i; + for (auto a = 0u; a < args.size(); a++) { + args_i.emplace_back(builder->CreateExtractElement(args[a], i)); + } + v.emplace_back(builder->CreateCall(f, args_i)); + } + auto vec_type = ::llvm::VectorType::get( + ::llvm::Type::getFloatTy(module->getContext()), t->dimension(), false); + auto vec = static_cast<::llvm::Value *>(::llvm::UndefValue::get(vec_type)); + for (auto i = 0u; i < t->dimension(); i++) { + vec = builder->CreateInsertElement(vec, v[i], i); + } + auto p_vec = builder->CreateAlloca(vec_type); + p_vec->setAlignment(::llvm::Align{16}); + builder->CreateStore(vec, p_vec); + return p_vec; + } + // scalar + auto y_name = luisa::format("{}.call", name); + auto y = builder->CreateCall(f, args, ::llvm::StringRef{y_name.data(), y_name.size()}); + auto py_name = luisa::format("{}.call.addr", name); + auto py = builder->CreateAlloca( + t_args.front(), nullptr, ::llvm::StringRef{py_name.data(), py_name.size()}); + py->setAlignment(::llvm::Align{16}); + builder->CreateStore(y, py); + return py; +} +#pragma clang diagnostic pop + +::llvm::Value *LLVMCodegen::_builtin_instance_transform(::llvm::Value *accel, ::llvm::Value *p_index) noexcept { + static Callable impl = [](BufferVar instances, UInt index) noexcept { + auto m = instances.read(index).affine; + return make_float4x4( + m[0], m[4], m[8], 0.f, + m[1], m[5], m[9], 0.f, + m[2], m[6], m[10], 0.f, + m[3], m[7], m[11], 1.f); + }; + auto func = _create_function(impl.function()); + auto b = _current_context()->builder.get(); + auto instances = b->CreateExtractValue(accel, 1, "accel.instance.transform.instances"); + auto index = b->CreateLoad(b->getInt32Ty(), p_index, "accel.instance.transform.index"); + auto ret = b->CreateCall(func->getFunctionType(), func, {instances, index}, "accel.instance.transform.ret"); + return _create_stack_variable(ret, "accel.instance.transform.ret.addr"); +} + +void LLVMCodegen::_builtin_set_instance_transform(::llvm::Value *accel, ::llvm::Value *p_index, ::llvm::Value *p_mat) noexcept { + static Callable impl = [](BufferVar instances, UInt index, Float4x4 m) noexcept { + auto inst = instances.read(index); + inst.dirty = true; + inst.affine[0] = m[0].x; + inst.affine[1] = m[1].x; + inst.affine[2] = m[2].x; + inst.affine[3] = m[3].x; + inst.affine[4] = m[0].y; + inst.affine[5] = m[1].y; + inst.affine[6] = m[2].y; + inst.affine[7] = m[3].y; + inst.affine[8] = m[0].z; + inst.affine[9] = m[1].z; + inst.affine[10] = m[2].z; + inst.affine[11] = m[3].z; + instances.write(index, inst); + }; + auto func = _create_function(impl.function()); + auto b = _current_context()->builder.get(); + auto instances = b->CreateExtractValue(accel, 1, "accel.instance.transform.instances"); + auto index = b->CreateLoad(b->getInt32Ty(), p_index, "accel.instance.transform.index"); + auto mat = b->CreateLoad(b->getFloatTy()->getPointerTo(), p_mat, "accel.instance.transform.mat"); + b->CreateCall(func->getFunctionType(), func, {instances, index, mat}); +} + +void LLVMCodegen::_builtin_set_instance_visibility(::llvm::Value *accel, ::llvm::Value *p_index, ::llvm::Value *p_vis) noexcept { + auto b = _current_context()->builder.get(); + auto ptr = b->CreateExtractValue(accel, 1, "accel.instance.visibility.instances"); + auto index = b->CreateLoad(b->getInt32Ty(), p_index, "accel.instance.visibility.index"); + auto t_instance = _create_type(Type::of()); + auto ptr_vis = b->CreateInBoundsGEP(t_instance, ptr, {index, _literal(1)}, "accel.instance.visibility.vis.ptr"); + auto ptr_dirty = b->CreateInBoundsGEP(t_instance, ptr, {index, _literal(2)}, "accel.instance.visibility.dirty.ptr"); + auto vis = b->CreateLoad(b->getInt32Ty(), p_vis, "accel.instance.visibility.vis"); + b->CreateStore(vis, ptr_vis); + b->CreateStore(_literal(true), ptr_dirty); +} + +::llvm::Value *LLVMCodegen::_create_builtin_call_expr(const Type *ret_type, CallOp op, luisa::span args) noexcept { + auto builder = _current_context()->builder.get(); + switch (op) { + case CallOp::ALL: return _builtin_all( + args[0]->type(), _create_expr(args[0])); + case CallOp::ANY: return _builtin_any( + args[0]->type(), _create_expr(args[0])); + case CallOp::SELECT: return _builtin_select( + args[2]->type(), args[0]->type(), _create_expr(args[2]), + _create_expr(args[1]), _create_expr(args[0])); + case CallOp::CLAMP: return _builtin_clamp( + args[0]->type(), _create_expr(args[0]), + _create_expr(args[1]), _create_expr(args[2])); + case CallOp::SATURATE: return _builtin_saturate( + args[0]->type(), _create_expr(args[0])); + case CallOp::LERP: return _builtin_lerp( + args[0]->type(), _create_expr(args[0]), + _create_expr(args[1]), _create_expr(args[2])); + case CallOp::STEP: return _builtin_step( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::ABS: return _builtin_abs( + args[0]->type(), _create_expr(args[0])); + case CallOp::MIN: return _builtin_min( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::MAX: return _builtin_max( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::CLZ: return _builtin_clz( + args[0]->type(), _create_expr(args[0])); + case CallOp::CTZ: return _builtin_ctz( + args[0]->type(), _create_expr(args[0])); + case CallOp::POPCOUNT: return _builtin_popcount( + args[0]->type(), _create_expr(args[0])); + case CallOp::REVERSE: return _builtin_reverse( + args[0]->type(), _create_expr(args[0])); + case CallOp::ISINF: return _builtin_isinf( + args[0]->type(), _create_expr(args[0])); + case CallOp::ISNAN: return _builtin_isnan( + args[0]->type(), _create_expr(args[0])); + case CallOp::ACOS: return _call_external_math_function( + _module, builder, args[0]->type(), "acos", + {_create_type(args[0]->type())}, {_create_expr(args[0])}); + case CallOp::ACOSH: return _builtin_acosh( + args[0]->type(), _create_expr(args[0])); + case CallOp::ASIN: return _call_external_math_function( + _module, builder, args[0]->type(), "asin", + {_create_type(args[0]->type())}, {_create_expr(args[0])}); + case CallOp::ASINH: return _builtin_asinh( + args[0]->type(), _create_expr(args[0])); + case CallOp::ATAN: return _call_external_math_function( + _module, builder, args[0]->type(), "atan", + {_create_type(args[0]->type())}, {_create_expr(args[0])}); + case CallOp::ATAN2: return _call_external_math_function( + _module, builder, args[0]->type(), "atan2", + {_create_type(args[0]->type()), _create_type(args[1]->type())}, + {_create_expr(args[0]), _create_expr(args[1])}); + case CallOp::ATANH: return _builtin_atanh( + args[0]->type(), _create_expr(args[0])); + case CallOp::COS: return _builtin_cos( + args[0]->type(), _create_expr(args[0])); + case CallOp::COSH: return _builtin_cosh( + args[0]->type(), _create_expr(args[0])); + case CallOp::SIN: return _builtin_sin( + args[0]->type(), _create_expr(args[0])); + case CallOp::SINH: return _builtin_sinh( + args[0]->type(), _create_expr(args[0])); + case CallOp::TAN: return _builtin_tan( + args[0]->type(), _create_expr(args[0])); + case CallOp::TANH: return _builtin_tanh( + args[0]->type(), _create_expr(args[0])); + case CallOp::EXP: return _builtin_exp( + args[0]->type(), _create_expr(args[0])); + case CallOp::EXP2: return _builtin_exp2( + args[0]->type(), _create_expr(args[0])); + case CallOp::EXP10: return _builtin_exp10( + args[0]->type(), _create_expr(args[0])); + case CallOp::LOG: return _builtin_log( + args[0]->type(), _create_expr(args[0])); + case CallOp::LOG2: return _builtin_log2( + args[0]->type(), _create_expr(args[0])); + case CallOp::LOG10: return _builtin_log10( + args[0]->type(), _create_expr(args[0])); + case CallOp::POW: return _builtin_pow( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::SQRT: return _builtin_sqrt( + args[0]->type(), _create_expr(args[0])); + case CallOp::RSQRT: return _builtin_rsqrt( + args[0]->type(), _create_expr(args[0])); + case CallOp::CEIL: return _builtin_ceil( + args[0]->type(), _create_expr(args[0])); + case CallOp::FLOOR: return _builtin_floor( + args[0]->type(), _create_expr(args[0])); + case CallOp::FRACT: return _builtin_fract( + args[0]->type(), _create_expr(args[0])); + case CallOp::TRUNC: return _builtin_trunc( + args[0]->type(), _create_expr(args[0])); + case CallOp::ROUND: return _builtin_round( + args[0]->type(), _create_expr(args[0])); + case CallOp::FMA: return _builtin_fma( + args[0]->type(), _create_expr(args[0]), + _create_expr(args[1]), _create_expr(args[2])); + case CallOp::COPYSIGN: return _builtin_copysign( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::CROSS: return _builtin_cross( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::DOT: return _builtin_dot( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::LENGTH: return _builtin_sqrt( + Type::of(), _builtin_length_squared(args[0]->type(), _create_expr(args[0]))); + case CallOp::LENGTH_SQUARED: return _builtin_length_squared( + args[0]->type(), _create_expr(args[0])); + case CallOp::NORMALIZE: return _builtin_normalize( + args[0]->type(), _create_expr(args[0])); + case CallOp::FACEFORWARD: return _builtin_faceforward( + args[0]->type(), _create_expr(args[0]), + _create_expr(args[1]), _create_expr(args[2])); + case CallOp::DETERMINANT: return _builtin_determinant( + args[0]->type(), _create_expr(args[0])); + case CallOp::TRANSPOSE: return _builtin_transpose( + args[0]->type(), _create_expr(args[0])); + case CallOp::INVERSE: return _builtin_inverse( + args[0]->type(), _create_expr(args[0])); + case CallOp::SYNCHRONIZE_BLOCK: + _builtin_synchronize_block(); + return nullptr; + case CallOp::ATOMIC_EXCHANGE: return _builtin_atomic_exchange( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::ATOMIC_COMPARE_EXCHANGE: return _builtin_atomic_compare_exchange( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1]), _create_expr(args[2])); + case CallOp::ATOMIC_FETCH_ADD: return _builtin_atomic_fetch_add( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::ATOMIC_FETCH_SUB: return _builtin_atomic_fetch_sub( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::ATOMIC_FETCH_AND: return _builtin_atomic_fetch_and( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::ATOMIC_FETCH_OR: return _builtin_atomic_fetch_or( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::ATOMIC_FETCH_XOR: return _builtin_atomic_fetch_xor( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::ATOMIC_FETCH_MIN: return _builtin_atomic_fetch_min( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::ATOMIC_FETCH_MAX: return _builtin_atomic_fetch_max( + args[0]->type(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::BUFFER_READ: return _builtin_buffer_read( + args[0]->type()->element(), _create_expr(args[0]), _create_expr(args[1])); + case CallOp::BUFFER_WRITE: + _builtin_buffer_write( + args[0]->type()->element(), _create_expr(args[0]), _create_expr(args[1]), + _builtin_static_cast(args[0]->type()->element(), args[2]->type(), _create_expr(args[2]))); + return nullptr; + case CallOp::TEXTURE_READ: return _builtin_texture_read( + ret_type, _create_expr(args[0]), args[1]->type(), _create_expr(args[1])); + case CallOp::TEXTURE_WRITE: + _builtin_texture_write( + args[2]->type(), _create_expr(args[0]), args[1]->type(), + _create_expr(args[1]), _create_expr(args[2])); + return nullptr; + case CallOp::BINDLESS_TEXTURE2D_SAMPLE: return _builtin_bindless_texture_sample2d( + _create_expr(args[0]), _create_expr(args[1]), _create_expr(args[2])); + case CallOp::BINDLESS_TEXTURE2D_SAMPLE_LEVEL: return _builtin_bindless_texture_sample2d_level( + _create_expr(args[0]), _create_expr(args[1]), _create_expr(args[2]), _create_expr(args[3])); + case CallOp::BINDLESS_TEXTURE2D_SAMPLE_GRAD: return _builtin_bindless_texture_sample2d_grad( + _create_expr(args[0]), _create_expr(args[1]), _create_expr(args[2]), + _create_expr(args[3]), _create_expr(args[4])); + case CallOp::BINDLESS_TEXTURE3D_SAMPLE: return _builtin_bindless_texture_sample3d( + _create_expr(args[0]), _create_expr(args[1]), _create_expr(args[2])); + case CallOp::BINDLESS_TEXTURE3D_SAMPLE_LEVEL: return _builtin_bindless_texture_sample3d_level( + _create_expr(args[0]), _create_expr(args[1]), _create_expr(args[2]), _create_expr(args[3])); + case CallOp::BINDLESS_TEXTURE3D_SAMPLE_GRAD: return _builtin_bindless_texture_sample3d_grad( + _create_expr(args[0]), _create_expr(args[1]), _create_expr(args[2]), + _create_expr(args[3]), _create_expr(args[4])); + case CallOp::BINDLESS_TEXTURE2D_READ: return _builtin_bindless_texture_read2d( + _create_expr(args[0]), _create_expr(args[1]), nullptr, _create_expr(args[2])); + case CallOp::BINDLESS_TEXTURE3D_READ: return _builtin_bindless_texture_read3d( + _create_expr(args[0]), _create_expr(args[1]), nullptr, _create_expr(args[2])); + case CallOp::BINDLESS_TEXTURE2D_READ_LEVEL: return _builtin_bindless_texture_read2d( + _create_expr(args[0]), _create_expr(args[1]), _create_expr(args[3]), _create_expr(args[2])); + case CallOp::BINDLESS_TEXTURE3D_READ_LEVEL: return _builtin_bindless_texture_read3d( + _create_expr(args[0]), _create_expr(args[1]), _create_expr(args[3]), _create_expr(args[2])); + case CallOp::BINDLESS_TEXTURE2D_SIZE: return _builtin_bindless_texture_size2d( + _create_expr(args[0]), _create_expr(args[1]), nullptr); + case CallOp::BINDLESS_TEXTURE3D_SIZE: return _builtin_bindless_texture_size3d( + _create_expr(args[0]), _create_expr(args[1]), nullptr); + case CallOp::BINDLESS_TEXTURE2D_SIZE_LEVEL: return _builtin_bindless_texture_size2d( + _create_expr(args[0]), _create_expr(args[1]), _create_expr(args[2])); + case CallOp::BINDLESS_TEXTURE3D_SIZE_LEVEL: return _builtin_bindless_texture_size3d( + _create_expr(args[0]), _create_expr(args[1]), _create_expr(args[2])); + case CallOp::BINDLESS_BUFFER_READ: return _builtin_bindless_buffer_read( + ret_type, _create_expr(args[0]), _create_expr(args[1]), _create_expr(args[2])); + case CallOp::MAKE_BOOL2: return _builtin_make_vector2_overloaded(ret_type, args); + case CallOp::MAKE_BOOL3: return _builtin_make_vector3_overloaded(ret_type, args); + case CallOp::MAKE_BOOL4: return _builtin_make_vector4_overloaded(ret_type, args); + case CallOp::MAKE_INT2: return _builtin_make_vector2_overloaded(ret_type, args); + case CallOp::MAKE_INT3: return _builtin_make_vector3_overloaded(ret_type, args); + case CallOp::MAKE_INT4: return _builtin_make_vector4_overloaded(ret_type, args); + case CallOp::MAKE_UINT2: return _builtin_make_vector2_overloaded(ret_type, args); + case CallOp::MAKE_UINT3: return _builtin_make_vector3_overloaded(ret_type, args); + case CallOp::MAKE_UINT4: return _builtin_make_vector4_overloaded(ret_type, args); + case CallOp::MAKE_FLOAT2: return _builtin_make_vector2_overloaded(ret_type, args); + case CallOp::MAKE_FLOAT3: return _builtin_make_vector3_overloaded(ret_type, args); + case CallOp::MAKE_FLOAT4: return _builtin_make_vector4_overloaded(ret_type, args); + case CallOp::MAKE_FLOAT2X2: return _builtin_make_matrix2_overloaded(args); + case CallOp::MAKE_FLOAT3X3: return _builtin_make_matrix3_overloaded(args); + case CallOp::MAKE_FLOAT4X4: return _builtin_make_matrix4_overloaded(args); + case CallOp::ASSUME: + _builtin_assume(_create_expr(args[0])); + return nullptr; + case CallOp::UNREACHABLE: + _builtin_unreachable(); + return nullptr; + case CallOp::RAY_TRACING_INSTANCE_TRANSFORM: return _builtin_instance_transform( + _create_expr(args[0]), _create_expr(args[1])); + case CallOp::RAY_TRACING_SET_INSTANCE_TRANSFORM: + _builtin_set_instance_transform( + _create_expr(args[0]), _create_expr(args[1]), _create_expr(args[2])); + return nullptr; + case CallOp::RAY_TRACING_SET_INSTANCE_VISIBILITY: + _builtin_set_instance_visibility( + _create_expr(args[0]), _create_expr(args[1]), _create_expr(args[2])); + return nullptr; + case CallOp::RAY_TRACING_TRACE_CLOSEST: return _builtin_trace_closest( + _create_expr(args[0]), _create_expr(args[1])); + case CallOp::RAY_TRACING_TRACE_ANY: return _builtin_trace_any( + _create_expr(args[0]), _create_expr(args[1])); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid built-in call."); +} + +// TODO: optimize memory allocation for coroutine frames +void LLVMCodegen::_builtin_synchronize_block() noexcept { + auto ctx = _current_context(); + auto b = ctx->builder.get(); + auto i8_type = ::llvm::Type::getInt8Ty(_context); + auto i1_type = ::llvm::Type::getInt1Ty(_context); + auto coro_state = b->CreateIntrinsic( + ::llvm::Intrinsic::coro_suspend, {}, + {::llvm::ConstantTokenNone::get(_context), + ::llvm::ConstantInt::get(i1_type, false)}, + nullptr, "synchronize.block.state"); + auto resume = ::llvm::BasicBlock::Create( + _context, "synchronize.block.resume", ctx->ir); + resume->moveAfter(b->GetInsertBlock()); + auto coro_switch = b->CreateSwitch( + coro_state, ctx->coro_suspend, 2u); + coro_switch->addCase( + ::llvm::ConstantInt::get(i8_type, 0), resume); + coro_switch->addCase( + ::llvm::ConstantInt::get(i8_type, 1), ctx->coro_cleanup); + b->SetInsertPoint(resume); +} + +[[nodiscard]] inline auto is_scalar_or_vector(const Type *t, Type::Tag tag) noexcept { + return t->tag() == tag || + (t->is_vector() && t->element()->tag() == tag); +} + +::llvm::Value *LLVMCodegen::_builtin_all(const Type *t, ::llvm::Value *v) noexcept { + auto b = _current_context()->builder.get(); + auto pred_type = ::llvm::FixedVectorType::get(b->getInt1Ty(), t->dimension()); + v = b->CreateLoad(_create_type(t), v, "all.load"); + v = b->CreateTrunc(v, pred_type, "all.pred"); + return _create_stack_variable(b->CreateAndReduce(v), "all.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_any(const Type *t, ::llvm::Value *v) noexcept { + auto b = _current_context()->builder.get(); + auto pred_type = ::llvm::FixedVectorType::get(b->getInt1Ty(), t->dimension()); + v = b->CreateLoad(_create_type(t), v, "any.load"); + v = b->CreateTrunc(v, pred_type, "any.pred"); + return _create_stack_variable(b->CreateOrReduce(v), "any.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_select(const Type *t_pred, const Type *t_value, + ::llvm::Value *pred, ::llvm::Value *v_true, ::llvm::Value *v_false) noexcept { + auto b = _current_context()->builder.get(); + auto pred_type = static_cast<::llvm::Type *>(b->getInt1Ty()); + if (t_pred->is_vector()) { pred_type = ::llvm::FixedVectorType::get(pred_type, t_pred->dimension()); } + auto pred_load = b->CreateLoad(_create_type(t_pred), pred, "sel.pred.load"); + auto bv = b->CreateTrunc(pred_load, pred_type, "sel.pred.bv"); + auto v_true_load = b->CreateLoad(_create_type(t_value), v_true, "sel.true"); + auto v_false_load = b->CreateLoad(_create_type(t_value), v_false, "sel.false"); + auto result = b->CreateSelect(bv, v_true_load, v_false_load, "sel"); + return _create_stack_variable(result, "sel.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_clamp(const Type *t, ::llvm::Value *v, ::llvm::Value *lo, ::llvm::Value *hi) noexcept { + return _builtin_min(t, _builtin_max(t, v, lo), hi); +} + +::llvm::Value *LLVMCodegen::_builtin_lerp(const Type *t, ::llvm::Value *a, ::llvm::Value *b, ::llvm::Value *x) noexcept { + auto s = _builtin_sub(t, b, a); + return _builtin_fma(t, x, s, a);// lerp(a, b, x) == x * (b - a) + a == fma(x, (b - a), a) +} + +::llvm::Value *LLVMCodegen::_builtin_step(const Type *t, ::llvm::Value *edge, ::llvm::Value *x) noexcept { + auto b = _current_context()->builder.get(); + auto zero = _builtin_static_cast( + t, Type::of(), _create_stack_variable(_literal(0.0f), "step.zero.addr")); + auto one = _builtin_static_cast( + t, Type::of(), _create_stack_variable(_literal(1.0f), "step.one.addr")); + if (t->is_scalar()) { return _builtin_select(Type::of(), t, _builtin_lt(t, x, edge), zero, one); } + if (t->dimension() == 2u) { return _builtin_select(Type::of(), t, _builtin_lt(t, x, edge), zero, one); } + if (t->dimension() == 3u) { return _builtin_select(Type::of(), t, _builtin_lt(t, x, edge), zero, one); } + if (t->dimension() == 4u) { return _builtin_select(Type::of(), t, _builtin_lt(t, x, edge), zero, one); } + LUISA_ERROR_WITH_LOCATION("Invalid type '{}' for step.", t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_saturate(const Type *t, ::llvm::Value *x) noexcept { + LUISA_ASSERT(t->tag() == Type::Tag::FLOAT, + "Invalid type '{}' for saturate", + t->description()); + static Callable saturate = [](Float x) noexcept { + return clamp(x, 0.f, 1.f); + }; + auto func = _create_function(saturate.function()); + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + x = b->CreateLoad(ir_type, x, "saturate.x"); + auto ret = b->CreateCall(func->getFunctionType(), func, x, "saturate.ret"); + return _create_stack_variable(ret, "saturate.ret.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_abs(const Type *t, ::llvm::Value *x) noexcept { + auto b = _current_context()->builder.get(); + if (is_scalar_or_vector(t, Type::Tag::UINT)) { return x; } + auto ir_type = _create_type(t); + if (is_scalar_or_vector(t, Type::Tag::INT)) { + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::abs, {ir_type}, + {b->CreateLoad(ir_type, x, "iabs.x")}, + nullptr, "iabs"); + return _create_stack_variable(m, "iabs.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::FLOAT)) { + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::fabs, {ir_type}, + {b->CreateLoad(ir_type, x, "fabs.x")}, + nullptr, "fabs"); + return _create_stack_variable(m, "fabs.addr"); + } + LUISA_ERROR_WITH_LOCATION("Invalid type '{}' for abs", t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_min(const Type *t, ::llvm::Value *x, ::llvm::Value *y) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + if (is_scalar_or_vector(t, Type::Tag::FLOAT)) { + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::minnum, {ir_type}, + {b->CreateLoad(ir_type, x, "fmin.x"), + b->CreateLoad(ir_type, y, "fmin.y")}, + nullptr, "fmin"); + return _create_stack_variable(m, "fmin.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::INT)) { + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::smin, {ir_type}, + {b->CreateLoad(ir_type, x, "imin.x"), + b->CreateLoad(ir_type, y, "imin.y")}, + nullptr, "imin"); + return _create_stack_variable(m, "imin.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::UINT)) { + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::umin, {ir_type}, + {b->CreateLoad(ir_type, x, "umin.x"), + b->CreateLoad(ir_type, y, "umin.y")}, + nullptr, "umin"); + return _create_stack_variable(m, "umin.addr"); + } + LUISA_ERROR_WITH_LOCATION("Invalid type '{}' for min.", t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_max(const Type *t, ::llvm::Value *x, ::llvm::Value *y) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + if (is_scalar_or_vector(t, Type::Tag::FLOAT)) { + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::maxnum, {ir_type}, + {b->CreateLoad(ir_type, x, "fmax.x"), + b->CreateLoad(ir_type, y, "fmax.y")}, + nullptr, "fmax"); + return _create_stack_variable(m, "fmax.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::INT)) { + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::smax, {ir_type}, + {b->CreateLoad(ir_type, x, "imax.x"), + b->CreateLoad(ir_type, y, "imax.y")}, + nullptr, "imax"); + return _create_stack_variable(m, "imax.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::UINT)) { + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::umax, {ir_type}, + {b->CreateLoad(ir_type, x, "umax.x"), + b->CreateLoad(ir_type, y, "umax.y")}, + nullptr, "umax"); + return _create_stack_variable(m, "umax.addr"); + } + LUISA_ERROR_WITH_LOCATION("Invalid type '{}' for max.", t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_clz(const Type *t, ::llvm::Value *p) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto x = b->CreateIntrinsic( + ::llvm::Intrinsic::ctlz, {ir_type}, + {b->CreateLoad(ir_type, p, "clz.x")}, + nullptr, "clz"); + return _create_stack_variable(x, "clz.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_ctz(const Type *t, ::llvm::Value *p) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto x = b->CreateIntrinsic( + ::llvm::Intrinsic::cttz, {ir_type}, + {b->CreateLoad(ir_type, p, "ctz.x")}, + nullptr, "ctz"); + return _create_stack_variable(x, "ctz.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_popcount(const Type *t, ::llvm::Value *p) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto x = b->CreateIntrinsic( + ::llvm::Intrinsic::ctpop, {ir_type}, + {b->CreateLoad(ir_type, p, "popcount.x")}, + nullptr, "popcount"); + return _create_stack_variable(x, "popcount.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_reverse(const Type *t, ::llvm::Value *p) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto x = b->CreateIntrinsic( + ::llvm::Intrinsic::bitreverse, {ir_type}, + {b->CreateLoad(ir_type, p, "reverse.x")}, + nullptr, "reverse"); + return _create_stack_variable(x, "reverse.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_fma(const Type *t, ::llvm::Value *pa, ::llvm::Value *pb, ::llvm::Value *pc) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::fma, {ir_type}, + {b->CreateLoad(ir_type, pa, "fma.a"), + b->CreateLoad(ir_type, pb, "fma.b"), + b->CreateLoad(ir_type, pc, "fma.c")}, + nullptr, "fma"); + return _create_stack_variable(m, "fma.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_exp(const Type *t, ::llvm::Value *v) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::exp, {ir_type}, + {b->CreateLoad(ir_type, v, "exp.x")}, + nullptr, "exp"); + return _create_stack_variable(m, "exp.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_exp2(const Type *t, ::llvm::Value *v) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::exp2, {ir_type}, + {b->CreateLoad(ir_type, v, "exp2.x")}, + nullptr, "exp2"); + return _create_stack_variable(m, "exp2.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_exp10(const Type *t, ::llvm::Value *v) noexcept { + auto ten = _builtin_static_cast( + t, Type::of(), + _create_stack_variable(_literal(10.f), "ten")); + return _builtin_pow(t, ten, v); +} + +::llvm::Value *LLVMCodegen::_builtin_log(const Type *t, ::llvm::Value *v) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::log, {ir_type}, + {b->CreateLoad(ir_type, v, "log.x")}, + nullptr, "log"); + return _create_stack_variable(m, "log.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_log2(const Type *t, ::llvm::Value *v) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::log2, {ir_type}, + {b->CreateLoad(ir_type, v, "log2.x")}, + nullptr, "log2"); + return _create_stack_variable(m, "log2.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_log10(const Type *t, ::llvm::Value *v) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::log10, {ir_type}, + {b->CreateLoad(ir_type, v, "log10.x")}, + nullptr, "log10"); + return _create_stack_variable(m, "log10.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_pow(const Type *t, ::llvm::Value *x, ::llvm::Value *y) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::pow, {ir_type}, + {b->CreateLoad(ir_type, x, "pow.x"), + b->CreateLoad(ir_type, y, "pow.y")}, + nullptr, "pow.ret"); + return _create_stack_variable(m, "pow.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_copysign(const Type *t, ::llvm::Value *x, ::llvm::Value *y) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::copysign, {ir_type}, + {b->CreateLoad(ir_type, x, "copysign.x"), + b->CreateLoad(ir_type, y, "copysign.y")}, + nullptr, "copysign"); + return _create_stack_variable(m, "copysign.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_faceforward(const Type *t, ::llvm::Value *n, ::llvm::Value *i, ::llvm::Value *nref) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto dot = b->CreateLoad( + _create_type(Type::of()), + _builtin_dot(t, nref, i), "faceforward.dot"); + auto pos_n = b->CreateLoad( + ir_type, n, "faceforward.pos_n"); + auto neg_n = b->CreateFNeg( + pos_n, "faceforward.neg_n"); + auto m = b->CreateSelect( + b->CreateFCmpOLT(dot, _literal(0.f)), + pos_n, neg_n, "faceforward.select"); + return _create_stack_variable(m, "faceforward.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_sin(const Type *t, ::llvm::Value *v) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::sin, {ir_type}, + {b->CreateLoad(ir_type, v, "sin.x")}, + nullptr, "sin"); + return _create_stack_variable(m, "sin.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_cos(const Type *t, ::llvm::Value *v) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::cos, {ir_type}, + {b->CreateLoad(ir_type, v, "cos.x")}, + nullptr, "cos"); + return _create_stack_variable(m, "cos.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_tan(const Type *t, ::llvm::Value *v) noexcept { + auto one = _create_stack_variable(_literal(1.f), "tan.one"); + if (t->is_vector()) { one = _builtin_static_cast(t, t->element(), one); } + return _builtin_mul(t, _builtin_sin(t, v), _builtin_div(t, one, _builtin_cos(t, v))); +} + +::llvm::Value *LLVMCodegen::_builtin_sqrt(const Type *t, ::llvm::Value *x) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::sqrt, {ir_type}, + {b->CreateLoad(ir_type, x, "sqrt.x")}, + nullptr, "sqrt"); + return _create_stack_variable(m, "sqrt.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_fract(const Type *t, ::llvm::Value *v) noexcept { + return _builtin_sub(t, v, _builtin_floor(t, v)); +} + +::llvm::Value *LLVMCodegen::_builtin_floor(const Type *t, ::llvm::Value *v) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::floor, {ir_type}, + {b->CreateLoad(ir_type, v, "floor.x")}, + nullptr, "floor"); + return _create_stack_variable(m, "floor.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_ceil(const Type *t, ::llvm::Value *v) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::ceil, {ir_type}, + {b->CreateLoad(ir_type, v, "ceil.x")}, + nullptr, "ceil"); + return _create_stack_variable(m, "ceil.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_trunc(const Type *t, ::llvm::Value *v) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::trunc, {ir_type}, + {b->CreateLoad(ir_type, v, "trunc.x")}, + nullptr, "trunc"); + return _create_stack_variable(m, "trunc.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_round(const Type *t, ::llvm::Value *v) noexcept { + auto ir_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto m = b->CreateIntrinsic( + ::llvm::Intrinsic::round, {ir_type}, + {b->CreateLoad(ir_type, v, "round.x")}, + nullptr, "round"); + return _create_stack_variable(m, "round.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_rsqrt(const Type *t, ::llvm::Value *x) noexcept { + auto s = _builtin_sqrt(t, x); + auto one = _builtin_static_cast( + t, Type::of(), + _create_stack_variable(_literal(1.f), "rsqrt.one")); + return _builtin_div(t, one, s); +} + +static constexpr auto atomic_operation_order = ::llvm::AtomicOrdering::Monotonic; + +::llvm::Value *LLVMCodegen::_builtin_atomic_exchange(const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_desired) noexcept { + auto b = _current_context()->builder.get(); + auto desired = b->CreateLoad( + _create_type(t), p_desired, "atomic.exchange.desired"); + auto old = b->CreateAtomicRMW( + ::llvm::AtomicRMWInst::Xchg, p_atomic, + desired, {}, atomic_operation_order); + old->setName("atomic.exchange.old"); + return _create_stack_variable(old, "atomic.exchange.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_atomic_compare_exchange(const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_expected, ::llvm::Value *p_desired) noexcept { + auto b = _current_context()->builder.get(); + auto expected = static_cast<::llvm::Value *>(b->CreateLoad( + _create_type(t), p_expected, "atomic.compare.exchange.expected")); + auto desired = static_cast<::llvm::Value *>(b->CreateLoad( + _create_type(t), p_desired, "atomic.compare.exchange.desired")); + if (t->tag() == Type::Tag::FLOAT) { + expected = b->CreateBitCast( + expected, b->getInt32Ty(), + "atomic.compare.exchange.expected.int"); + desired = b->CreateBitCast( + desired, b->getInt32Ty(), + "atomic.compare.exchange.desired.int"); + p_atomic = b->CreateBitOrPointerCast( + p_atomic, ::llvm::PointerType::get(b->getInt32Ty(), 0), + "atomic.compare.exchange.atomic.int"); + } + auto old_and_success = b->CreateAtomicCmpXchg( + p_atomic, expected, desired, {}, + atomic_operation_order, + atomic_operation_order); + old_and_success->setName("atomic.compare.exchange.old_and_success"); + auto old = b->CreateExtractValue( + old_and_success, 0, "atomic.compare.exchange.old"); + if (t->tag() == Type::Tag::FLOAT) { + old = b->CreateBitCast( + old, b->getFloatTy(), + "atomic.compare.exchange.old.float"); + } + return _create_stack_variable(old, "atomic.compare.exchange.addr"); +} + +// TODO: atomic_fetch_add for float seems not correct, hence it is manually implemented with atomic_compare_exchange +[[nodiscard]] inline ::llvm::Value *_atomic_fetch_add_float(::llvm::IRBuilder<> *builder, ::llvm::Value *ptr, ::llvm::Value *v_float) noexcept { +#define LUISA_COMPUTE_LLVM_USE_ATOMIC_FADD 0 +#if LUISA_COMPUTE_LLVM_USE_ATOMIC_FADD + auto old = builder->CreateAtomicRMW( + ::llvm::AtomicRMWInst::FAdd, ptr, + v_float, {}, atomic_operation_order); + old->setName("atomic.fetch.add.old"); + auto p_old = builder->CreateAlloca( + builder->getFloatTy(), nullptr, + "atomic.fetch.add.old.addr"); + p_old->setAlignment(::llvm::Align{16}); + builder->CreateStore(old, p_old); + return p_old; +#else + auto p_old = builder->CreateAlloca(builder->getFloatTy(), nullptr, "atomic.fetch.add.old.addr"); + p_old->setAlignment(::llvm::Align{16}); + auto v_int = builder->CreateBitCast(v_float, builder->getInt32Ty(), "atomic.fetch.add.value.int"); + auto ptr_int = builder->CreateBitOrPointerCast(ptr, ::llvm::PointerType::get(builder->getInt32Ty(), 0), "atomic.fetch.add.ptr.int"); + auto func = builder->GetInsertBlock()->getParent(); + auto loop = ::llvm::BasicBlock::Create(builder->getContext(), "atomic.fetch.add.loop", func); + auto loop_out = ::llvm::BasicBlock::Create(builder->getContext(), "atomic.fetch.add.loop.out", func); + loop->moveAfter(builder->GetInsertBlock()); + builder->CreateBr(loop); + builder->SetInsertPoint(loop); + auto expected = builder->CreateLoad(builder->getFloatTy(), ptr, "atomic.fetch.add.expected"); + builder->CreateStore(expected, p_old); + auto desired = builder->CreateFAdd(expected, v_float, "atomic.fetch.add.desired"); + auto desired_int = builder->CreateBitCast(desired, builder->getInt32Ty(), "atomic.fetch.add.desired.int"); + auto expected_int = builder->CreateBitCast(expected, builder->getInt32Ty(), "atomic.fetch.add.expected.int"); + auto old_and_success = builder->CreateAtomicCmpXchg( + ptr_int, expected_int, desired_int, {}, atomic_operation_order, atomic_operation_order); + old_and_success->setName("atomic.fetch.add.old_and_success"); + auto success = builder->CreateExtractValue(old_and_success, 1, "atomic.fetch.add.success"); + builder->CreateCondBr(success, loop_out, loop); + loop_out->moveAfter(builder->GetInsertBlock()); + builder->SetInsertPoint(loop_out); + return p_old; +#endif +#undef LUISA_COMPUTE_LLVM_USE_ATOMIC_FADD +} + +::llvm::Value *LLVMCodegen::_builtin_atomic_fetch_add(const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_value) noexcept { + auto b = _current_context()->builder.get(); + auto value = b->CreateLoad( + _create_type(t), p_value, "atomic.fetch.add.value"); + if (t->tag() == Type::Tag::FLOAT) { + return _atomic_fetch_add_float(b, p_atomic, value); + } + auto old = b->CreateAtomicRMW( + ::llvm::AtomicRMWInst::Add, p_atomic, + value, {}, atomic_operation_order); + old->setName("atomic.fetch.add.old"); + return _create_stack_variable(old, "atomic.fetch.add.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_atomic_fetch_sub(const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_value) noexcept { + auto b = _current_context()->builder.get(); + if (t->tag() == Type::Tag::FLOAT) { + return _builtin_atomic_fetch_add( + t, p_atomic, _builtin_unary_minus(t, p_value)); + } + auto value = b->CreateLoad( + _create_type(t), p_value, "atomic.fetch.sub.value"); + auto old = b->CreateAtomicRMW( + ::llvm::AtomicRMWInst::Sub, p_atomic, + value, {}, atomic_operation_order); + old->setName("atomic.fetch.sub.old"); + return _create_stack_variable(old, "atomic.fetch.sub.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_atomic_fetch_and(const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_value) noexcept { + auto b = _current_context()->builder.get(); + auto value = b->CreateLoad( + _create_type(t), p_value, "atomic.fetch.and.value"); + auto old = b->CreateAtomicRMW( + ::llvm::AtomicRMWInst::And, p_atomic, + value, {}, atomic_operation_order); + old->setName("atomic.fetch.and.old"); + return _create_stack_variable(old, "atomic.fetch.and.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_atomic_fetch_or(const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_value) noexcept { + auto b = _current_context()->builder.get(); + auto value = b->CreateLoad( + _create_type(t), p_value, "atomic.fetch.or.value"); + auto old = b->CreateAtomicRMW( + ::llvm::AtomicRMWInst::Or, p_atomic, + value, {}, atomic_operation_order); + old->setName("atomic.fetch.or.old"); + return _create_stack_variable(old, "atomic.fetch.or.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_atomic_fetch_xor(const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_value) noexcept { + auto b = _current_context()->builder.get(); + auto value = b->CreateLoad( + _create_type(t), p_value, "atomic.fetch.xor.value"); + auto old = b->CreateAtomicRMW( + ::llvm::AtomicRMWInst::Xor, p_atomic, + value, {}, atomic_operation_order); + old->setName("atomic.fetch.xor.old"); + return _create_stack_variable(old, "atomic.fetch.xor.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_atomic_fetch_min(const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_value) noexcept { + auto b = _current_context()->builder.get(); + auto value = static_cast<::llvm::Value *>(b->CreateLoad( + _create_type(t), p_value, "atomic.fetch.min.value")); + if (t->tag() == Type::Tag::UINT) { + auto old = b->CreateAtomicRMW( + ::llvm::AtomicRMWInst::UMin, p_atomic, + value, {}, atomic_operation_order); + old->setName("atomic.fetch.min.old"); + return _create_stack_variable(old, "atomic.fetch.min.addr"); + } + if (t->tag() == Type::Tag::FLOAT) { + auto elem_type = b->getInt32Ty(); + value = b->CreateBitCast( + value, elem_type, "atomic.fetch.min.value.int"); + p_atomic = b->CreateBitOrPointerCast( + p_atomic, ::llvm::PointerType::get(elem_type, 0), + "atomic.fetch.min.addr.int"); + auto old = static_cast<::llvm::Value *>( + b->CreateAtomicRMW( + ::llvm::AtomicRMWInst::Min, p_atomic, + value, {}, atomic_operation_order)); + old->setName("atomic.fetch.min.old.int"); + old = b->CreateBitCast( + old, b->getFloatTy(), "atomic.fetch.min.old"); + return _create_stack_variable(old, "atomic.fetch.min.addr"); + } + auto old = b->CreateAtomicRMW( + ::llvm::AtomicRMWInst::Min, p_atomic, + value, {}, atomic_operation_order); + old->setName("atomic.fetch.min.old"); + return _create_stack_variable(old, "atomic.fetch.min.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_atomic_fetch_max(const Type *t, ::llvm::Value *p_atomic, ::llvm::Value *p_value) noexcept { + auto b = _current_context()->builder.get(); + auto value = static_cast<::llvm::Value *>(b->CreateLoad( + _create_type(t), p_value, "atomic.fetch.max.value")); + if (t->tag() == Type::Tag::UINT) { + auto old = b->CreateAtomicRMW( + ::llvm::AtomicRMWInst::UMax, p_atomic, + value, {}, atomic_operation_order); + old->setName("atomic.fetch.max.old"); + return _create_stack_variable(old, "atomic.fetch.max.addr"); + } + if (t->tag() == Type::Tag::FLOAT) { + auto elem_type = b->getInt32Ty(); + value = b->CreateBitCast( + value, elem_type, "atomic.fetch.max.value.int"); + p_atomic = b->CreateBitOrPointerCast( + p_atomic, ::llvm::PointerType::get(elem_type, 0), + "atomic.fetch.max.addr.int"); + auto old = static_cast<::llvm::Value *>( + b->CreateAtomicRMW( + ::llvm::AtomicRMWInst::Max, p_atomic, + value, {}, atomic_operation_order)); + old->setName("atomic.fetch.max.old.int"); + old = b->CreateBitCast( + old, b->getFloatTy(), "atomic.fetch.max.old"); + return _create_stack_variable(old, "atomic.fetch.max.addr"); + } + auto old = b->CreateAtomicRMW( + ::llvm::AtomicRMWInst::Max, p_atomic, + value, {}, atomic_operation_order); + old->setName("atomic.fetch.max.old"); + return _create_stack_variable(old, "atomic.fetch.max.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_normalize(const Type *t, ::llvm::Value *v) noexcept { + auto norm = _builtin_rsqrt(Type::of(), _builtin_dot(t, v, v)); + auto norm_v = _builtin_static_cast(t, Type::of(), norm); + return _builtin_mul(t, v, norm_v); +} + +::llvm::Value *LLVMCodegen::_builtin_dot(const Type *t, ::llvm::Value *va, ::llvm::Value *vb) noexcept { + auto b = _current_context()->builder.get(); + auto type = _create_type(t); + va = b->CreateLoad(type, va, "dot.a"); + vb = b->CreateLoad(type, vb, "dot.b"); + auto mul = b->CreateFMul(va, vb, "dot.mul"); + auto sum = b->CreateFAddReduce(_literal(0.f), mul); + sum->setName("dot.sum"); + return _create_stack_variable(sum, "dot.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_add(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto lhs_v = b->CreateLoad(ir_type, lhs, "add.lhs"); + auto rhs_v = b->CreateLoad(ir_type, rhs, "add.rhs"); + if (is_scalar_or_vector(t, Type::Tag::INT)) { + return _create_stack_variable( + b->CreateNSWAdd(lhs_v, rhs_v, "add"), + "add.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::UINT)) { + return _create_stack_variable( + b->CreateAdd(lhs_v, rhs_v, "add"), + "add.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::FLOAT)) { + return _create_stack_variable( + b->CreateFAdd(lhs_v, rhs_v, "add"), + "add.addr"); + } + LUISA_ERROR_WITH_LOCATION( + "Invalid operand type '{}' for add.", + t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_sub(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto lhs_v = b->CreateLoad(ir_type, lhs, "sub.lhs"); + auto rhs_v = b->CreateLoad(ir_type, rhs, "sub.rhs"); + if (is_scalar_or_vector(t, Type::Tag::INT)) { + return _create_stack_variable( + b->CreateNSWSub(lhs_v, rhs_v, "sub"), + "sub.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::UINT)) { + return _create_stack_variable( + b->CreateSub(lhs_v, rhs_v, "sub"), + "sub.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::FLOAT)) { + return _create_stack_variable( + b->CreateFSub(lhs_v, rhs_v, "sub"), + "sub.addr"); + } + LUISA_ERROR_WITH_LOCATION( + "Invalid operand type '{}' for sub.", + t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_mul(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto lhs_v = b->CreateLoad(ir_type, lhs, "mul.lhs"); + auto rhs_v = b->CreateLoad(ir_type, rhs, "mul.rhs"); + if (is_scalar_or_vector(t, Type::Tag::INT)) { + return _create_stack_variable( + b->CreateNSWMul(lhs_v, rhs_v, "mul"), + "mul.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::UINT)) { + return _create_stack_variable( + b->CreateMul(lhs_v, rhs_v, "mul"), + "mul.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::FLOAT)) { + return _create_stack_variable( + b->CreateFMul(lhs_v, rhs_v, "mul"), + "mul.addr"); + } + LUISA_ERROR_WITH_LOCATION( + "Invalid operand type '{}' for mul.", + t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_div(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto lhs_v = b->CreateLoad(ir_type, lhs, "div.lhs"); + auto rhs_v = b->CreateLoad(ir_type, rhs, "div.rhs"); + if (is_scalar_or_vector(t, Type::Tag::INT)) { + return _create_stack_variable( + b->CreateSDiv(lhs_v, rhs_v, "div"), + "div.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::UINT)) { + return _create_stack_variable( + b->CreateUDiv(lhs_v, rhs_v, "div"), + "div.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::FLOAT)) { + return _create_stack_variable( + b->CreateFDiv(lhs_v, rhs_v, "div"), + "div.addr"); + } + LUISA_ERROR_WITH_LOCATION( + "Invalid operand type '{}' for div.", + t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_mod(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto lhs_v = b->CreateLoad(ir_type, lhs, "mod.lhs"); + auto rhs_v = b->CreateLoad(ir_type, rhs, "mod.rhs"); + if (is_scalar_or_vector(t, Type::Tag::INT)) { + return _create_stack_variable( + b->CreateSRem(lhs_v, rhs_v, "mod"), + "mod.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::UINT)) { + return _create_stack_variable( + b->CreateURem(lhs_v, rhs_v, "mod"), + "mod.addr"); + } + LUISA_ERROR_WITH_LOCATION( + "Invalid operand type '{}' for mod.", + t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_and(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + LUISA_ASSERT(is_scalar_or_vector(t, Type::Tag::INT) || + is_scalar_or_vector(t, Type::Tag::UINT) || + is_scalar_or_vector(t, Type::Tag::BOOL), + "Invalid type '{}' for and.", t->description()); + auto b = _current_context()->builder.get(); + auto result = b->CreateAnd( + b->CreateLoad(_create_type(t), lhs, "and.lhs"), + b->CreateLoad(_create_type(t), rhs, "and.rhs"), "and"); + return _create_stack_variable(result, "and.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_or(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + LUISA_ASSERT(is_scalar_or_vector(t, Type::Tag::INT) || + is_scalar_or_vector(t, Type::Tag::UINT) || + is_scalar_or_vector(t, Type::Tag::BOOL), + "Invalid type '{}' for or.", t->description()); + auto b = _current_context()->builder.get(); + auto result = b->CreateOr( + b->CreateLoad(_create_type(t), lhs, "or.lhs"), + b->CreateLoad(_create_type(t), rhs, "or.rhs"), "or"); + return _create_stack_variable(result, "or.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_xor(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + LUISA_ASSERT(is_scalar_or_vector(t, Type::Tag::INT) || + is_scalar_or_vector(t, Type::Tag::UINT) || + is_scalar_or_vector(t, Type::Tag::BOOL), + "Invalid type '{}' for xor.", t->description()); + auto b = _current_context()->builder.get(); + auto result = b->CreateXor( + b->CreateLoad(_create_type(t), lhs, "xor.lhs"), + b->CreateLoad(_create_type(t), rhs, "xor.rhs"), "xor"); + return _create_stack_variable(result, "xor.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_lt(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto lhs_v = b->CreateLoad(ir_type, lhs, "lt.lhs"); + auto rhs_v = b->CreateLoad(ir_type, rhs, "lt.rhs"); + if (is_scalar_or_vector(t, Type::Tag::INT)) { + return _create_stack_variable( + b->CreateICmpSLT(lhs_v, rhs_v, "lt"), + "lt.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::UINT)) { + return _create_stack_variable( + b->CreateICmpULT(lhs_v, rhs_v, "lt"), + "lt.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::FLOAT)) { + return _create_stack_variable( + b->CreateFCmpOLT(lhs_v, rhs_v, "lt"), + "lt.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::BOOL)) { + return _create_stack_variable( + b->CreateICmpULT(lhs_v, rhs_v, "lt"), + "lt.addr"); + } + LUISA_ERROR_WITH_LOCATION( + "Invalid operand type '{}' for lt.", + t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_le(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto lhs_v = b->CreateLoad(ir_type, lhs, "le.lhs"); + auto rhs_v = b->CreateLoad(ir_type, rhs, "le.rhs"); + if (is_scalar_or_vector(t, Type::Tag::INT)) { + return _create_stack_variable( + b->CreateICmpSLE(lhs_v, rhs_v, "le"), + "le.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::UINT)) { + return _create_stack_variable( + b->CreateICmpULE(lhs_v, rhs_v, "le"), + "le.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::FLOAT)) { + return _create_stack_variable( + b->CreateFCmpOLE(lhs_v, rhs_v, "le"), + "le.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::BOOL)) { + return _create_stack_variable( + b->CreateICmpULE(lhs_v, rhs_v, "le"), + "le.addr"); + } + LUISA_ERROR_WITH_LOCATION( + "Invalid operand type '{}' for le.", + t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_gt(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto lhs_v = b->CreateLoad(ir_type, lhs, "gt.lhs"); + auto rhs_v = b->CreateLoad(ir_type, rhs, "gt.rhs"); + if (is_scalar_or_vector(t, Type::Tag::INT)) { + return _create_stack_variable( + b->CreateICmpSGT(lhs_v, rhs_v, "gt"), + "gt.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::UINT)) { + return _create_stack_variable( + b->CreateICmpUGT(lhs_v, rhs_v, "gt"), + "gt.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::FLOAT)) { + return _create_stack_variable( + b->CreateFCmpOGT(lhs_v, rhs_v, "gt"), + "gt.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::BOOL)) { + return _create_stack_variable( + b->CreateICmpUGT(lhs_v, rhs_v, "gt"), + "gt.addr"); + } + LUISA_ERROR_WITH_LOCATION( + "Invalid operand type '{}' for gt.", + t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_ge(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto lhs_v = b->CreateLoad(ir_type, lhs, "ge.lhs"); + auto rhs_v = b->CreateLoad(ir_type, rhs, "ge.rhs"); + if (is_scalar_or_vector(t, Type::Tag::INT)) { + return _create_stack_variable( + b->CreateICmpSGE(lhs_v, rhs_v, "ge"), + "ge.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::UINT)) { + return _create_stack_variable( + b->CreateICmpUGE(lhs_v, rhs_v, "ge"), + "ge.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::FLOAT)) { + return _create_stack_variable( + b->CreateFCmpOGE(lhs_v, rhs_v, "ge"), + "ge.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::BOOL)) { + return _create_stack_variable( + b->CreateICmpUGE(lhs_v, rhs_v, "ge"), + "ge.addr"); + } + LUISA_ERROR_WITH_LOCATION( + "Invalid operand type '{}' for ge.", + t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_eq(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto lhs_v = b->CreateLoad(ir_type, lhs, "eq.lhs"); + auto rhs_v = b->CreateLoad(ir_type, rhs, "eq.rhs"); + if (is_scalar_or_vector(t, Type::Tag::INT)) { + return _create_stack_variable( + b->CreateICmpEQ(lhs_v, rhs_v, "eq"), + "eq.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::UINT)) { + return _create_stack_variable( + b->CreateICmpEQ(lhs_v, rhs_v, "eq"), + "eq.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::FLOAT)) { + return _create_stack_variable( + b->CreateFCmpOEQ(lhs_v, rhs_v, "eq"), + "eq.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::BOOL)) { + return _create_stack_variable( + b->CreateICmpEQ(lhs_v, rhs_v, "eq"), + "eq.addr"); + } + LUISA_ERROR_WITH_LOCATION( + "Invalid operand type '{}' for eq.", + t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_ne(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto lhs_v = b->CreateLoad(ir_type, lhs, "neq.lhs"); + auto rhs_v = b->CreateLoad(ir_type, rhs, "neq.rhs"); + if (is_scalar_or_vector(t, Type::Tag::INT)) { + return _create_stack_variable( + b->CreateICmpNE(lhs_v, rhs_v, "neq"), + "neq.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::UINT)) { + return _create_stack_variable( + b->CreateICmpNE(lhs_v, rhs_v, "neq"), + "neq.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::FLOAT)) { + return _create_stack_variable( + b->CreateFCmpONE(lhs_v, rhs_v, "neq"), + "neq.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::BOOL)) { + return _create_stack_variable( + b->CreateICmpNE(lhs_v, rhs_v, "neq"), + "neq.addr"); + } + LUISA_ERROR_WITH_LOCATION( + "Invalid operand type '{}' for neq.", + t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_shl(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto lhs_v = b->CreateLoad(ir_type, lhs, "shl.lhs"); + auto rhs_v = b->CreateLoad(ir_type, rhs, "shl.rhs"); + if (is_scalar_or_vector(t, Type::Tag::INT) || + is_scalar_or_vector(t, Type::Tag::UINT)) { + return _create_stack_variable( + b->CreateShl(lhs_v, rhs_v, "shl"), + "shl.addr"); + } + LUISA_ERROR_WITH_LOCATION( + "Invalid operand type '{}' for shl.", + t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_shr(const Type *t, ::llvm::Value *lhs, ::llvm::Value *rhs) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto lhs_v = b->CreateLoad(ir_type, lhs, "shr.lhs"); + auto rhs_v = b->CreateLoad(ir_type, rhs, "shr.rhs"); + if (is_scalar_or_vector(t, Type::Tag::INT)) { + return _create_stack_variable( + b->CreateAShr(lhs_v, rhs_v, "shr"), + "shr.addr"); + } + if (is_scalar_or_vector(t, Type::Tag::UINT)) { + return _create_stack_variable( + b->CreateLShr(lhs_v, rhs_v, "shr"), + "shr.addr"); + } + LUISA_ERROR_WITH_LOCATION( + "Invalid operand type '{}' for shr.", + t->description()); +} + +void LLVMCodegen::_builtin_assume(::llvm::Value *p) noexcept { + auto b = _current_context()->builder.get(); + auto pred = b->CreateICmpNE( + b->CreateLoad( + _create_type(Type::of()), p, "assume.load"), + _literal(false), "assume.pred"); + b->CreateAssumption(pred); +} + +void LLVMCodegen::_builtin_unreachable() noexcept { + _current_context()->builder->CreateUnreachable(); +} + +::llvm::Value *LLVMCodegen::_builtin_isinf(const Type *t, ::llvm::Value *p) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + if (t->is_scalar()) { + auto bits = b->CreateLoad( + b->getInt32Ty(), + _builtin_bitwise_cast(Type::of(), t, p), + "isinf.bits"); + auto is_inf = b->CreateLogicalOr( + b->CreateICmpEQ(bits, _literal(0x7f800000u), "isinf.pos"), + b->CreateICmpEQ(bits, _literal(0xff800000u), "isinf.neg"), + "isinf.pred"); + return _create_stack_variable(is_inf, "isinf.addr"); + } + switch (t->dimension()) { + case 2u: { + auto bits = b->CreateLoad( + _create_type(Type::of()), + _builtin_bitwise_cast(Type::of(), t, p), + "isinf.bits"); + auto is_inf = b->CreateLogicalOr( + b->CreateICmpEQ(bits, _literal(make_uint2(0x7f800000u)), "isinf.pos"), + b->CreateICmpEQ(bits, _literal(make_uint2(0xff800000u)), "isinf.neg"), + "isinf.pred"); + return _create_stack_variable(is_inf, "isinf.addr"); + } + case 3u: { + auto bits = b->CreateLoad( + _create_type(Type::of()), + _builtin_bitwise_cast(Type::of(), t, p), + "isinf.bits"); + auto is_inf = b->CreateLogicalOr( + b->CreateICmpEQ(bits, _literal(make_uint3(0x7f800000u)), "isinf.pos"), + b->CreateICmpEQ(bits, _literal(make_uint3(0xff800000u)), "isinf.neg"), + "isinf.pred"); + return _create_stack_variable(is_inf, "isinf.addr"); + } + case 4u: { + auto bits = b->CreateLoad( + _create_type(Type::of()), + _builtin_bitwise_cast(Type::of(), t, p), + "isinf.bits"); + auto is_inf = b->CreateLogicalOr( + b->CreateICmpEQ(bits, _literal(make_uint4(0x7f800000u)), "isinf.pos"), + b->CreateICmpEQ(bits, _literal(make_uint4(0xff800000u)), "isinf.neg"), + "isinf.pred"); + return _create_stack_variable(is_inf, "isinf.addr"); + } + default: break; + } + LUISA_ERROR_WITH_LOCATION( + "Invalid argument type '{}' for isinf.", + t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_isnan(const Type *t, ::llvm::Value *p) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + if (t->is_scalar()) { + auto bits = b->CreateLoad( + b->getInt32Ty(), + _builtin_bitwise_cast(Type::of(), t, p), + "isnan.bits"); + auto is_nan = b->CreateLogicalAnd( + b->CreateICmpEQ( + b->CreateAnd(bits, _literal(0x7f800000u), "isnan.exp"), + _literal(0x7f800000u), "isnan.exp.cmp"), + b->CreateICmpNE( + b->CreateAnd(bits, _literal(0x7fffffu), "isnan.mant"), + _literal(0u), "isnan.mant.cmp"), + "isnan.pred"); + return _create_stack_variable(is_nan, "isnan.addr"); + } + switch (t->dimension()) { + case 2u: { + auto bits = b->CreateLoad( + _create_type(Type::of()), + _builtin_bitwise_cast(Type::of(), t, p), + "isnan.bits"); + auto is_nan = b->CreateLogicalAnd( + b->CreateICmpEQ( + b->CreateAnd(bits, _literal(make_uint2(0x7f800000u)), "isnan.exp"), + _literal(make_uint2(0x7f800000u)), "isnan.exp.cmp"), + b->CreateICmpNE( + b->CreateAnd(bits, _literal(make_uint2(0x7fffffu)), "isnan.mant"), + _literal(make_uint2(0u)), "isnan.mant.cmp"), + "isnan.pred"); + return _create_stack_variable(is_nan, "isnan.addr"); + } + case 3u: { + auto bits = b->CreateLoad( + _create_type(Type::of()), + _builtin_bitwise_cast(Type::of(), t, p), + "isnan.bits"); + auto is_nan = b->CreateLogicalAnd( + b->CreateICmpEQ( + b->CreateAnd(bits, _literal(make_uint3(0x7f800000u)), "isnan.exp"), + _literal(make_uint3(0x7f800000u)), "isnan.exp.cmp"), + b->CreateICmpNE( + b->CreateAnd(bits, _literal(make_uint3(0x7fffffu)), "isnan.mant"), + _literal(make_uint3(0u)), "isnan.mant.cmp"), + "isnan.pred"); + return _create_stack_variable(is_nan, "isnan.addr"); + } + case 4u: { + auto bits = b->CreateLoad( + _create_type(Type::of()), + _builtin_bitwise_cast(Type::of(), t, p), + "isnan.bits"); + auto is_nan = b->CreateLogicalAnd( + b->CreateICmpEQ( + b->CreateAnd(bits, _literal(make_uint4(0x7f800000u)), "isnan.exp"), + _literal(make_uint4(0x7f800000u)), "isnan.exp.cmp"), + b->CreateICmpNE( + b->CreateAnd(bits, _literal(make_uint4(0x7fffffu)), "isnan.mant"), + _literal(make_uint4(0u)), "isnan.mant.cmp"), + "isnan.pred"); + return _create_stack_variable(is_nan, "isnan.addr"); + } + default: break; + } + LUISA_ERROR_WITH_LOCATION( + "Invalid argument type '{}' for isnan.", + t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_static_cast(const Type *t_dst, const Type *t_src, ::llvm::Value *p) noexcept { + switch (t_dst->tag()) { + case Type::Tag::BOOL: return _scalar_to_bool(t_src, p); + case Type::Tag::FLOAT: return _scalar_to_float(t_src, p); + case Type::Tag::INT: return _scalar_to_int(t_src, p); + case Type::Tag::UINT: return _scalar_to_uint(t_src, p); + case Type::Tag::VECTOR: + return t_src->is_vector() ? + _vector_to_vector(t_dst, t_src, p) : + _scalar_to_vector(t_dst, t_src, p); + case Type::Tag::MATRIX: + return t_src->is_matrix() ? + _matrix_to_matrix(t_dst, t_src, p) : + _scalar_to_matrix(t_dst, t_src, p); + default: break; + } + LUISA_ASSERT(*t_dst == *t_src, "Cannot convert '{}' to '{}'.", + t_src->description(), t_dst->description()); + return p; +} + +::llvm::Value *LLVMCodegen::_builtin_bitwise_cast(const Type *t_dst, const Type *t_src, ::llvm::Value *p) noexcept { + LUISA_ASSERT(t_dst->size() == t_src->size(), + "Invalid bitwise cast: {} to {}.", + t_src->description(), t_dst->description()); + auto b = _current_context()->builder.get(); + auto src_ir_type = _create_type(t_src); + auto dst_ir_type = _create_type(t_dst); + auto p_dst = b->CreateBitOrPointerCast(p, dst_ir_type->getPointerTo(), "bitcast.ptr"); + auto dst = b->CreateLoad(dst_ir_type, p_dst, "bitcast.dst"); + return _create_stack_variable(dst, "bitcast.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_unary_plus(const Type *t, ::llvm::Value *p) noexcept { + return p; +} + +::llvm::Value *LLVMCodegen::_builtin_unary_minus(const Type *t, ::llvm::Value *p) noexcept { + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + if (t->is_matrix()) { + std::array<::llvm::Value *, 4u> m{}; + for (auto i = 0u; i < t->dimension(); ++i) { + auto name = fmt::format("unary.minus.m{}.addr", i); + m[i] = b->CreateStructGEP( + ir_type, p, i, + ::llvm::StringRef{name.data(), name.size()}); + } + if (t->dimension() == 2u) { + return _make_float2x2( + b->CreateFNeg(m[0]), + b->CreateFNeg(m[1])); + } + if (t->dimension() == 3u) { + return _make_float3x3( + b->CreateFNeg(m[0]), + b->CreateFNeg(m[1]), + b->CreateFNeg(m[2])); + } + if (t->dimension() == 4u) { + return _make_float4x4( + b->CreateFNeg(m[0]), + b->CreateFNeg(m[1]), + b->CreateFNeg(m[2]), + b->CreateFNeg(m[3])); + } + LUISA_ERROR_WITH_LOCATION( + "Invalid matrix dimension '{}' for unary minus.", + t->dimension()); + } + auto x = b->CreateLoad(ir_type, p, "unary.minus.load"); + switch (auto tag = t->is_scalar() ? t->tag() : t->element()->tag()) { + case Type::Tag::BOOL: return _create_stack_variable( + b->CreateNot(x, "unary.minus"), + "unary.minus.addr"); + case Type::Tag::FLOAT: return _create_stack_variable( + b->CreateFNeg(x, "unary.minus"), + "unary.minus.addr"); + case Type::Tag::INT: + case Type::Tag::UINT: return _create_stack_variable( + b->CreateNeg(x, "unary.minus"), + "unary.minus.addr"); + default: break; + } + LUISA_ERROR_WITH_LOCATION( + "Invalid argument type '{}' for unary minus.", + t->description()); +} + +::llvm::Value *LLVMCodegen::_builtin_unary_not(const Type *t, ::llvm::Value *p) noexcept { + auto b = _current_context()->builder.get(); + p = t->is_scalar() ? _scalar_to_bool(t, p) : _vector_to_bool_vector(t, p); + auto i8_type = static_cast<::llvm::Type *>(::llvm::Type::getInt8Ty(_context)); + auto i8_vec_type = t->is_scalar() ? i8_type : ::llvm::FixedVectorType::get(i8_type, t->dimension()); + auto v = b->CreateLoad(i8_vec_type, p); + auto type = static_cast<::llvm::Type *>(b->getInt1Ty()); + if (t->is_vector()) { type = ::llvm::FixedVectorType::get(type, t->dimension()); } + auto nv = b->CreateNot(b->CreateTrunc(v, type), "unary.not"); + return _create_stack_variable(nv, "unary.not.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_unary_bit_not(const Type *t, ::llvm::Value *p) noexcept { + LUISA_ASSERT(t->tag() == Type::Tag::INT || t->tag() == Type::Tag::UINT || + (t->is_vector() && t->element()->tag() == Type::Tag::INT) || + (t->is_vector() && t->element()->tag() == Type::Tag::UINT), + "Invalid argument type '{}' for bitwise not.", + t->description()); + auto b = _current_context()->builder.get(); + auto ir_type = _create_type(t); + auto x = b->CreateLoad(ir_type, p, "unary.bitnot.load"); + return _create_stack_variable(b->CreateNot(x, "unary.bitnot"), "unary.bitnot.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_add_matrix_scalar(const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept { + LUISA_ASSERT(t_lhs->is_matrix() && t_rhs->is_scalar(), + "Invalid argument types '{}' and '{}' for matrix-scalar addition.", + t_lhs->description(), t_rhs->description()); + auto b = _current_context()->builder.get(); + auto lhs_type = _create_type(t_lhs); + auto col_type = Type::from(luisa::format("vector", t_lhs->dimension())); + auto rhs = _scalar_to_vector(col_type, t_rhs, p_rhs); + std::array<::llvm::Value *, 4u> m{}; + for (auto i = 0u; i < t_lhs->dimension(); ++i) { + auto name = fmt::format("add.lhs.m{}.addr", i); + auto col = b->CreateStructGEP( + lhs_type, p_lhs, i, + ::llvm::StringRef{name.data(), name.size()}); + m[i] = _builtin_add(col_type, col, rhs); + } + if (t_lhs->dimension() == 2u) { return _make_float2x2(m[0], m[1]); } + if (t_lhs->dimension() == 3u) { return _make_float3x3(m[0], m[1], m[2]); } + if (t_lhs->dimension() == 4u) { return _make_float4x4(m[0], m[1], m[2], m[3]); } + LUISA_ERROR_WITH_LOCATION( + "Invalid matrix dimension '{}' for matrix-scalar addition.", + t_lhs->dimension()); +} + +::llvm::Value *LLVMCodegen::_builtin_add_scalar_matrix(const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept { + return _builtin_add_matrix_scalar(t_rhs, t_lhs, p_rhs, p_lhs); +} + +::llvm::Value *LLVMCodegen::_builtin_add_matrix_matrix(const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept { + LUISA_ASSERT(t_lhs->is_matrix() && t_rhs->is_matrix() && + t_lhs->dimension() == t_rhs->dimension(), + "Invalid argument types '{}' and '{}' for matrix-matrix addition.", + t_lhs->description(), t_rhs->description()); + auto b = _current_context()->builder.get(); + auto matrix_type = _create_type(t_lhs); + auto col_type = Type::from(luisa::format("vector", t_lhs->dimension())); + std::array<::llvm::Value *, 4u> m{}; + for (auto i = 0u; i < t_lhs->dimension(); ++i) { + auto lhs_name = fmt::format("add.lhs.m{}.addr", i); + auto rhs_name = fmt::format("add.rhs.m{}.addr", i); + auto lhs = b->CreateStructGEP( + matrix_type, p_lhs, i, + ::llvm::StringRef{lhs_name.data(), lhs_name.size()}); + auto rhs = b->CreateStructGEP( + matrix_type, p_rhs, i, + ::llvm::StringRef{rhs_name.data(), rhs_name.size()}); + m[i] = _builtin_add(col_type, lhs, rhs); + } + if (t_lhs->dimension() == 2u) { return _make_float2x2(m[0], m[1]); } + if (t_lhs->dimension() == 3u) { return _make_float3x3(m[0], m[1], m[2]); } + if (t_lhs->dimension() == 4u) { return _make_float4x4(m[0], m[1], m[2], m[3]); } + LUISA_ERROR_WITH_LOCATION( + "Invalid matrix dimension '{}' for matrix-matrix addition.", + t_lhs->dimension()); +} + +::llvm::Value *LLVMCodegen::_builtin_sub_matrix_scalar(const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept { + LUISA_ASSERT(t_lhs->is_matrix() && t_rhs->is_scalar(), + "Invalid argument types '{}' and '{}' for matrix-scalar subtraction.", + t_lhs->description(), t_rhs->description()); + auto b = _current_context()->builder.get(); + auto lhs_type = _create_type(t_lhs); + auto col_type = Type::from(luisa::format("vector", t_lhs->dimension())); + auto rhs = _scalar_to_vector(col_type, t_rhs, p_rhs); + std::array<::llvm::Value *, 4u> m{}; + for (auto i = 0u; i < t_lhs->dimension(); ++i) { + auto name = fmt::format("sub.lhs.m{}.addr", i); + auto col = b->CreateStructGEP( + lhs_type, p_lhs, i, + ::llvm::StringRef{name.data(), name.size()}); + m[i] = _builtin_sub(col_type, col, rhs); + } + if (t_lhs->dimension() == 2u) { return _make_float2x2(m[0], m[1]); } + if (t_lhs->dimension() == 3u) { return _make_float3x3(m[0], m[1], m[2]); } + if (t_lhs->dimension() == 4u) { return _make_float4x4(m[0], m[1], m[2], m[3]); } + LUISA_ERROR_WITH_LOCATION( + "Invalid matrix dimension '{}' for matrix-scalar subtraction.", + t_lhs->dimension()); +} + +::llvm::Value *LLVMCodegen::_builtin_sub_scalar_matrix(const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept { + LUISA_ASSERT(t_lhs->is_scalar() && t_rhs->is_matrix(), + "Invalid argument types '{}' and '{}' for matrix-scalar subtraction.", + t_lhs->description(), t_rhs->description()); + auto b = _current_context()->builder.get(); + auto matrix_type = _create_type(t_rhs); + auto col_type = Type::from(luisa::format("vector", t_lhs->dimension())); + auto lhs = _scalar_to_vector(col_type, t_lhs, p_lhs); + std::array<::llvm::Value *, 4u> m{}; + for (auto i = 0u; i < t_lhs->dimension(); ++i) { + auto name = fmt::format("add.rhs.m{}.addr", i); + auto rhs_col = b->CreateStructGEP( + matrix_type, p_rhs, i, + ::llvm::StringRef{name.data(), name.size()}); + m[i] = _builtin_sub(col_type, lhs, rhs_col); + } + if (t_lhs->dimension() == 2u) { return _make_float2x2(m[0], m[1]); } + if (t_lhs->dimension() == 3u) { return _make_float3x3(m[0], m[1], m[2]); } + if (t_lhs->dimension() == 4u) { return _make_float4x4(m[0], m[1], m[2], m[3]); } + LUISA_ERROR_WITH_LOCATION( + "Invalid matrix dimension '{}' for matrix-scalar subtraction.", + t_lhs->dimension()); +} + +::llvm::Value *LLVMCodegen::_builtin_sub_matrix_matrix(const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept { + LUISA_ASSERT(t_lhs->is_matrix() && t_rhs->is_matrix() && + t_lhs->dimension() == t_rhs->dimension(), + "Invalid argument types '{}' and '{}' for matrix-matrix subtraction.", + t_lhs->description(), t_rhs->description()); + auto b = _current_context()->builder.get(); + auto matrix_type = _create_type(t_lhs); + auto col_type = Type::from(luisa::format("vector", t_lhs->dimension())); + std::array<::llvm::Value *, 4u> m{}; + for (auto i = 0u; i < t_lhs->dimension(); ++i) { + auto lhs_name = fmt::format("sub.lhs.m{}.addr", i); + auto rhs_name = fmt::format("sub.rhs.m{}.addr", i); + auto lhs = b->CreateStructGEP( + matrix_type, p_lhs, i, + ::llvm::StringRef{lhs_name.data(), lhs_name.size()}); + auto rhs = b->CreateStructGEP( + matrix_type, p_rhs, i, + ::llvm::StringRef{rhs_name.data(), rhs_name.size()}); + m[i] = _builtin_sub(col_type, lhs, rhs); + } + if (t_lhs->dimension() == 2u) { return _make_float2x2(m[0], m[1]); } + if (t_lhs->dimension() == 3u) { return _make_float3x3(m[0], m[1], m[2]); } + if (t_lhs->dimension() == 4u) { return _make_float4x4(m[0], m[1], m[2], m[3]); } + LUISA_ERROR_WITH_LOCATION( + "Invalid matrix dimension '{}' for matrix-matrix subtraction.", + t_lhs->dimension()); +} + +::llvm::Value *LLVMCodegen::_builtin_mul_matrix_scalar(const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept { + LUISA_ASSERT(t_lhs->is_matrix() && t_rhs->is_scalar(), + "Invalid argument types '{}' and '{}' for matrix-scalar multiplication.", + t_lhs->description(), t_rhs->description()); + auto b = _current_context()->builder.get(); + auto lhs_type = _create_type(t_lhs); + auto col_type = Type::from(luisa::format("vector", t_lhs->dimension())); + auto rhs = _scalar_to_vector(col_type, t_rhs, p_rhs); + std::array<::llvm::Value *, 4u> m{}; + for (auto i = 0u; i < t_lhs->dimension(); ++i) { + auto name = fmt::format("mul.lhs.m{}.addr", i); + auto col = b->CreateStructGEP( + lhs_type, p_lhs, i, + ::llvm::StringRef{name.data(), name.size()}); + m[i] = _builtin_mul(col_type, col, rhs); + } + if (t_lhs->dimension() == 2u) { return _make_float2x2(m[0], m[1]); } + if (t_lhs->dimension() == 3u) { return _make_float3x3(m[0], m[1], m[2]); } + if (t_lhs->dimension() == 4u) { return _make_float4x4(m[0], m[1], m[2], m[3]); } + LUISA_ERROR_WITH_LOCATION( + "Invalid matrix dimension '{}' for matrix-scalar multiplication.", + t_lhs->dimension()); +} + +::llvm::Value *LLVMCodegen::_builtin_mul_scalar_matrix(const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept { + return _builtin_mul_matrix_scalar(t_rhs, t_lhs, p_rhs, p_lhs); +} + +::llvm::Value *LLVMCodegen::_builtin_mul_matrix_matrix(const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept { + LUISA_ASSERT(t_lhs->is_matrix() && t_rhs->is_matrix() && + t_lhs->dimension() == t_rhs->dimension(), + "Invalid argument types '{}' and '{}' for matrix-matrix multiplication.", + t_lhs->description(), t_rhs->description()); + std::array<::llvm::Value *, 4u> m{}; + auto matrix_type = _create_type(t_lhs); + auto col_type = Type::from(luisa::format("vector", t_lhs->dimension())); + auto b = _current_context()->builder.get(); + for (auto i = 0u; i < t_lhs->dimension(); ++i) { + auto rhs_name = fmt::format("mul.rhs.m{}.addr", i); + auto rhs_col = b->CreateStructGEP( + matrix_type, p_rhs, i, + ::llvm::StringRef{rhs_name.data(), rhs_name.size()}); + m[i] = _builtin_mul_matrix_vector(t_lhs, col_type, p_lhs, rhs_col); + } + if (t_lhs->dimension() == 2u) { return _make_float2x2(m[0], m[1]); } + if (t_lhs->dimension() == 3u) { return _make_float3x3(m[0], m[1], m[2]); } + if (t_lhs->dimension() == 4u) { return _make_float4x4(m[0], m[1], m[2], m[3]); } + LUISA_ERROR_WITH_LOCATION( + "Invalid matrix dimension '{}' for matrix-matrix multiplication.", + t_lhs->dimension()); +} + +::llvm::Value *LLVMCodegen::_builtin_mul_matrix_vector(const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept { + LUISA_ASSERT(t_lhs->is_matrix() && t_rhs->is_vector() && + t_lhs->dimension() == t_rhs->dimension(), + "Invalid argument types '{}' and '{}' for matrix-vector multiplication.", + t_lhs->description(), t_rhs->description()); + std::array<::llvm::Value *, 4u> m{}; + auto b = _current_context()->builder.get(); + auto matrix_type = _create_type(t_lhs); + auto col_type = Type::from(luisa::format("vector", t_lhs->dimension())); + auto rhs = b->CreateLoad(_create_type(t_rhs), p_rhs, "mul.rhs"); + for (auto i = 0u; i < t_lhs->dimension(); ++i) { + auto col_name = fmt::format("mul.lhs.m{}.addr", i); + auto col = b->CreateStructGEP( + matrix_type, p_lhs, i, + ::llvm::StringRef{col_name.data(), col_name.size()}); + auto v_name = fmt::format("mul.rhs.v{}", i); + ::llvm::SmallVector masks(t_rhs->dimension(), static_cast(i)); + auto v = b->CreateShuffleVector(rhs, masks, ::llvm::StringRef{v_name.data(), v_name.size()}); + auto pv_name = fmt::format("mul.rhs.v{}.addr", i); + m[i] = _builtin_mul(col_type, col, _create_stack_variable(v, luisa::string_view{pv_name})); + } + if (t_lhs->dimension() == 2u) { return _builtin_add(col_type, m[0], m[1]); } + if (t_lhs->dimension() == 3u) { return _builtin_add(col_type, _builtin_add(col_type, m[0], m[1]), m[2]); } + if (t_lhs->dimension() == 4u) { return _builtin_add(col_type, _builtin_add(col_type, m[0], m[1]), _builtin_add(col_type, m[2], m[3])); } + LUISA_ERROR_WITH_LOCATION( + "Invalid matrix dimension '{}' for matrix-vector multiplication.", + t_lhs->dimension()); +} + +::llvm::Value *LLVMCodegen::_builtin_div_matrix_scalar(const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept { + LUISA_ASSERT(t_lhs->is_matrix() && t_rhs->is_scalar(), + "Invalid argument types '{}' and '{}' for matrix-scalar division.", + t_lhs->description(), t_rhs->description()); + auto b = _current_context()->builder.get(); + auto lhs_type = _create_type(t_lhs); + auto col_type = Type::from(luisa::format("vector", t_lhs->dimension())); + auto rhs = _scalar_to_vector(col_type, t_rhs, p_rhs); + std::array<::llvm::Value *, 4u> m{}; + for (auto i = 0u; i < t_lhs->dimension(); ++i) { + auto name = fmt::format("div.lhs.m{}.addr", i); + auto col = b->CreateStructGEP( + lhs_type, p_lhs, i, + ::llvm::StringRef{name.data(), name.size()}); + m[i] = _builtin_div(col_type, col, rhs); + } + if (t_lhs->dimension() == 2u) { return _make_float2x2(m[0], m[1]); } + if (t_lhs->dimension() == 3u) { return _make_float3x3(m[0], m[1], m[2]); } + if (t_lhs->dimension() == 4u) { return _make_float4x4(m[0], m[1], m[2], m[3]); } + LUISA_ERROR_WITH_LOCATION( + "Invalid matrix dimension '{}' for matrix-scalar division.", + t_lhs->dimension()); +} + +::llvm::Value *LLVMCodegen::_builtin_div_scalar_matrix(const Type *t_lhs, const Type *t_rhs, ::llvm::Value *p_lhs, ::llvm::Value *p_rhs) noexcept { + LUISA_ASSERT(t_lhs->is_scalar() && t_rhs->is_matrix(), + "Invalid argument types '{}' and '{}' for matrix-scalar division.", + t_lhs->description(), t_rhs->description()); + auto b = _current_context()->builder.get(); + auto matrix_type = _create_type(t_rhs); + auto col_type = Type::from(luisa::format("vector", t_lhs->dimension())); + auto lhs = _scalar_to_vector(col_type, t_lhs, p_lhs); + std::array<::llvm::Value *, 4u> m{}; + for (auto i = 0u; i < t_lhs->dimension(); ++i) { + auto name = fmt::format("add.rhs.m{}.addr", i); + auto rhs_col = b->CreateStructGEP( + matrix_type, p_rhs, i, + ::llvm::StringRef{name.data(), name.size()}); + m[i] = _builtin_div(col_type, lhs, rhs_col); + } + if (t_lhs->dimension() == 2u) { return _make_float2x2(m[0], m[1]); } + if (t_lhs->dimension() == 3u) { return _make_float3x3(m[0], m[1], m[2]); } + if (t_lhs->dimension() == 4u) { return _make_float4x4(m[0], m[1], m[2], m[3]); } + LUISA_ERROR_WITH_LOCATION( + "Invalid matrix dimension '{}' for matrix-scalar division.", + t_lhs->dimension()); +} + +::llvm::Value *LLVMCodegen::_builtin_buffer_read(const Type *t_value, ::llvm::Value *buffer, ::llvm::Value *p_index) noexcept { + auto b = _current_context()->builder.get(); + auto value_type = _create_type(t_value); + auto index = b->CreateLoad(_create_type(Type::of()), p_index, "buffer.read.index"); + auto ptr = b->CreateInBoundsGEP(value_type, buffer, index, "buffer.read.ptr"); + auto value = b->CreateLoad(value_type, ptr, "buffer.read"); + return _create_stack_variable(value, "buffer.read.addr"); +} + +void LLVMCodegen::_builtin_buffer_write(const Type *t_value, ::llvm::Value *buffer, ::llvm::Value *p_index, ::llvm::Value *p_value) noexcept { + auto b = _current_context()->builder.get(); + auto value_type = _create_type(t_value); + auto index = b->CreateLoad(_create_type(Type::of()), p_index, "buffer.write.index"); + auto ptr = b->CreateInBoundsGEP(value_type, buffer, index, "buffer.write.ptr"); + _create_assignment(t_value, t_value, ptr, p_value); +} + +::llvm::Value *LLVMCodegen::_builtin_texture_read(const Type *t, ::llvm::Value *texture, + const Type *t_coord, ::llvm::Value *p_coord) noexcept { + LUISA_ASSERT(t->is_vector() && t->dimension() == 4u, + "Invalid type '{}' for texture-read.", + t->description()); + // <4 x float> texture.read.Nd.type(i64 t0, i64 t1, i64 c0, i64 c2) + auto b = _current_context()->builder.get(); + auto coord = b->CreateLoad(_create_type(t_coord), p_coord, "texture.read.coord"); + auto coord_type = static_cast<::llvm::FixedVectorType *>(coord->getType()); + auto dim = coord_type->getNumElements() == 2u ? 2u : 3u; + auto func_name = luisa::format("texture.read.{}d.{}", dim, t->element()->description()); + auto func = _module->getFunction(::llvm::StringRef{func_name.data(), func_name.size()}); + auto i64_type = ::llvm::Type::getInt64Ty(_context); + auto f32v4_type = ::llvm::FixedVectorType::get(b->getFloatTy(), 4u); + if (func == nullptr) { + func = ::llvm::Function::Create( + ::llvm::FunctionType::get( + f32v4_type, + {i64_type, i64_type, i64_type, i64_type}, + false), + ::llvm::Function::ExternalLinkage, + ::llvm::StringRef{func_name.data(), func_name.size()}, + _module); + func->setNoSync(); + func->setWillReturn(); + func->setDoesNotThrow(); + func->setMustProgress(); + func->setDoesNotRecurse(); + func->setOnlyReadsMemory(); + func->setDoesNotFreeMemory(); + func->setOnlyAccessesInaccessibleMemOrArgMem(); + } + auto t0 = b->CreateExtractValue(texture, 0u, "texture.read.texture.t0"); + auto t1 = b->CreateExtractValue(texture, 1u, "texture.read.texture.t1"); + std::array shuffle{0, 1, 0, 0}; + if (dim == 3u) { shuffle[2] = 2; } + auto coord_vector = _create_stack_variable( + b->CreateShuffleVector( + coord, shuffle, "texture.read.coord.vector"), + "texture.read.coord.vector.addr"); + auto i64v2_type = ::llvm::FixedVectorType::get(i64_type, 2u); + p_coord = b->CreateBitOrPointerCast( + coord_vector, i64v2_type->getPointerTo(0), + "texture.read.coord.ulong2.addr"); + coord = b->CreateLoad(i64v2_type, p_coord, "texture.read.coord.ulong2"); + auto c0 = b->CreateExtractElement(coord, static_cast(0u), "texture.read.coord.c0"); + auto c1 = b->CreateExtractElement(coord, static_cast(1u), "texture.read.coord.c1"); + auto ret = static_cast<::llvm::Value *>(b->CreateCall(func, {t0, t1, c0, c1}, "texture.read.ret")); + if (t->element()->tag() != Type::Tag::FLOAT) { ret = b->CreateBitCast(ret, _create_type(t), "texture.read.ret.cast"); } + return _create_stack_variable(ret, "texture.read.addr"); +} + +void LLVMCodegen::_builtin_texture_write(const Type *t, ::llvm::Value *texture, const Type *t_coord, + ::llvm::Value *p_coord, ::llvm::Value *p_value) noexcept { + LUISA_ASSERT(t->is_vector() && t->dimension() == 4u, + "Invalid type '{}' for texture-write.", + t->description()); + // texture.write.Nd.type(i64 t0, i64 t1, i64 c0, i64 c1, i64 v0, i64 v1) + auto b = _current_context()->builder.get(); + auto coord = b->CreateLoad(_create_type(t_coord), p_coord, "texture.write.coord"); + auto coord_type = static_cast<::llvm::FixedVectorType *>(coord->getType()); + auto dim = coord_type->getNumElements() == 2u ? 2u : 3u; + auto func_name = luisa::format("texture.write.{}d.{}", dim, t->element()->description()); + auto func = _module->getFunction(::llvm::StringRef{func_name.data(), func_name.size()}); + auto i64_type = ::llvm::Type::getInt64Ty(_context); + if (func == nullptr) { + func = ::llvm::Function::Create( + ::llvm::FunctionType::get( + ::llvm::Type::getVoidTy(_context), + {i64_type, i64_type, i64_type, i64_type, i64_type, i64_type}, + false), + ::llvm::Function::ExternalLinkage, + ::llvm::StringRef{func_name.data(), func_name.size()}, + _module); + func->setNoSync(); + func->setWillReturn(); + func->setDoesNotThrow(); + func->setMustProgress(); + func->setDoesNotRecurse(); + func->setDoesNotFreeMemory(); + func->setOnlyAccessesInaccessibleMemOrArgMem(); + } + auto t0 = b->CreateExtractValue(texture, 0u, "texture.write.texture.t0"); + auto t1 = b->CreateExtractValue(texture, 1u, "texture.write.texture.t1"); + std::array shuffle{0, 1, 0, 0}; + if (dim == 3u) { shuffle[2] = 2; } + auto i64v2_type = ::llvm::FixedVectorType::get(i64_type, 2u); + auto coord_vector = _create_stack_variable( + b->CreateShuffleVector( + coord, shuffle, "texture.write.coord.vector"), + "texture.write.coord.vector.addr"); + p_coord = b->CreateBitOrPointerCast( + coord_vector, i64v2_type->getPointerTo(0), + "texture.write.coord.ulong2.addr"); + coord = b->CreateLoad(i64v2_type, p_coord, "texture.write.coord.ulong2"); + auto c0 = b->CreateExtractElement(coord, static_cast(0u), "texture.write.coord.c0"); + auto c1 = b->CreateExtractElement(coord, static_cast(1u), "texture.write.coord.c1"); + p_value = b->CreateBitOrPointerCast( + p_value, i64v2_type->getPointerTo(0), "texture.write.value.ulong2.addr"); + auto value = b->CreateLoad(i64v2_type, p_value, "texture.write.value.ulong"); + auto v0 = b->CreateExtractElement(value, static_cast(0u), "texture.write.value.v0"); + auto v1 = b->CreateExtractElement(value, static_cast(1u), "texture.write.value.v1"); + b->CreateCall(func->getFunctionType(), func, {t0, t1, c0, c1, v0, v1}); +} + +::llvm::Value *LLVMCodegen::_builtin_trace_closest(::llvm::Value *accel, ::llvm::Value *p_ray) noexcept { + // <4 x float> trace_closest(i64 accel, i64 r0, i64 r1, i64 r2, i64 r3) + auto b = _current_context()->builder.get(); + auto i64_type = ::llvm::Type::getInt64Ty(_context); + auto func_name = "accel.trace.closest"; + auto func = _module->getFunction(func_name); + accel = b->CreateExtractValue(accel, 0u, "trace.closest.accel.handle"); + if (func == nullptr) { + func = ::llvm::Function::Create( + ::llvm::FunctionType::get( + ::llvm::FixedVectorType::get(b->getFloatTy(), 4u), + {accel->getType(), i64_type, i64_type, i64_type, i64_type}, + false), + ::llvm::Function::ExternalLinkage, func_name, _module); + func->setNoSync(); + func->setWillReturn(); + func->setDoesNotThrow(); + func->setMustProgress(); + func->setSpeculatable(); + func->setOnlyReadsMemory(); + func->setDoesNotFreeMemory(); + func->setOnlyAccessesInaccessibleMemOrArgMem(); + } + auto ray_struct_type = ::llvm::FixedVectorType::get(i64_type, 4u); + p_ray = b->CreateBitOrPointerCast(p_ray, ray_struct_type->getPointerTo(0), + "trace.closest.ray.struct.addr"); + auto ray = b->CreateLoad(ray_struct_type, p_ray, "trace.closest.ray.struct"); + auto r0 = b->CreateExtractElement(ray, static_cast(0u), "trace.closest.ray.r0"); + auto r1 = b->CreateExtractElement(ray, static_cast(1u), "trace.closest.ray.r1"); + auto r2 = b->CreateExtractElement(ray, static_cast(2u), "trace.closest.ray.r2"); + auto r3 = b->CreateExtractElement(ray, static_cast(3u), "trace.closest.ray.r3"); + auto ret = b->CreateCall( + func->getFunctionType(), func, {accel, r0, r1, r2, r3}, + "accel.trace.closest.struct"); + auto inst = b->CreateBitCast(b->CreateExtractElement(ret, static_cast(0u)), b->getInt32Ty(), "trace.closest.hit.inst"); + auto prim = b->CreateBitCast(b->CreateExtractElement(ret, static_cast(1u)), b->getInt32Ty(), "trace.closest.hit.prim"); + auto bary = b->CreateShuffleVector(ret, {2, 3}, "trace.closest.hit.bary"); + auto hit = static_cast<::llvm::Value *>(::llvm::UndefValue::get(_create_type(Type::of()))); + hit = b->CreateInsertValue(hit, inst, 0u); + hit = b->CreateInsertValue(hit, prim, 1u); + hit = b->CreateInsertValue(hit, bary, 2u, "trace_closest.hit"); + return _create_stack_variable(hit, "trace_closest.hit.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_trace_any(::llvm::Value *accel, ::llvm::Value *p_ray) noexcept { + // i8 trace_closest(i64 accel, i64 r0, i64 r1, i64 r2, i64 r3) + auto b = _current_context()->builder.get(); + auto i64_type = ::llvm::Type::getInt64Ty(_context); + auto func_name = "accel.trace.any"; + auto func = _module->getFunction(func_name); + accel = b->CreateExtractValue(accel, 0u, "trace_closest.accel.handle"); + if (func == nullptr) { + func = ::llvm::Function::Create( + ::llvm::FunctionType::get( + ::llvm::Type::getInt8Ty(_context), + {accel->getType(), i64_type, i64_type, i64_type, i64_type}, + false), + ::llvm::Function::ExternalLinkage, func_name, _module); + func->setNoSync(); + func->setWillReturn(); + func->setDoesNotThrow(); + func->setMustProgress(); + func->setSpeculatable(); + func->setOnlyReadsMemory(); + func->setDoesNotFreeMemory(); + func->setOnlyAccessesInaccessibleMemOrArgMem(); + } + auto ray_struct_type = ::llvm::FixedVectorType::get(i64_type, 4u); + p_ray = b->CreateBitOrPointerCast( + p_ray, ray_struct_type->getPointerTo(0), + "trace_any.ray.struct.addr"); + auto ray = b->CreateLoad(ray_struct_type, p_ray, "trace_any.ray.struct"); + auto r0 = b->CreateExtractElement(ray, static_cast(0u), "trace_any.ray.r0"); + auto r1 = b->CreateExtractElement(ray, static_cast(1u), "trace_any.ray.r1"); + auto r2 = b->CreateExtractElement(ray, static_cast(2u), "trace_any.ray.r2"); + auto r3 = b->CreateExtractElement(ray, static_cast(3u), "trace_any.ray.r3"); + auto ret = b->CreateCall( + func->getFunctionType(), func, {accel, r0, r1, r2, r3}, + "accel.trace.any.ret"); + auto hit = b->CreateTrunc(ret, b->getInt1Ty()); + hit->setName("accel.trace.any.hit"); + return _create_stack_variable(hit, "accel.trace.any.hit.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_length_squared(const Type *t, ::llvm::Value *v) noexcept { + return _builtin_dot(t, v, v); +} + +::llvm::Value *LLVMCodegen::_builtin_cross(const Type *t, ::llvm::Value *va, ::llvm::Value *vb) noexcept { + LUISA_ASSERT(t->is_vector() && t->dimension() == 3u, + "Invalid argument types '{}' and '{}' for cross product.", + t->description(), t->description()); + auto b = _current_context()->builder.get(); + auto type = _create_type(t); + va = b->CreateLoad(type, va, "cross.a"); + vb = b->CreateLoad(type, vb, "cross.b"); + auto a_x = b->CreateExtractElement(va, static_cast(0u), "cross.a.x"); + auto a_y = b->CreateExtractElement(va, static_cast(1u), "cross.a.y"); + auto a_z = b->CreateExtractElement(va, static_cast(2u), "cross.a.z"); + auto b_x = b->CreateExtractElement(vb, static_cast(0u), "cross.b.x"); + auto b_y = b->CreateExtractElement(vb, static_cast(1u), "cross.b.y"); + auto b_z = b->CreateExtractElement(vb, static_cast(2u), "cross.b.z"); + auto x = b->CreateFSub(b->CreateFMul(a_y, b_z), b->CreateFMul(a_z, b_y), "cross.x"); + auto y = b->CreateFSub(b->CreateFMul(a_z, b_x), b->CreateFMul(a_x, b_z), "cross.y"); + auto z = b->CreateFSub(b->CreateFMul(a_x, b_y), b->CreateFMul(a_y, b_x), "cross.z"); + return _make_float3(_create_stack_variable(x, "cross.x.addr"), + _create_stack_variable(y, "cross.y.addr"), + _create_stack_variable(z, "cross.z.addr")); +} + +::llvm::Value *LLVMCodegen::_builtin_make_vector2_overloaded(const Type *t_vec, luisa::span args) noexcept { + if (args.size() == 1u) { + return _builtin_static_cast(t_vec, args[0]->type(), _create_expr(args[0])); + } + if (args.size() == 2u) { + LUISA_ASSERT(args[0]->type()->is_scalar() && args[1]->type()->is_scalar(), + "Invalid argument types '{}' and '{}' for make-vector2.", + args[0]->type()->description(), args[1]->type()->description()); + return _make_float2(_builtin_static_cast(t_vec->element(), args[0]->type(), _create_expr(args[0])), + _builtin_static_cast(t_vec->element(), args[1]->type(), _create_expr(args[1]))); + } + LUISA_ERROR_WITH_LOCATION("Invalid number of arguments '{}' for make-vector2.", args.size()); +} + +::llvm::Value *LLVMCodegen::_builtin_make_vector3_overloaded(const Type *t_vec, luisa::span args) noexcept { + if (args.size() == 1u) { + return _builtin_static_cast(t_vec, args[0]->type(), _create_expr(args[0])); + } + auto b = _current_context()->builder.get(); + if (args.size() == 2u) { + if (args[0]->type()->is_scalar()) { + LUISA_ASSERT(args[1]->type()->is_vector() && args[1]->type()->dimension() == 2u, + "Invalid argument types ('{}', '{}') to make {}.", + args[0]->type()->description(), args[1]->type()->description(), + t_vec->description()); + auto yz = b->CreateLoad( + _create_type(args[1]->type()), _create_expr(args[1]), "make.vector3.yz"); + auto y = _create_stack_variable( + b->CreateExtractElement(yz, static_cast(0u), "make.vector3.x"), + "make.vector3.y.addr"); + auto z = _create_stack_variable( + b->CreateExtractElement(yz, static_cast(1u), "make.vector3.y"), + "make.vector3.z.addr"); + auto x = _builtin_static_cast(t_vec->element(), args[0]->type(), _create_expr(args[0])); + return _make_float3(x, y, z); + } + LUISA_ASSERT(args[0]->type()->is_vector() && args[0]->type()->dimension() == 2u && + args[1]->type()->is_scalar(), + "Invalid argument types ('{}', '{}') to make {}.", + args[0]->type()->description(), args[1]->type()->description(), + t_vec->description()); + auto xy = b->CreateLoad( + _create_type(args[0]->type()), _create_expr(args[0]), "make.vector3.xy"); + auto x = _create_stack_variable( + b->CreateExtractElement(xy, static_cast(0u), "make.vector3.x"), + "make.vector3.x.addr"); + auto y = _create_stack_variable( + b->CreateExtractElement(xy, static_cast(1u), "make.vector3.y"), + "make.vector3.y.addr"); + auto z = _builtin_static_cast(t_vec->element(), args[1]->type(), _create_expr(args[1])); + return _make_float3(x, y, z); + } + if (args.size() == 3u) { + LUISA_ASSERT(args[0]->type()->is_scalar() && args[1]->type()->is_scalar() && + args[2]->type()->is_scalar(), + "Invalid argument types ('{}', '{}', '{}') for make-vector3.", + args[0]->type()->description(), args[1]->type()->description(), + args[2]->type()->description()); + return _make_float3(_builtin_static_cast(t_vec->element(), args[0]->type(), _create_expr(args[0])), + _builtin_static_cast(t_vec->element(), args[1]->type(), _create_expr(args[1])), + _builtin_static_cast(t_vec->element(), args[2]->type(), _create_expr(args[2]))); + } + LUISA_ERROR_WITH_LOCATION("Invalid number of arguments '{}' for make-vector3.", args.size()); +} + +::llvm::Value *LLVMCodegen::_builtin_make_vector4_overloaded(const Type *t_vec, luisa::span args) noexcept { + if (args.size() == 1u) { + return _builtin_static_cast(t_vec, args[0]->type(), _create_expr(args[0])); + } + auto b = _current_context()->builder.get(); + if (args.size() == 2u) { + // (x, yzw) + if (args[0]->type()->is_scalar()) { + LUISA_ASSERT(args[1]->type()->is_vector() && args[1]->type()->dimension() == 3u, + "Invalid argument types ('{}', '{}') to make {}.", + args[0]->type()->description(), args[1]->type()->description(), + t_vec->description()); + auto yzw = b->CreateLoad( + _create_type(args[1]->type()), _create_expr(args[1]), "make.vector4.yzw"); + auto y = _create_stack_variable( + b->CreateExtractElement(yzw, static_cast(0u), "make.vector4.x"), + "make.vector4.y.addr"); + auto z = _create_stack_variable( + b->CreateExtractElement(yzw, static_cast(1u), "make.vector4.y"), + "make.vector4.z.addr"); + auto w = _create_stack_variable( + b->CreateExtractElement(yzw, static_cast(2u), "make.vector4.z"), + "make.vector4.w.addr"); + auto x = _builtin_static_cast(t_vec->element(), args[0]->type(), _create_expr(args[0])); + return _make_float4(x, y, z, w); + } + LUISA_ASSERT(args[0]->type()->is_vector(), + "Invalid argument types ('{}', '{}') to make {}.", + args[0]->type()->description(), args[1]->type()->description(), + t_vec->description()); + // (xyz, w) + if (args[0]->type()->dimension() == 3u) { + LUISA_ASSERT(args[1]->type()->is_scalar(), + "Invalid argument types ('{}', '{}') to make {}.", + args[0]->type()->description(), args[1]->type()->description(), + t_vec->description()); + auto xyz = b->CreateLoad( + _create_type(args[0]->type()), _create_expr(args[0]), "make.vector4.xyz"); + auto x = _create_stack_variable( + b->CreateExtractElement(xyz, static_cast(0u), "make.vector4.x"), + "make.vector4.x.addr"); + auto y = _create_stack_variable( + b->CreateExtractElement(xyz, static_cast(1u), "make.vector4.y"), + "make.vector4.y.addr"); + auto z = _create_stack_variable( + b->CreateExtractElement(xyz, static_cast(2u), "make.vector4.z"), + "make.vector4.z.addr"); + auto w = _builtin_static_cast(t_vec->element(), args[1]->type(), _create_expr(args[1])); + return _make_float4(x, y, z, w); + } + // (xy, zw) + LUISA_ASSERT(args[0]->type()->dimension() == 2u && + args[1]->type()->is_vector() && args[1]->type()->dimension() == 2u, + "Invalid argument types ('{}', '{}') to make {}.", + args[0]->type()->description(), args[1]->type()->description(), + t_vec->description()); + auto xy = b->CreateLoad( + _create_type(args[0]->type()), _create_expr(args[0]), "make.vector4.xy"); + auto zw = b->CreateLoad( + _create_type(args[1]->type()), _create_expr(args[1]), "make.vector4.zw"); + auto x = _create_stack_variable( + b->CreateExtractElement(xy, static_cast(0u), "make.vector4.x"), + "make.vector4.x.addr"); + auto y = _create_stack_variable( + b->CreateExtractElement(xy, static_cast(1u), "make.vector4.y"), + "make.vector4.y.addr"); + auto z = _create_stack_variable( + b->CreateExtractElement(zw, static_cast(0u), "make.vector4.z"), + "make.vector4.z.addr"); + auto w = _create_stack_variable( + b->CreateExtractElement(zw, static_cast(1u), "make.vector4.w"), + "make.vector4.w.addr"); + return _make_float4(x, y, z, w); + } + if (args.size() == 3u) { + ::llvm::SmallVector<::llvm::Value *, 4u> v; + for (auto arg : args) { + if (arg->type()->is_scalar()) { + v.emplace_back(_builtin_static_cast( + t_vec->element(), arg->type(), _create_expr(arg))); + } else { + LUISA_ASSERT(arg->type()->is_vector() && arg->type()->dimension() == 2u, + "Invalid argument types ('{}', '{}', '{}') to make {}.", + args[0]->type()->description(), args[1]->type()->description(), + args[2]->type()->description(), t_vec->description()); + auto vec = b->CreateLoad( + _create_type(arg->type()), _create_expr(arg), "make.vector4.v"); + v.emplace_back(_create_stack_variable( + b->CreateExtractElement(vec, static_cast(0u), "make.vector4.v.x"), + "make.vector4.v.x.addr")); + v.emplace_back(_create_stack_variable( + b->CreateExtractElement(vec, static_cast(1u), "make.vector4.v.y"), + "make.vector4.v.y.addr")); + } + } + LUISA_ASSERT(v.size() == 4u, "Invalid argument types ('{}', '{}', '{}') to make {}.", + args[0]->type()->description(), args[1]->type()->description(), + args[2]->type()->description(), t_vec->description()); + return _make_float4(v[0], v[1], v[2], v[3]); + } + LUISA_ASSERT(args.size() == 4u && + args[0]->type()->is_scalar() && args[1]->type()->is_scalar() && + args[2]->type()->is_scalar() && args[3]->type()->is_scalar(), + "Invalid argument types ('{}', '{}', '{}', '{}') to make {}.", + args[0]->type()->description(), args[1]->type()->description(), + args[2]->type()->description(), args[3]->type()->description(), + t_vec->description()); + return _make_float4(_builtin_static_cast(t_vec->element(), args[0]->type(), _create_expr(args[0])), + _builtin_static_cast(t_vec->element(), args[1]->type(), _create_expr(args[1])), + _builtin_static_cast(t_vec->element(), args[2]->type(), _create_expr(args[2])), + _builtin_static_cast(t_vec->element(), args[3]->type(), _create_expr(args[3]))); +} + +::llvm::Value *LLVMCodegen::_builtin_make_matrix2_overloaded(luisa::span args) noexcept { + if (args.size() == 1u) { + return _builtin_static_cast(Type::of(), args[0]->type(), _create_expr(args[0])); + } + if (args.size() == 2u) { + LUISA_ASSERT(args[0]->type()->is_vector() && args[0]->type()->dimension() == 2u && + args[1]->type()->is_vector() && args[1]->type()->dimension() == 2u, + "Invalid argument types '{}' and '{}' for float2x2 constructor.", + args[0]->type()->description(), args[1]->type()->description()); + return _make_float2x2(_create_expr(args[0]), _create_expr(args[1])); + } + LUISA_ASSERT(args.size() == 4u, + "Invalid number of arguments '{}' for float2x2 constructor.", + args.size()); + LUISA_ASSERT(args[0]->type()->is_scalar() && args[1]->type()->is_scalar() && + args[2]->type()->is_scalar() && args[3]->type()->is_scalar(), + "Invalid argument types ('{}', '{}', '{}', '{}') for float2x2 constructor.", + args[0]->type()->description(), args[1]->type()->description(), + args[2]->type()->description(), args[3]->type()->description()); + auto c0 = _make_float2(_builtin_static_cast(Type::of(), args[0]->type(), _create_expr(args[0])), + _builtin_static_cast(Type::of(), args[1]->type(), _create_expr(args[1]))); + auto c1 = _make_float2(_builtin_static_cast(Type::of(), args[2]->type(), _create_expr(args[2])), + _builtin_static_cast(Type::of(), args[3]->type(), _create_expr(args[3]))); + return _make_float2x2(c0, c1); +} + +::llvm::Value *LLVMCodegen::_builtin_make_matrix3_overloaded(luisa::span args) noexcept { + if (args.size() == 1u) { + return _builtin_static_cast(Type::of(), args[0]->type(), _create_expr(args[0])); + } + if (args.size() == 3u) { + LUISA_ASSERT(args[0]->type()->is_vector() && args[0]->type()->dimension() == 3u && + args[1]->type()->is_vector() && args[1]->type()->dimension() == 3u && + args[2]->type()->is_vector() && args[2]->type()->dimension() == 3u, + "Invalid argument types '{}' and '{}' for float3x3 constructor.", + args[0]->type()->description(), args[1]->type()->description(), + args[2]->type()->description()); + return _make_float3x3(_create_expr(args[0]), _create_expr(args[1]), _create_expr(args[2])); + } + LUISA_ASSERT(args.size() == 9u, + "Invalid number of arguments '{}' for float3x3 constructor.", + args.size()); + LUISA_ASSERT(args[0]->type()->is_scalar() && args[1]->type()->is_scalar() && + args[2]->type()->is_scalar() && args[3]->type()->is_scalar() && + args[4]->type()->is_scalar() && args[5]->type()->is_scalar() && + args[6]->type()->is_scalar() && args[7]->type()->is_scalar() && + args[8]->type()->is_scalar(), + "Invalid argument types ('{}', '{}', '{}', '{}', '{}', " + "'{}', '{}', '{}', '{}') for float3x3 constructor.", + args[0]->type()->description(), args[1]->type()->description(), + args[2]->type()->description(), args[3]->type()->description(), + args[4]->type()->description(), args[5]->type()->description(), + args[6]->type()->description(), args[7]->type()->description(), + args[8]->type()->description()); + auto c0 = _make_float3(_builtin_static_cast(Type::of(), args[0]->type(), _create_expr(args[0])), + _builtin_static_cast(Type::of(), args[1]->type(), _create_expr(args[1])), + _builtin_static_cast(Type::of(), args[2]->type(), _create_expr(args[2]))); + auto c1 = _make_float3(_builtin_static_cast(Type::of(), args[3]->type(), _create_expr(args[3])), + _builtin_static_cast(Type::of(), args[4]->type(), _create_expr(args[4])), + _builtin_static_cast(Type::of(), args[5]->type(), _create_expr(args[5]))); + auto c2 = _make_float3(_builtin_static_cast(Type::of(), args[6]->type(), _create_expr(args[6])), + _builtin_static_cast(Type::of(), args[7]->type(), _create_expr(args[7])), + _builtin_static_cast(Type::of(), args[8]->type(), _create_expr(args[8]))); + return _make_float3x3(c0, c1, c2); +} + +::llvm::Value *LLVMCodegen::_builtin_make_matrix4_overloaded(luisa::span args) noexcept { + if (args.size() == 1u) { + return _builtin_static_cast(Type::of(), args[0]->type(), _create_expr(args[0])); + } + if (args.size() == 4u) { + LUISA_ASSERT(args[0]->type()->is_vector() && args[0]->type()->dimension() == 4u && + args[1]->type()->is_vector() && args[1]->type()->dimension() == 4u && + args[2]->type()->is_vector() && args[2]->type()->dimension() == 4u && + args[3]->type()->is_vector() && args[3]->type()->dimension() == 4u, + "Invalid argument types '{}' and '{}' for float4x4 constructor.", + args[0]->type()->description(), args[1]->type()->description(), + args[2]->type()->description(), args[3]->type()->description()); + return _make_float4x4(_create_expr(args[0]), _create_expr(args[1]), + _create_expr(args[2]), _create_expr(args[3])); + } + LUISA_ASSERT(args.size() == 16u, + "Invalid number of arguments '{}' for float4x4 constructor.", + args.size()); + LUISA_ASSERT(args[0]->type()->is_scalar() && args[1]->type()->is_scalar() && + args[2]->type()->is_scalar() && args[3]->type()->is_scalar() && + args[4]->type()->is_scalar() && args[5]->type()->is_scalar() && + args[6]->type()->is_scalar() && args[7]->type()->is_scalar() && + args[8]->type()->is_scalar() && args[9]->type()->is_scalar() && + args[10]->type()->is_scalar() && args[11]->type()->is_scalar() && + args[12]->type()->is_scalar() && args[13]->type()->is_scalar() && + args[14]->type()->is_scalar() && args[15]->type()->is_scalar(), + "Invalid argument types ('{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', " + "'{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}') for float4x4 constructor.", + args[0]->type()->description(), args[1]->type()->description(), + args[2]->type()->description(), args[3]->type()->description(), + args[4]->type()->description(), args[5]->type()->description(), + args[6]->type()->description(), args[7]->type()->description(), + args[8]->type()->description(), args[9]->type()->description(), + args[10]->type()->description(), args[11]->type()->description(), + args[12]->type()->description(), args[13]->type()->description(), + args[14]->type()->description(), args[15]->type()->description()); + auto c0 = _make_float4(_builtin_static_cast(Type::of(), args[0]->type(), _create_expr(args[0])), + _builtin_static_cast(Type::of(), args[1]->type(), _create_expr(args[1])), + _builtin_static_cast(Type::of(), args[2]->type(), _create_expr(args[2])), + _builtin_static_cast(Type::of(), args[3]->type(), _create_expr(args[3]))); + auto c1 = _make_float4(_builtin_static_cast(Type::of(), args[4]->type(), _create_expr(args[4])), + _builtin_static_cast(Type::of(), args[5]->type(), _create_expr(args[5])), + _builtin_static_cast(Type::of(), args[6]->type(), _create_expr(args[6])), + _builtin_static_cast(Type::of(), args[7]->type(), _create_expr(args[7]))); + auto c2 = _make_float4(_builtin_static_cast(Type::of(), args[8]->type(), _create_expr(args[8])), + _builtin_static_cast(Type::of(), args[9]->type(), _create_expr(args[9])), + _builtin_static_cast(Type::of(), args[10]->type(), _create_expr(args[10])), + _builtin_static_cast(Type::of(), args[11]->type(), _create_expr(args[11]))); + auto c3 = _make_float4(_builtin_static_cast(Type::of(), args[12]->type(), _create_expr(args[12])), + _builtin_static_cast(Type::of(), args[13]->type(), _create_expr(args[13])), + _builtin_static_cast(Type::of(), args[14]->type(), _create_expr(args[14])), + _builtin_static_cast(Type::of(), args[15]->type(), _create_expr(args[15]))); + return _make_float4x4(c0, c1, c2, c3); +} + +::llvm::Value *LLVMCodegen::_builtin_bindless_texture_size2d(::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_level) noexcept { + auto b = _current_context()->builder.get(); + auto level = p_level == nullptr ? _literal(0u) : b->CreateLoad(b->getInt32Ty(), p_level, "bindless.texture.size.2d.level"); + auto index = b->CreateLoad(b->getInt32Ty(), p_index, "bindless.texture.size.2d.index"); + auto pp_texture = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(1)}, "bindless.texture.size.2d.texture.ptr.ptr"); + auto p_texture = b->CreateLoad(_bindless_texture_type()->getPointerTo(), pp_texture, "bindless.texture.size.2d.texture.ptr"); + auto texture = b->CreateLoad(_bindless_texture_type(), p_texture, "bindless.texture.size.2d.texture"); + auto texture_size = b->CreateExtractValue(texture, 1u, "bindless.texture.size.2d.texture.size.i16"); + texture_size = b->CreateShuffleVector(texture_size, {0, 1}, "bindless.texture.size.2d.texture.i16.v2"); + texture_size = b->CreateZExt(texture_size, _create_type(Type::of()), "bindless.texture.size.2d.texture.size.i32"); + auto shift = b->CreateVectorSplat(2u, level, "bindless.texture.size.2d.shift"); + texture_size = b->CreateLShr(texture_size, shift, "bindless.texture.size.2d.shifted"); + auto one = b->CreateVectorSplat(2u, _literal(1u), "bindless.texture.size.2d.one"); + texture_size = b->CreateMaxNum(texture_size, one, "bindless.texture.size.2d.max"); + return _create_stack_variable(texture_size, "bindless.texture.size.2d.size.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_bindless_texture_size3d(::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_level) noexcept { + auto b = _current_context()->builder.get(); + auto level = p_level == nullptr ? _literal(0u) : b->CreateLoad(b->getInt32Ty(), p_level, "bindless.texture.size.3d.level"); + auto index = b->CreateLoad(b->getInt32Ty(), p_index, "bindless.texture.size.3d.index"); + auto pp_texture = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(2)}, "bindless.texture.size.3d.texture.ptr.ptr"); + auto p_texture = b->CreateLoad(_bindless_texture_type()->getPointerTo(), pp_texture, "bindless.texture.size.3d.texture.ptr"); + auto texture = b->CreateLoad(_bindless_texture_type(), p_texture, "bindless.texture.size.3d.texture"); + auto texture_size = b->CreateExtractValue(texture, 1u, "bindless.texture.size.3d.texture.size.i16"); + texture_size = b->CreateZExt(texture_size, _create_type(Type::of()), "bindless.texture.size.3d.texture.size.i32"); + auto shift = b->CreateVectorSplat(4u, level, "bindless.texture.size.3d.shift"); + texture_size = b->CreateLShr(texture_size, shift, "bindless.texture.size.3d.shifted"); + auto one = b->CreateVectorSplat(4u, _literal(1u), "bindless.texture.size.3d.one"); + texture_size = b->CreateMaxNum(texture_size, one, "bindless.texture.size.3d.max"); + return _create_stack_variable(texture_size, "bindless.texture.size.3d.size.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_bindless_buffer_read( + const Type *t, ::llvm::Value *p_items, ::llvm::Value *p_buffer_index, ::llvm::Value *p_elem_index) noexcept { + auto elem_type = _create_type(t); + auto b = _current_context()->builder.get(); + auto buffer_index = b->CreateLoad(b->getInt32Ty(), p_buffer_index, "bindless.buffer.read.buffer.index"); + auto buffer_ptr = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {buffer_index, _literal(0u)}, "bindless.buffer.read.buffer.ptr"); + auto typeless_buffer = b->CreateLoad(b->getInt8PtrTy(), buffer_ptr, "bindless.buffer.read.buffer.typeless"); + auto buffer = b->CreateBitOrPointerCast(typeless_buffer, elem_type->getPointerTo(), "bindless.buffer.read.buffer"); + auto elem_index = b->CreateLoad(b->getInt32Ty(), p_elem_index, "bindless.buffer.read.elem.index"); + auto elem_ptr = b->CreateInBoundsGEP(elem_type, buffer, elem_index, "bindless.buffer.read.elem.ptr"); + auto elem = b->CreateLoad(elem_type, elem_ptr, "bindless.buffer.read.elem"); + return _create_stack_variable(elem, "bindless.buffer.read.elem.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_bindless_texture_read2d( + ::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_level, ::llvm::Value *p_uv) noexcept { + auto b = _current_context()->builder.get(); + auto level = p_level == nullptr ? _literal(0u) : b->CreateLoad(b->getInt32Ty(), p_level, "bindless.texture.read.2d.level"); + auto index = b->CreateLoad(b->getInt32Ty(), p_index, "bindless.texture.read.2d.index"); + auto pp_texture = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(1)}, "bindless.texture.read.2d.texture.ptr.ptr"); + auto p_texture = b->CreateLoad(_bindless_texture_type()->getPointerTo(), pp_texture, "bindless.texture.read.2d.texture.ptr"); + auto coord = b->CreateLoad(_create_type(Type::of()), p_uv, "bindless.texture.read.2d.uv"); + auto coord_x = b->CreateExtractElement(coord, _literal(0u), "bindless.texture.read.2d.uv.x"); + auto coord_y = b->CreateExtractElement(coord, _literal(1u), "bindless.texture.read.2d.uv.y"); + auto func = _module->getFunction("bindless.texture.2d.read"); + if (func == nullptr) { + func = ::llvm::Function::Create( + ::llvm::FunctionType::get( + ::llvm::FixedVectorType::get(b->getFloatTy(), 4u), + {_bindless_texture_type()->getPointerTo(), b->getInt32Ty(), b->getInt32Ty(), b->getInt32Ty()}, false), + ::llvm::Function::ExternalLinkage, "bindless.texture.2d.read", _module); + } + auto ret = b->CreateCall(func, {p_texture, level, coord_x, coord_y}, "bindless.texture.read.2d.ret"); + return _create_stack_variable(ret, "bindless.texture.read.2d.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_bindless_texture_read3d( + ::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_level, ::llvm::Value *p_uvw) noexcept { + auto b = _current_context()->builder.get(); + auto level = p_level == nullptr ? _literal(0u) : b->CreateLoad(b->getInt32Ty(), p_level, "bindless.texture.read.3d.level"); + auto index = b->CreateLoad(b->getInt32Ty(), p_index, "bindless.texture.read.3d.index"); + auto pp_texture = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(2)}, "bindless.texture.read.3d.texture.ptr.ptr"); + auto p_texture = b->CreateLoad(_bindless_texture_type()->getPointerTo(), pp_texture, "bindless.texture.read.3d.texture.ptr"); + auto coord = b->CreateLoad(_create_type(Type::of()), p_uvw, "bindless.texture.read.3d.uvw"); + auto coord_x = b->CreateExtractElement(coord, _literal(0u), "bindless.texture.read.3d.uvw.x"); + auto coord_y = b->CreateExtractElement(coord, _literal(1u), "bindless.texture.read.3d.uvw.y"); + auto coord_z = b->CreateExtractElement(coord, _literal(2u), "bindless.texture.read.3d.uvw.z"); + auto func = _module->getFunction("bindless.texture.3d.read"); + if (func == nullptr) { + func = ::llvm::Function::Create( + ::llvm::FunctionType::get( + ::llvm::FixedVectorType::get(b->getFloatTy(), 4u), + {_bindless_texture_type()->getPointerTo(), b->getInt32Ty(), b->getInt32Ty(), b->getInt32Ty(), b->getInt32Ty()}, false), + ::llvm::Function::ExternalLinkage, "bindless.texture.3d.read", _module); + } + auto ret = b->CreateCall(func, {p_texture, level, coord_x, coord_y, coord_z}, "bindless.texture.read.3d.ret"); + return _create_stack_variable(ret, "bindless.texture.read.3d.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_bindless_texture_sample2d(::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_uv) noexcept { + auto b = _current_context()->builder.get(); + auto index = b->CreateLoad(b->getInt32Ty(), p_index, "bindless.texture.sample.2d.index"); + auto pp_texture = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(1)}, "bindless.texture.sample.2d.texture.ptr.ptr"); + auto p_texture = b->CreateLoad(_bindless_texture_type()->getPointerTo(), pp_texture, "bindless.texture.sample.2d.texture.ptr"); + auto p_sampler = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(3)}, "bindless.texture.sample.2d.sampler.ptr"); + auto sampler = b->CreateLoad(b->getInt32Ty(), p_sampler, "bindless.texture.sample.2d.sampler"); + auto uv = b->CreateLoad(_create_type(Type::of()), p_uv, "bindless.texture.sample.2d.uv"); + auto uv_x = b->CreateExtractElement(uv, _literal(0u), "bindless.texture.sample.2d.uv.x"); + auto uv_y = b->CreateExtractElement(uv, _literal(1u), "bindless.texture.sample.2d.uv.y"); + auto func = _module->getFunction("bindless.texture.2d.sample"); + if (func == nullptr) { + func = ::llvm::Function::Create( + ::llvm::FunctionType::get( + ::llvm::FixedVectorType::get(b->getFloatTy(), 4u), + {_bindless_texture_type()->getPointerTo(), b->getInt32Ty(), + b->getFloatTy(), b->getFloatTy()}, + false), + ::llvm::Function::ExternalLinkage, "bindless.texture.2d.sample", _module); + } + auto ret = b->CreateCall(func, {p_texture, sampler, uv_x, uv_y}, "bindless.texture.sample.2d.ret"); + return _create_stack_variable(ret, "bindless.texture.sample.2d.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_bindless_texture_sample3d(::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_uvw) noexcept { + auto b = _current_context()->builder.get(); + auto index = b->CreateLoad(b->getInt32Ty(), p_index, "bindless.texture.sample.3d.index"); + auto pp_texture = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(2)}, "bindless.texture.sample.3d.texture.ptr.ptr"); + auto p_texture = b->CreateLoad(_bindless_texture_type()->getPointerTo(), pp_texture, "bindless.texture.sample.3d.texture.ptr"); + auto p_sampler = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(4)}, "bindless.texture.sample.3d.sampler.ptr"); + auto sampler = b->CreateLoad(b->getInt32Ty(), p_sampler, "bindless.texture.sample.3d.sampler"); + auto uvw = b->CreateLoad(_create_type(Type::of()), p_uvw, "bindless.texture.sample.3d.uvw"); + auto uvw_x = b->CreateExtractElement(uvw, _literal(0u), "bindless.texture.sample.3d.uvw.x"); + auto uvw_y = b->CreateExtractElement(uvw, _literal(1u), "bindless.texture.sample.3d.uvw.y"); + auto uvw_z = b->CreateExtractElement(uvw, _literal(2u), "bindless.texture.sample.3d.uvw.z"); + auto func = _module->getFunction("bindless.texture.3d.sample"); + if (func == nullptr) { + func = ::llvm::Function::Create( + ::llvm::FunctionType::get( + ::llvm::FixedVectorType::get(b->getFloatTy(), 4u), + {_bindless_texture_type()->getPointerTo(), b->getInt32Ty(), + b->getFloatTy(), b->getFloatTy(), b->getFloatTy()}, + false), + ::llvm::Function::ExternalLinkage, "bindless.texture.3d.sample", _module); + } + auto ret = b->CreateCall(func, {p_texture, sampler, uvw_x, uvw_y, uvw_z}, "bindless.texture.sample.3d.ret"); + return _create_stack_variable(ret, "bindless.texture.sample.3d.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_bindless_texture_sample2d_level(::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_uv, ::llvm::Value *p_lod) noexcept { + auto b = _current_context()->builder.get(); + auto index = b->CreateLoad(b->getInt32Ty(), p_index, "bindless.texture.sample.2d.level.index"); + auto pp_texture = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(1)}, "bindless.texture.sample.2d.level.texture.ptr.ptr"); + auto p_texture = b->CreateLoad(_bindless_texture_type()->getPointerTo(), pp_texture, "bindless.texture.sample.2d.level.texture.ptr"); + auto p_sampler = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(3)}, "bindless.texture.sample.2d.level.sampler.ptr"); + auto sampler = b->CreateLoad(b->getInt32Ty(), p_sampler, "bindless.texture.sample.2d.level.sampler"); + auto uv = b->CreateLoad(_create_type(Type::of()), p_uv, "bindless.texture.sample.2d.level.uv"); + auto uv_x = b->CreateExtractElement(uv, _literal(0u), "bindless.texture.sample.2d.level.uv.x"); + auto uv_y = b->CreateExtractElement(uv, _literal(1u), "bindless.texture.sample.2d.level.uv.y"); + auto lod = b->CreateLoad(b->getFloatTy(), p_lod, "bindless.texture.sample.2d.level.lod"); + auto func = _module->getFunction("bindless.texture.2d.sample.level"); + if (func == nullptr) { + func = ::llvm::Function::Create( + ::llvm::FunctionType::get( + ::llvm::FixedVectorType::get(b->getFloatTy(), 4u), + {_bindless_texture_type()->getPointerTo(), b->getInt32Ty(), + b->getFloatTy(), b->getFloatTy(), b->getFloatTy()}, + false), + ::llvm::Function::ExternalLinkage, "bindless.texture.2d.sample.level", _module); + } + auto ret = b->CreateCall(func, {p_texture, sampler, uv_x, uv_y, lod}, "bindless.texture.sample.2d.level.ret"); + return _create_stack_variable(ret, "bindless.texture.sample.2d.level.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_bindless_texture_sample3d_level(::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_uvw, ::llvm::Value *p_lod) noexcept { + auto b = _current_context()->builder.get(); + auto index = b->CreateLoad(b->getInt32Ty(), p_index, "bindless.texture.sample.3d.level.index"); + auto pp_texture = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(2)}, "bindless.texture.sample.3d.level.texture.ptr.ptr"); + auto p_texture = b->CreateLoad(_bindless_texture_type()->getPointerTo(), pp_texture, "bindless.texture.sample.3d.level.texture.ptr"); + auto p_sampler = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(4)}, "bindless.texture.sample.3d.level.sampler.ptr"); + auto sampler = b->CreateLoad(b->getInt32Ty(), p_sampler, "bindless.texture.sample.3d.level.sampler"); + auto uvw = b->CreateLoad(_create_type(Type::of()), p_uvw, "bindless.texture.sample.3d.level.uvw"); + auto uvw_x = b->CreateExtractElement(uvw, _literal(0u), "bindless.texture.sample.3d.level.uvw.x"); + auto uvw_y = b->CreateExtractElement(uvw, _literal(1u), "bindless.texture.sample.3d.level.uvw.y"); + auto uvw_z = b->CreateExtractElement(uvw, _literal(2u), "bindless.texture.sample.3d.level.uvw.z"); + auto lod = b->CreateLoad(b->getFloatTy(), p_lod, "bindless.texture.sample.3d.level.lod"); + auto func = _module->getFunction("bindless.texture.3d.sample.level"); + if (func == nullptr) { + func = ::llvm::Function::Create( + ::llvm::FunctionType::get( + ::llvm::FixedVectorType::get(b->getFloatTy(), 4u), + {_bindless_texture_type()->getPointerTo(), b->getInt32Ty(), + b->getFloatTy(), b->getFloatTy(), b->getFloatTy(), b->getFloatTy()}, + false), + ::llvm::Function::ExternalLinkage, "bindless.texture.3d.sample.level", _module); + } + auto ret = b->CreateCall(func, {p_texture, sampler, uvw_x, uvw_y, uvw_z, lod}, "bindless.texture.sample.3d.level.ret"); + return _create_stack_variable(ret, "bindless.texture.sample.3d.level.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_bindless_texture_sample2d_grad(::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_uv, ::llvm::Value *p_dpdx, ::llvm::Value *p_dpdy) noexcept { + auto b = _current_context()->builder.get(); + auto index = b->CreateLoad(b->getInt32Ty(), p_index, "bindless.texture.sample.2d.grad.index"); + auto pp_texture = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(1)}, "bindless.texture.sample.2d.grad.texture.ptr.ptr"); + auto p_texture = b->CreateLoad(_bindless_texture_type()->getPointerTo(), pp_texture, "bindless.texture.sample.2d.grad.texture.ptr"); + auto p_sampler = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(3)}, "bindless.texture.sample.2d.grad.sampler.ptr"); + auto sampler = b->CreateLoad(b->getInt32Ty(), p_sampler, "bindless.texture.sample.2d.grad.sampler"); + auto uv = b->CreateLoad(_create_type(Type::of()), p_uv, "bindless.texture.sample.2d.grad.uv"); + auto uv_x = b->CreateExtractElement(uv, _literal(0u), "bindless.texture.sample.2d.grad.uv.x"); + auto uv_y = b->CreateExtractElement(uv, _literal(1u), "bindless.texture.sample.2d.grad.uv.y"); + p_dpdx = b->CreateBitOrPointerCast(p_dpdx, b->getInt64Ty()->getPointerTo(), "bindless.texture.sample.2d.grad.dpdx.addr"); + p_dpdy = b->CreateBitOrPointerCast(p_dpdy, b->getInt64Ty()->getPointerTo(), "bindless.texture.sample.2d.grad.dpdy.addr"); + auto dpdx = b->CreateLoad(b->getInt64Ty(), p_dpdx, "bindless.texture.sample.2d.grad.dpdx"); + auto dpdy = b->CreateLoad(b->getInt64Ty(), p_dpdy, "bindless.texture.sample.2d.grad.dpdy"); + auto func = _module->getFunction("bindless.texture.2d.sample.grad"); + if (func == nullptr) { + func = ::llvm::Function::Create( + ::llvm::FunctionType::get( + ::llvm::FixedVectorType::get(b->getFloatTy(), 4u), + {_bindless_texture_type()->getPointerTo(), b->getInt32Ty(), + b->getFloatTy(), b->getFloatTy(), b->getInt64Ty(), b->getInt64Ty()}, + false), + ::llvm::Function::ExternalLinkage, "bindless.texture.2d.sample.grad", _module); + } + auto ret = b->CreateCall(func, {p_texture, sampler, uv_x, uv_y, dpdx, dpdy}, "bindless.texture.sample.2d.grad.ret"); + return _create_stack_variable(ret, "bindless.texture.sample.2d.grad.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_bindless_texture_sample3d_grad(::llvm::Value *p_items, ::llvm::Value *p_index, ::llvm::Value *p_uvw, ::llvm::Value *p_dpdx, ::llvm::Value *p_dpdy) noexcept { + auto b = _current_context()->builder.get(); + auto index = b->CreateLoad(b->getInt32Ty(), p_index, "bindless.texture.sample.3d.grad.index"); + auto pp_texture = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(1)}, "bindless.texture.sample.3d.grad.texture.ptr.ptr"); + auto p_texture = b->CreateLoad(_bindless_texture_type()->getPointerTo(), pp_texture, "bindless.texture.sample.3d.grad.texture.ptr"); + auto p_sampler = b->CreateInBoundsGEP(_bindless_item_type(), p_items, {index, _literal(3)}, "bindless.texture.sample.3d.grad.sampler.ptr"); + p_uvw = _builtin_bitwise_cast(Type::of(), Type::of(), p_uvw); + p_dpdx = _builtin_bitwise_cast(Type::of(), Type::of(), p_dpdx); + p_dpdy = _builtin_bitwise_cast(Type::of(), Type::of(), p_dpdy); + auto uvw = b->CreateLoad(_create_type(Type::of()), p_uvw, "bindless.texture.sample.3d.grad.uvw"); + auto dpdx = b->CreateLoad(_create_type(Type::of()), p_dpdx, "bindless.texture.sample.3d.grad.dpdx"); + auto dpdy = b->CreateLoad(_create_type(Type::of()), p_dpdy, "bindless.texture.sample.3d.grad.dpdy"); + auto p_u = _create_stack_variable(b->CreateExtractElement(uvw, _literal(0u), "bindless.texture.sample.3d.grad.uvw.x"), "bindless.texture.sample.3d.grad.uvw.x.addr"); + auto p_v = _create_stack_variable(b->CreateExtractElement(uvw, _literal(1u), "bindless.texture.sample.3d.grad.uvw.y"), "bindless.texture.sample.3d.grad.uvw.y.addr"); + auto p_w = _create_stack_variable(b->CreateExtractElement(uvw, _literal(2u), "bindless.texture.sample.3d.grad.uvw.z"), "bindless.texture.sample.3d.grad.uvw.z.addr"); + auto p_dudx = _create_stack_variable(b->CreateExtractElement(dpdx, _literal(0u), "bindless.texture.sample.3d.grad.dpdx.x"), "bindless.texture.sample.3d.grad.dpdx.x.addr"); + auto p_dvdx = _create_stack_variable(b->CreateExtractElement(dpdy, _literal(1u), "bindless.texture.sample.3d.grad.dpdy.y"), "bindless.texture.sample.3d.grad.dpdy.y.addr"); + auto p_dwdx = _create_stack_variable(b->CreateExtractElement(dpdy, _literal(2u), "bindless.texture.sample.3d.grad.dpdy.z"), "bindless.texture.sample.3d.grad.dpdy.z.addr"); + auto p_dudy = _create_stack_variable(b->CreateExtractElement(dpdx, _literal(1u), "bindless.texture.sample.3d.grad.dpdx.y"), "bindless.texture.sample.3d.grad.dpdx.y.addr"); + auto p_dvdy = _create_stack_variable(b->CreateExtractElement(dpdy, _literal(0u), "bindless.texture.sample.3d.grad.dpdy.x"), "bindless.texture.sample.3d.grad.dpdy.x.addr"); + auto p_dwdy = _create_stack_variable(b->CreateExtractElement(dpdy, _literal(2u), "bindless.texture.sample.3d.grad.dpdy.z"), "bindless.texture.sample.3d.grad.dpdy.z.addr"); + auto p_sampler_and_w = b->CreateBitOrPointerCast(_make_int2(p_sampler, p_w), b->getInt64Ty()->getPointerTo(), "bindless.texture.sample.3d.grad.sampler.w.addr"); + auto p_uv = b->CreateBitOrPointerCast(_make_int2(p_u, p_v), b->getInt64Ty()->getPointerTo(), "bindless.texture.sample.3d.grad.uv.addr"); + auto p_dudxy = b->CreateBitOrPointerCast(_make_int2(p_dudx, p_dudy), b->getInt64Ty()->getPointerTo(), "bindless.texture.sample.3d.grad.dudxy.addr"); + auto p_dvdxy = b->CreateBitOrPointerCast(_make_int2(p_dvdx, p_dvdy), b->getInt64Ty()->getPointerTo(), "bindless.texture.sample.3d.grad.dvdxy.addr"); + auto p_dwdxy = b->CreateBitOrPointerCast(_make_int2(p_dwdx, p_dwdy), b->getInt64Ty()->getPointerTo(), "bindless.texture.sample.3d.grad.dwdxy.addr"); + auto sampler_and_w = b->CreateLoad(b->getInt64Ty(), p_sampler_and_w, "bindless.texture.sample.3d.grad.sampler.and.w"); + auto uv = b->CreateLoad(b->getInt64Ty(), p_uv, "bindless.texture.sample.3d.grad.uv"); + auto dudxy = b->CreateLoad(b->getInt64Ty(), p_dudxy, "bindless.texture.sample.3d.grad.dudxy"); + auto dvdxy = b->CreateLoad(b->getInt64Ty(), p_dvdxy, "bindless.texture.sample.3d.grad.dvdxy"); + auto dwdxy = b->CreateLoad(b->getInt64Ty(), p_dwdxy, "bindless.texture.sample.3d.grad.dwdxy"); + auto func = _module->getFunction("bindless.texture.sample.3d.grad"); + if (func == nullptr) { + func = ::llvm::Function::Create( + ::llvm::FunctionType::get( + ::llvm::FixedVectorType::get(b->getFloatTy(), 4u), + {_bindless_texture_type()->getPointerTo(), b->getInt64Ty(), + b->getFloatTy(), b->getFloatTy(), b->getInt64Ty(), b->getInt64Ty()}, + false), + ::llvm::Function::ExternalLinkage, "bindless.texture.3d.sample.grad", _module); + } + auto ret = b->CreateCall(func, {p_texture, sampler_and_w, uv, dudxy, dvdxy, dwdxy}, "bindless.texture.sample.3d.grad.ret"); + return _create_stack_variable(ret, "bindless.texture.sample.3d.grad.addr"); +} + +::llvm::Value *LLVMCodegen::_builtin_asinh(const Type *t, ::llvm::Value *v) noexcept { + // log(x + sqrt(x * x + 1.0)) + auto one = _create_stack_variable(_literal(1.0f), "asinh.one"); + if (t->is_vector()) { one = _builtin_static_cast(t, t->element(), one); } + return _builtin_log(t, _builtin_add(t, v, _builtin_sqrt(t, _builtin_add(t, _builtin_mul(t, v, v), one)))); +} + +::llvm::Value *LLVMCodegen::_builtin_acosh(const Type *t, ::llvm::Value *v) noexcept { + // log(x + sqrt(x * x - 1.0)) + auto one = _create_stack_variable(_literal(1.0f), "cosh.one"); + if (t->is_vector()) { one = _builtin_static_cast(t, t->element(), one); } + return _builtin_log(t, _builtin_add(t, v, _builtin_sqrt(t, _builtin_sub(t, _builtin_mul(t, v, v), one)))); +} + +::llvm::Value *LLVMCodegen::_builtin_atanh(const Type *t, ::llvm::Value *v) noexcept { + // 0.5 * log((1.0 + x) / (1.0 - x)) + auto one = _create_stack_variable(_literal(1.0f), "tanh.one"); + auto half = _create_stack_variable(_literal(0.5f), "tanh.half"); + if (t->is_vector()) { + one = _builtin_static_cast(t, t->element(), one); + half = _builtin_static_cast(t, t->element(), half); + } + auto one_plus_x = _builtin_add(t, one, v); + auto one_minus_x = _builtin_sub(t, one, v); + auto one_plus_x_over_one_minus_x = _builtin_div(t, one_plus_x, one_minus_x); + auto log_of_one_plus_x_over_one_minus_x = _builtin_log(t, one_plus_x_over_one_minus_x); + return _builtin_mul(t, half, log_of_one_plus_x_over_one_minus_x); +} + +::llvm::Value *LLVMCodegen::_builtin_cosh(const Type *t, ::llvm::Value *v) noexcept { + // y = exp(x) + // 0.5 * (y + 1 / y) + auto half = _create_stack_variable(_literal(0.5f), "cosh.half"); + auto one = _create_stack_variable(_literal(1.0f), "cosh.one"); + if (t->is_vector()) { + half = _builtin_static_cast(t, t->element(), half); + one = _builtin_static_cast(t, t->element(), one); + } + auto exp_x = _builtin_exp(t, v); + auto exp_minus_x = _builtin_div(t, one, exp_x); + auto exp_x_plus_exp_minus_x = _builtin_add(t, exp_x, exp_minus_x); + return _builtin_mul(t, half, exp_x_plus_exp_minus_x); +} + +::llvm::Value *LLVMCodegen::_builtin_sinh(const Type *t, ::llvm::Value *v) noexcept { + // y = exp(x) + // 0.5 * (y – 1 / y) + auto half = _create_stack_variable(_literal(0.5f), "sinh.half"); + auto one = _create_stack_variable(_literal(1.0f), "sinh.one"); + if (t->is_vector()) { + half = _builtin_static_cast(t, t->element(), half); + one = _builtin_static_cast(t, t->element(), one); + } + auto exp_x = _builtin_exp(t, v); + auto exp_minus_x = _builtin_div(t, one, exp_x); + auto exp_x_minus_exp_minus_x = _builtin_sub(t, exp_x, exp_minus_x); + return _builtin_mul(t, half, exp_x_minus_exp_minus_x); +} + +::llvm::Value *LLVMCodegen::_builtin_tanh(const Type *t, ::llvm::Value *v) noexcept { + // y = exp(2.0 * x) + // (y - 1.0) / (y + 1.0) + auto one = _create_stack_variable(_literal(1.0f), "tanh.one"); + auto two = _create_stack_variable(_literal(2.0f), "tanh.two"); + if (t->is_vector()) { + one = _builtin_static_cast(t, t->element(), one); + two = _builtin_static_cast(t, t->element(), two); + } + auto y = _builtin_exp(t, _builtin_mul(t, two, v)); + auto y_minus_one = _builtin_sub(t, y, one); + auto y_plus_one = _builtin_add(t, y, one); + return _builtin_div(t, y_minus_one, y_plus_one); +} + +}// namespace luisa::compute::llvm diff --git a/src/backends/fallback/llvm_codegen_expr.cpp b/src/backends/fallback/llvm_codegen_expr.cpp new file mode 100644 index 000000000..5adf97334 --- /dev/null +++ b/src/backends/fallback/llvm_codegen_expr.cpp @@ -0,0 +1,343 @@ +// +// Created by Mike Smith on 2022/5/23. +// + +#include + +namespace luisa::compute::fallback { + +#pragma clang diagnostic push +#pragma ide diagnostic ignored "cppcoreguidelines-pro-type-static-cast-downcast" +::llvm::Value *LLVMCodegen::_create_expr(const Expression *expr) noexcept { + switch (expr->tag()) { + case Expression::Tag::UNARY: + return _create_unary_expr(static_cast(expr)); + case Expression::Tag::BINARY: + return _create_binary_expr(static_cast(expr)); + case Expression::Tag::MEMBER: + return _create_member_expr(static_cast(expr)); + case Expression::Tag::ACCESS: + return _create_access_expr(static_cast(expr)); + case Expression::Tag::LITERAL: + return _create_literal_expr(static_cast(expr)); + case Expression::Tag::REF: + return _create_ref_expr(static_cast(expr)); + case Expression::Tag::CONSTANT: + return _create_constant_expr(static_cast(expr)); + case Expression::Tag::CALL: + return _create_call_expr(static_cast(expr)); + case Expression::Tag::CAST: + return _create_cast_expr(static_cast(expr)); + } + LUISA_ERROR_WITH_LOCATION("Invalid expression tag: {}.", to_underlying(expr->tag())); +} +#pragma clang diagnostic pop + +::llvm::Value *LLVMCodegen::_create_unary_expr(const UnaryExpr *expr) noexcept { + auto x = _create_expr(expr->operand()); + switch (expr->op()) { + case UnaryOp::PLUS: return _builtin_unary_plus(expr->operand()->type(), x); + case UnaryOp::MINUS: return _builtin_unary_minus(expr->operand()->type(), x); + case UnaryOp::NOT: return _builtin_unary_not(expr->operand()->type(), x); + case UnaryOp::BIT_NOT: return _builtin_unary_bit_not(expr->operand()->type(), x); + } + LUISA_ERROR_WITH_LOCATION("Invalid unary operator."); +} + +::llvm::Value *LLVMCodegen::_short_circuit_and(const Expression *lhs, const Expression *rhs) noexcept { + LUISA_ASSERT(lhs->type()->tag() == Type::Tag::BOOL && + rhs->type()->tag() == Type::Tag::BOOL, + "Expected (bool && bool) but got ({} && {}).", + lhs->type()->description(), rhs->type()->description()); + auto ctx = _current_context(); + auto value = _create_expr(lhs); + auto lhs_is_true = ctx->builder->CreateICmpNE( + ctx->builder->CreateLoad(_create_type(lhs->type()), value, "load"), + ctx->builder->getInt8(0), "cmp"); + auto next_block = ::llvm::BasicBlock::Create(_context, "and.next", ctx->ir); + auto out_block = ::llvm::BasicBlock::Create(_context, "and.out", ctx->ir); + next_block->moveAfter(ctx->builder->GetInsertBlock()); + ctx->builder->CreateCondBr(lhs_is_true, next_block, out_block); + ctx->builder->SetInsertPoint(next_block); + _create_assignment(Type::of(), rhs->type(), value, _create_expr(rhs)); + out_block->moveAfter(ctx->builder->GetInsertBlock()); + ctx->builder->CreateBr(out_block); + ctx->builder->SetInsertPoint(out_block); + return value; +} + +::llvm::Value *LLVMCodegen::_short_circuit_or(const Expression *lhs, const Expression *rhs) noexcept { + LUISA_ASSERT(lhs->type()->tag() == Type::Tag::BOOL && + rhs->type()->tag() == Type::Tag::BOOL, + "Expected (bool || bool) but got ({} || {}).", + lhs->type()->description(), rhs->type()->description()); + auto ctx = _current_context(); + auto value = _create_expr(lhs); + auto lhs_is_true = ctx->builder->CreateICmpNE( + ctx->builder->CreateLoad(_create_type(lhs->type()), value, "load"), + ctx->builder->getInt8(0), "cmp"); + auto next_block = ::llvm::BasicBlock::Create(_context, "or.next", ctx->ir); + auto out_block = ::llvm::BasicBlock::Create(_context, "or.out", ctx->ir); + next_block->moveAfter(ctx->builder->GetInsertBlock()); + ctx->builder->CreateCondBr(lhs_is_true, out_block, next_block); + ctx->builder->SetInsertPoint(next_block); + _create_assignment(Type::of(), rhs->type(), value, _create_expr(rhs)); + out_block->moveAfter(ctx->builder->GetInsertBlock()); + ctx->builder->CreateBr(out_block); + ctx->builder->SetInsertPoint(out_block); + return value; +} + +::llvm::Value *LLVMCodegen::_create_binary_expr(const BinaryExpr *expr) noexcept { + auto ctx = _current_context(); + auto lhs_type = expr->lhs()->type(); + auto rhs_type = expr->rhs()->type(); + // logical and/or should be short-circuit. + if (lhs_type->is_scalar() && rhs_type->is_scalar()) { + if (expr->op() == BinaryOp::AND) { return _short_circuit_and(expr->lhs(), expr->rhs()); } + if (expr->op() == BinaryOp::OR) { return _short_circuit_or(expr->lhs(), expr->rhs()); } + } + // matrices have to be handled separately + auto p_lhs = _create_expr(expr->lhs()); + auto p_rhs = _create_expr(expr->rhs()); + if (lhs_type->is_matrix() && rhs_type->is_matrix()) { + switch (expr->op()) { + case BinaryOp::ADD: return _builtin_add_matrix_matrix(lhs_type, rhs_type, p_lhs, p_rhs); + case BinaryOp::SUB: return _builtin_sub_matrix_matrix(lhs_type, rhs_type, p_lhs, p_rhs); + case BinaryOp::MUL: return _builtin_mul_matrix_matrix(lhs_type, rhs_type, p_lhs, p_rhs); + default: LUISA_ERROR_WITH_LOCATION("Invalid binary matrix-matrix operator."); + } + } + if (lhs_type->is_matrix() && rhs_type->is_scalar()) { + p_rhs = _scalar_to_float(rhs_type, p_rhs); + switch (expr->op()) { + case BinaryOp::ADD: return _builtin_add_matrix_scalar(lhs_type, rhs_type, p_lhs, p_rhs); + case BinaryOp::SUB: return _builtin_sub_matrix_scalar(lhs_type, rhs_type, p_lhs, p_rhs); + case BinaryOp::MUL: return _builtin_mul_matrix_scalar(lhs_type, rhs_type, p_lhs, p_rhs); + case BinaryOp::DIV: return _builtin_div_matrix_scalar(lhs_type, rhs_type, p_lhs, p_rhs); + default: LUISA_ERROR_WITH_LOCATION("Invalid binary matrix-scalar operator."); + } + } + if (lhs_type->is_scalar() && rhs_type->is_matrix()) { + p_lhs = _scalar_to_float(lhs_type, p_lhs); + switch (expr->op()) { + case BinaryOp::ADD: return _builtin_add_scalar_matrix(lhs_type, rhs_type, p_lhs, p_rhs); + case BinaryOp::SUB: return _builtin_sub_scalar_matrix(lhs_type, rhs_type, p_lhs, p_rhs); + case BinaryOp::MUL: return _builtin_mul_scalar_matrix(lhs_type, rhs_type, p_lhs, p_rhs); + case BinaryOp::DIV: return _builtin_div_scalar_matrix(lhs_type, rhs_type, p_lhs, p_rhs); + default: LUISA_ERROR_WITH_LOCATION("Invalid binary scalar-matrix operator."); + } + } + if (lhs_type->is_matrix() && rhs_type->is_vector()) { + LUISA_ASSERT(expr->op() == BinaryOp::MUL, "Invalid binary matrix-vector operator."); + LUISA_ASSERT(lhs_type->dimension() == rhs_type->dimension(), + "Dimensions mismatch in matrix-vector multiplication: {} vs {}.", + lhs_type->dimension(), rhs_type->dimension()); + p_rhs = _vector_to_float_vector(rhs_type, p_rhs); + return _builtin_mul_matrix_vector(lhs_type, rhs_type, p_lhs, p_rhs); + } + // scalar/scalar or vector/vector or vector/scalar + LUISA_ASSERT((lhs_type->is_scalar() || lhs_type->is_vector()) && + (rhs_type->is_scalar() || rhs_type->is_vector()), + "Expected (scalar op vector) or (scalar op vector) but got ({} op {}).", + lhs_type->description(), rhs_type->description()); + auto lhs_elem_type = lhs_type->is_scalar() ? lhs_type : lhs_type->element(); + auto rhs_elem_type = rhs_type->is_scalar() ? rhs_type : rhs_type->element(); + auto promoted_elem_type = [&] { + if (expr->op() == BinaryOp::AND || + expr->op() == BinaryOp::OR) { + return Type::of(); + } + switch (lhs_elem_type->tag()) { + case Type::Tag::BOOL: return rhs_elem_type; + case Type::Tag::FLOAT: return lhs_elem_type; + case Type::Tag::INT: + return rhs_elem_type->tag() == Type::Tag::UINT || + rhs_elem_type->tag() == Type::Tag::FLOAT ? + rhs_elem_type : + lhs_elem_type; + case Type::Tag::UINT: + return rhs_elem_type->tag() == Type::Tag::FLOAT ? + rhs_elem_type : + lhs_elem_type; + default: break; + } + LUISA_ERROR_WITH_LOCATION( + "Invalid types '{}' and '{}' for binary operator.", + lhs_elem_type->description(), rhs_elem_type->description()); + }(); + auto promoted_type = expr->type()->is_vector() ? + Type::from(luisa::format( + "vector<{},{}>", + promoted_elem_type->description(), + expr->type()->dimension())) : + promoted_elem_type; + auto lhs_v = _builtin_static_cast(promoted_type, lhs_type, p_lhs); + auto rhs_v = _builtin_static_cast(promoted_type, rhs_type, p_rhs); + switch (expr->op()) { + case BinaryOp::ADD: return _builtin_add(promoted_type, lhs_v, rhs_v); + case BinaryOp::SUB: return _builtin_sub(promoted_type, lhs_v, rhs_v); + case BinaryOp::MUL: return _builtin_mul(promoted_type, lhs_v, rhs_v); + case BinaryOp::DIV: return _builtin_div(promoted_type, lhs_v, rhs_v); + case BinaryOp::MOD: return _builtin_mod(promoted_type, lhs_v, rhs_v); + case BinaryOp::BIT_AND: return _builtin_and(promoted_type, lhs_v, rhs_v); + case BinaryOp::BIT_OR: return _builtin_or(promoted_type, lhs_v, rhs_v); + case BinaryOp::BIT_XOR: return _builtin_xor(promoted_type, lhs_v, rhs_v); + case BinaryOp::SHL: return _builtin_shl(promoted_type, lhs_v, rhs_v); + case BinaryOp::SHR: return _builtin_shr(promoted_type, lhs_v, rhs_v); + case BinaryOp::AND: return _builtin_and(promoted_type, lhs_v, rhs_v); + case BinaryOp::OR: return _builtin_or(promoted_type, lhs_v, rhs_v); + case BinaryOp::LESS: return _builtin_lt(promoted_type, lhs_v, rhs_v); + case BinaryOp::GREATER: return _builtin_gt(promoted_type, lhs_v, rhs_v); + case BinaryOp::LESS_EQUAL: return _builtin_le(promoted_type, lhs_v, rhs_v); + case BinaryOp::GREATER_EQUAL: return _builtin_ge(promoted_type, lhs_v, rhs_v); + case BinaryOp::EQUAL: return _builtin_eq(promoted_type, lhs_v, rhs_v); + case BinaryOp::NOT_EQUAL: return _builtin_ne(promoted_type, lhs_v, rhs_v); + } + LUISA_ERROR_WITH_LOCATION("Invalid binary operator."); +} + +::llvm::Value *LLVMCodegen::_create_member_expr(const MemberExpr *expr) noexcept { + auto ctx = _current_context(); + auto self = _create_expr(expr->self()); + auto self_type = expr->self()->type(); + if (self_type->is_structure()) { + auto member_index = _struct_types.at(self_type->hash()) + .member_indices.at(expr->member_index()); + return ctx->builder->CreateStructGEP( + _create_type(self_type), self, member_index, + "struct.member.addr"); + } + LUISA_ASSERT(expr->self()->type()->is_vector() && expr->is_swizzle(), + "Invalid member expression. Vector swizzling expected."); + switch (expr->swizzle_size()) { + case 1u: { + auto idx = static_cast(expr->swizzle_index(0u)); + auto elem_type = _create_type(expr->type()); + auto ptr_type = ::llvm::PointerType::get(elem_type, 0); + auto ptr = ctx->builder->CreateBitOrPointerCast(self, ptr_type, "vector.member.ptr"); + return ctx->builder->CreateConstInBoundsGEP1_32(elem_type, ptr, idx, "vector.member.addr"); + } + case 2u: return _create_stack_variable( + ctx->builder->CreateShuffleVector( + ctx->builder->CreateLoad( + _create_type(self_type), self, "vector.member.load"), + {static_cast(expr->swizzle_index(0u)), + static_cast(expr->swizzle_index(1u))}, + "vector.swizzle"), + "vector.swizzle.addr"); + case 3u: return _create_stack_variable( + ctx->builder->CreateShuffleVector( + ctx->builder->CreateLoad( + _create_type(self_type), self, "vector.member.load"), + {static_cast(expr->swizzle_index(0u)), + static_cast(expr->swizzle_index(1u)), + static_cast(expr->swizzle_index(2u))}, + "vector.swizzle"), + "vector.swizzle.addr"); + case 4u: return _create_stack_variable( + ctx->builder->CreateShuffleVector( + ctx->builder->CreateLoad( + _create_type(self_type), self, "vector.member.load"), + {static_cast(expr->swizzle_index(0u)), + static_cast(expr->swizzle_index(1u)), + static_cast(expr->swizzle_index(2u)), + static_cast(expr->swizzle_index(3u))}, + "vector.swizzle"), + "vector.swizzle.addr"); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid swizzle size: {}.", expr->swizzle_size()); +} + +::llvm::Value *LLVMCodegen::_create_access_expr(const AccessExpr *expr) noexcept { + auto ctx = _current_context(); + auto range = _create_expr(expr->range()); + auto index = ctx->builder->CreateLoad( + _create_type(Type::of()), + _builtin_static_cast( + Type::of(), expr->index()->type(), + _create_expr(expr->index())), + "access.index"); + auto elem_type = _create_type(expr->type()); + auto ptr_type = elem_type->getPointerTo(); + auto range_type = expr->range()->type(); + if (range_type->is_buffer()) { + return ctx->builder->CreateInBoundsGEP(elem_type, range, index, "access.addr"); + } + if (range_type->is_vector()) { + auto ptr = ctx->builder->CreateBitOrPointerCast(range, ptr_type, "vector.ptr"); + return ctx->builder->CreateInBoundsGEP(elem_type, ptr, index, "access.addr"); + } + LUISA_ASSERT(range_type->is_array() || range_type->is_matrix(), + "Invalid range type '{}'.", range_type->description()); + return ctx->builder->CreateInBoundsGEP( + _create_type(range_type), range, {_literal(0u), index}, "access.addr"); +} + +::llvm::Value *LLVMCodegen::_create_literal_expr(const LiteralExpr *expr) noexcept { + return luisa::visit( + [this](auto x) noexcept { + return _create_stack_variable( + _literal(x), "const.addr"); + }, + expr->value()); +} + +::llvm::Value *LLVMCodegen::_create_ref_expr(const RefExpr *expr) noexcept { + return _current_context()->variables.at(expr->variable().uid()); +} + +::llvm::Value *LLVMCodegen::_create_constant_expr(const ConstantExpr *expr) noexcept { + return _create_constant(expr->data()); +} + +::llvm::Value *LLVMCodegen::_create_call_expr(const CallExpr *expr) noexcept { + if (expr->is_builtin()) { + return _create_builtin_call_expr( + expr->type(), expr->op(), expr->arguments()); + } + // custom + auto f = _create_function(expr->custom()); + auto ctx = _current_context(); + luisa::vector<::llvm::Value *> args; + for (auto i = 0u; i < expr->arguments().size(); i++) { + auto arg = expr->arguments()[i]; + auto call_arg = _create_expr(arg); + if (auto expected_arg = expr->custom().arguments()[i]; + expected_arg.type()->is_basic() || + expected_arg.type()->is_array() || + expected_arg.type()->is_structure()) { + call_arg = _builtin_static_cast(expected_arg.type(), arg->type(), _create_expr(arg)); + if (auto usage = expr->custom().variable_usage(expected_arg.uid()); + expected_arg.tag() != Variable::Tag::REFERENCE || + (usage == Usage::NONE || usage == Usage::READ)) { + call_arg = ctx->builder->CreateLoad( + _create_type(expected_arg.type()), call_arg, "load"); + } + } + args.emplace_back(call_arg); + } + ::llvm::ArrayRef<::llvm::Value *> args_ref{args.data(), args.size()}; + auto call = ctx->builder->CreateCall(f->getFunctionType(), f, args_ref); + if (expr->type() == nullptr) { return call; } + call->setName("result"); + return _create_stack_variable(call, "result.addr"); +} + +::llvm::Value *LLVMCodegen::_create_cast_expr(const CastExpr *expr) noexcept { + if (expr->op() == CastOp::STATIC) { + return _builtin_static_cast( + expr->type(), expr->expression()->type(), + _create_expr(expr->expression())); + } + return _builtin_bitwise_cast( + expr->type(), expr->expression()->type(), + _create_expr(expr->expression())); +} + +::llvm::Value *LLVMCodegen::_create_custom_op_expr(const CpuCustomOpExpr * expr) noexcept { + LUISA_ERROR_WITH_LOCATION("Not implemented."); +} + +}// namespace luisa::compute::llvm diff --git a/src/backends/fallback/llvm_codegen_func.cpp b/src/backends/fallback/llvm_codegen_func.cpp new file mode 100644 index 000000000..1e52d85db --- /dev/null +++ b/src/backends/fallback/llvm_codegen_func.cpp @@ -0,0 +1,519 @@ +// +// Created by Mike Smith on 2022/6/6. +// + +#include + +namespace luisa::compute::fallback { + +luisa::string LLVMCodegen::_function_name(Function f) const noexcept { + return luisa::format("{}.{:016x}", + f.tag() == Function::Tag::KERNEL ? "kernel" : "custom", + f.hash()); +} + +unique_ptr LLVMCodegen::_create_kernel_context(Function f) noexcept { + auto create_argument_struct = [&] { + auto member_index = 0u; + luisa::vector<::llvm::Type *> field_types; + luisa::vector field_indices; + auto size = 0ul; + static constexpr auto alignment = 16ul; + for (auto &arg : f.arguments()) { + auto aligned_offset = luisa::align(size, alignment); + if (aligned_offset > size) { + auto padding = ::llvm::ArrayType::get( + ::llvm::Type::getInt8Ty(_context), aligned_offset - size); + field_types.emplace_back(padding); + member_index++; + } + auto arg_size = [arg]() noexcept -> size_t { + switch (arg.tag()) { + case Variable::Tag::REFERENCE: return sizeof(void *); + case Variable::Tag::BUFFER: return buffer_handle_size; + case Variable::Tag::TEXTURE: return texture_handle_size; + case Variable::Tag::BINDLESS_ARRAY: return bindless_array_handle_size; + case Variable::Tag::ACCEL: return accel_handle_size; + default: break; + } + return arg.type()->size(); + }(); + field_types.emplace_back(_create_type(arg.type())); + field_indices.emplace_back(member_index++); + size = aligned_offset + arg_size; + } + auto aligned_size = luisa::align(size, alignment); + if (aligned_size > size) {// last padding + auto padding = ::llvm::ArrayType::get( + ::llvm::Type::getInt8Ty(_context), aligned_size - size); + field_types.emplace_back(padding); + member_index++; + } + // launch size + field_types.emplace_back(_create_type(Type::of())); + field_indices.emplace_back(member_index++); + ::llvm::ArrayRef<::llvm::Type *> fields_ref{field_types.data(), field_types.size()}; + return std::make_pair( + ::llvm::StructType::create(_context, fields_ref), + std::move(field_indices)); + }; + auto [arg_struct_type, arg_struct_indices] = create_argument_struct(); + auto arg_struct_name = luisa::format("arg.buffer.struct.{:016x}", f.hash()); + arg_struct_type->setName(::llvm::StringRef{arg_struct_name.data(), arg_struct_name.size()}); + auto arg_buffer_type = ::llvm::PointerType::get(arg_struct_type, 0); + ::llvm::SmallVector<::llvm::Type *, 8u> arg_types; + arg_types.emplace_back(arg_buffer_type); + arg_types.emplace_back(::llvm::PointerType::get(::llvm::Type::getInt8Ty(_context), 0)); + auto i32_type = ::llvm::Type::getInt32Ty(_context); + // dispatch size + arg_types.emplace_back(i32_type); + arg_types.emplace_back(i32_type); + arg_types.emplace_back(i32_type); + // block id + arg_types.emplace_back(i32_type); + arg_types.emplace_back(i32_type); + arg_types.emplace_back(i32_type); + LUISA_ASSERT(f.return_type() == nullptr, + "Invalid return type '{}' for kernel. Only void is allowed.", + f.return_type()->description()); + auto function_type = ::llvm::FunctionType::get( + ::llvm::Type::getVoidTy(_context), arg_types, false); + auto main_name = luisa::format("kernel.{:016x}.main", f.hash()); + auto ir = ::llvm::Function::Create( + function_type, ::llvm::Function::ExternalLinkage, + ::llvm::StringRef{main_name.data(), main_name.size()}, _module); + auto builder = luisa::make_unique<::llvm::IRBuilder<>>(_context); + auto entry_block = ::llvm::BasicBlock::Create(_context, "entry", ir); + builder->SetInsertPoint(entry_block); + luisa::vector<::llvm::Value *> arguments; + for (auto arg_id = 0u; arg_id < f.arguments().size(); arg_id++) { + auto &arg = f.arguments()[arg_id]; + switch (arg.tag()) { + case Variable::Tag::LOCAL: + case Variable::Tag::BUFFER: + case Variable::Tag::TEXTURE: + case Variable::Tag::BINDLESS_ARRAY: + case Variable::Tag::ACCEL: { + auto arg_name = _variable_name(arg); + auto addr_name = luisa::format("{}.addr", arg_name); + auto pr = builder->CreateStructGEP( + arg_struct_type, ir->getArg(0u), arg_struct_indices[arg_id], + ::llvm::StringRef{addr_name.data(), addr_name.size()}); + auto r = builder->CreateAlignedLoad( + _create_type(arg.type()), pr, ::llvm::Align{16ull}, + ::llvm::StringRef{arg_name.data(), arg_name.size()}); + arguments.emplace_back(r); + break; + } + default: LUISA_ERROR_WITH_LOCATION("Invalid kernel argument type."); + } + } + auto exit_block = ::llvm::BasicBlock::Create(_context, "exit", ir); + builder->SetInsertPoint(exit_block); + builder->CreateRetVoid(); + + // create work function... + auto ctx = _create_kernel_program(f); + // create simple schedule... + builder->SetInsertPoint(entry_block); + // block id + auto block_id = static_cast<::llvm::Value *>( + ::llvm::UndefValue::get(::llvm::FixedVectorType::get(i32_type, 3u))); + auto dispatch_size = static_cast<::llvm::Value *>( + ::llvm::UndefValue::get(::llvm::FixedVectorType::get(i32_type, 3u))); + for (auto i = 0u; i < 3u; i++) { + using namespace std::string_literals; + std::array elements{"x", "y", "z"}; + auto block_id_i = ir->getArg(i + 5u); + auto dispatch_size_i = ir->getArg(i + 2u); + block_id_i->setName("block.id."s.append(elements[i])); + dispatch_size_i->setName("dispatch.size."s.append(elements[i])); + block_id = builder->CreateInsertElement(block_id, block_id_i, i); + dispatch_size = builder->CreateInsertElement(dispatch_size, dispatch_size_i, i); + } + + auto i1_type = ::llvm::Type::getInt1Ty(_context); + auto i8_type = ::llvm::Type::getInt8Ty(_context); + auto ptr_type = ::llvm::PointerType::get(i8_type, 0); + auto needs_coro = f.propagated_builtin_callables().test(CallOp::SYNCHRONIZE_BLOCK); + auto thread_count = f.block_size().x * f.block_size().y * f.block_size().z; + ::llvm::AllocaInst *p_coro_states = nullptr; + ::llvm::AllocaInst *p_coro_all_done = nullptr; + ::llvm::BasicBlock *coro_loop = nullptr; + if (needs_coro) { + p_coro_states = builder->CreateAlloca( + ptr_type, ::llvm::ConstantInt::get(i32_type, thread_count)); + p_coro_states->setName("coro.states"); + p_coro_states->setAlignment(::llvm::Align{16u}); + builder->CreateMemSet( + p_coro_states, builder->getInt8(0u), + thread_count * sizeof(void *), ::llvm::Align{16u}); + p_coro_all_done = builder->CreateAlloca( + i1_type, ::llvm::ConstantInt::get(i32_type, 1u), "coro.all.done.addr"); + coro_loop = ::llvm::BasicBlock::Create(_context, "coro.loop", ir); + coro_loop->moveAfter(entry_block); + builder->CreateBr(coro_loop); + builder->SetInsertPoint(coro_loop); + builder->CreateStore(::llvm::ConstantInt::get(i1_type, true), p_coro_all_done); + } + + // loop + auto p_index = builder->CreateAlloca(::llvm::Type::getInt32Ty(_context), nullptr, "loop.index.addr"); + builder->CreateStore(builder->getInt32(0u), p_index); + auto loop_block = ::llvm::BasicBlock::Create(_context, "loop.head", ir, exit_block); + builder->CreateBr(loop_block); + builder->SetInsertPoint(loop_block); + auto index = builder->CreateLoad(::llvm::Type::getInt32Ty(_context), p_index, "loop.index"); + auto thread_yz = builder->CreateUDiv(index, builder->getInt32(f.block_size().x)); + auto thread_x = builder->CreateURem(index, builder->getInt32(f.block_size().x), "thread.id.x"); + auto thread_y = builder->CreateURem(thread_yz, builder->getInt32(f.block_size().y), "thread.id.y"); + auto thread_z = builder->CreateUDiv(thread_yz, builder->getInt32(f.block_size().y), "thread.id.z"); + auto thread_id = static_cast<::llvm::Value *>(::llvm::UndefValue::get(_create_type(Type::of()))); + thread_id = builder->CreateInsertElement(thread_id, thread_x, static_cast(0u)); + thread_id = builder->CreateInsertElement(thread_id, thread_y, static_cast(1u)); + thread_id = builder->CreateInsertElement(thread_id, thread_z, static_cast(2u), "thread.id"); + auto dispatch_id = builder->CreateNUWAdd(builder->CreateNUWMul(block_id, _literal(f.block_size())), thread_id, "dispatch.id"); + auto valid_thread = builder->CreateAndReduce(builder->CreateICmpULT(dispatch_id, dispatch_size, "thread.id.cmp")); + auto call_block = ::llvm::BasicBlock::Create(_context, "loop.kernel", ir, exit_block); + auto loop_update_block = ::llvm::BasicBlock::Create(_context, "loop.update", ir, exit_block); + builder->CreateCondBr(valid_thread, call_block, loop_update_block); + // call or resume + builder->SetInsertPoint(call_block); + if (needs_coro) { + auto p_coro_state = builder->CreateInBoundsGEP(ptr_type, p_coro_states, index, "coro.state.addr"); + auto coro_state = builder->CreateLoad(ptr_type, p_coro_state, "coro.state"); + auto coro_state_is_null = builder->CreateIsNull(coro_state, "coro.state.is.null"); + auto call_kernel = ::llvm::BasicBlock::Create(_context, "loop.kernel.call", ir); + auto resume_kernel = ::llvm::BasicBlock::Create(_context, "loop.kernel.resume", ir); + call_kernel->moveAfter(call_block); + resume_kernel->moveAfter(call_block); + builder->CreateCondBr(coro_state_is_null, call_kernel, resume_kernel); + // call + builder->SetInsertPoint(call_kernel); + auto call_args = arguments; + call_args.emplace_back(thread_id); + call_args.emplace_back(block_id); + call_args.emplace_back(dispatch_id); + call_args.emplace_back(dispatch_size); + call_args.emplace_back(ir->getArg(1u));// shared memory + auto coro_handle = builder->CreateCall( + ctx->ir->getFunctionType(), ctx->ir, + ::llvm::ArrayRef<::llvm::Value *>{call_args.data(), call_args.size()}); + builder->CreateStore(coro_handle, p_coro_state); + builder->CreateStore(::llvm::ConstantInt::get(i1_type, false), p_coro_all_done); + builder->CreateBr(loop_update_block); + // resume or done + builder->SetInsertPoint(resume_kernel); + builder->CreateIntrinsic(::llvm::Intrinsic::coro_resume, {}, {coro_state}); + auto coro_done = builder->CreateIntrinsic(::llvm::Intrinsic::coro_done, {}, {coro_state}); + auto coro_all_done = builder->CreateLoad(i1_type, p_coro_all_done, "coro.all.done"); + auto coro_all_done_and = builder->CreateAnd(coro_all_done, coro_done, "coro.all.done.and"); + builder->CreateStore(coro_all_done_and, p_coro_all_done); + auto coro_done_block = ::llvm::BasicBlock::Create(_context, "loop.kernel.done", ir); + coro_done_block->moveAfter(resume_kernel); + builder->CreateCondBr(coro_done, coro_done_block, loop_update_block); + builder->SetInsertPoint(coro_done_block); + builder->CreateIntrinsic(::llvm::Intrinsic::coro_destroy, {}, {coro_state}); + builder->CreateBr(loop_update_block); + } else { + auto call_args = arguments; + call_args.emplace_back(thread_id); + call_args.emplace_back(block_id); + call_args.emplace_back(dispatch_id); + call_args.emplace_back(dispatch_size); + call_args.emplace_back(ir->getArg(1u));// shared memory + builder->CreateCall( + ctx->ir->getFunctionType(), ctx->ir, + ::llvm::ArrayRef<::llvm::Value *>{call_args.data(), call_args.size()}); + builder->CreateBr(loop_update_block); + } + // update + builder->SetInsertPoint(loop_update_block); + auto next_index = builder->CreateAdd(index, builder->getInt32(1u), "loop.index.next"); + builder->CreateStore(next_index, p_index); + auto should_continue = builder->CreateICmpULT(next_index, builder->getInt32(thread_count)); + if (needs_coro) { + auto loop_out = ::llvm::BasicBlock::Create(_context, "loop.out", ir); + loop_out->moveAfter(loop_update_block); + builder->CreateCondBr(should_continue, loop_block, loop_out); + builder->SetInsertPoint(loop_out); + auto coro_all_done = builder->CreateLoad(i1_type, p_coro_all_done, "coro.all.done"); + builder->CreateCondBr(coro_all_done, exit_block, coro_loop); + } else { + builder->CreateCondBr(should_continue, loop_block, exit_block); + } + return ctx; +} + +luisa::unique_ptr LLVMCodegen::_create_kernel_program(Function f) noexcept { + luisa::vector<::llvm::Type *> arg_types; + for (auto &&arg : f.arguments()) { + switch (arg.tag()) { + case Variable::Tag::LOCAL: + case Variable::Tag::BUFFER: + case Variable::Tag::TEXTURE: + case Variable::Tag::BINDLESS_ARRAY: + case Variable::Tag::ACCEL: + arg_types.emplace_back(_create_type(arg.type())); + break; + default: LUISA_ERROR_WITH_LOCATION("Invalid kernel argument type."); + } + } + // thread_id/block_id/dispatch_id/dispatch_size + for (auto i = 0u; i < 4u; i++) { + arg_types.emplace_back(_create_type(Type::of())); + } + // shared memory + arg_types.emplace_back(::llvm::PointerType::get(::llvm::Type::getInt8Ty(_context), 0u)); + auto needs_coroutine = f.propagated_builtin_callables().test(CallOp::SYNCHRONIZE_BLOCK); + auto return_type = needs_coroutine ? ::llvm::Type::getInt8PtrTy(_context) : ::llvm::Type::getVoidTy(_context); + ::llvm::ArrayRef<::llvm::Type *> arg_types_ref{arg_types.data(), arg_types.size()}; + auto function_type = ::llvm::FunctionType::get(return_type, arg_types_ref, false); + auto name = _function_name(f); + auto ir = ::llvm::Function::Create( + function_type, ::llvm::Function::InternalLinkage, + ::llvm::StringRef{name.data(), name.size()}, _module); + ir->addFnAttr("coroutine.presplit", "0");// LLVM require the frontend to add the function attribute + auto builder = luisa::make_unique<::llvm::IRBuilder<>>(_context); + auto entry_block = ::llvm::BasicBlock::Create(_context, "entry", ir); + auto exit_block = ::llvm::BasicBlock::Create(_context, "exit", ir); + ::llvm::BasicBlock *coro_cleanup = nullptr; + ::llvm::BasicBlock *coro_suspend = nullptr; + if (needs_coroutine) { + // coro begin + builder->SetInsertPoint(entry_block); + auto i32_type = ::llvm::Type::getInt32Ty(_context); + auto i8_type = ::llvm::Type::getInt8Ty(_context); + auto i1_type = ::llvm::Type::getInt1Ty(_context); + auto ptr_type = ::llvm::Type::getInt8PtrTy(_context); + auto coro_id = builder->CreateIntrinsic( + ::llvm::Intrinsic::coro_id, {}, + {::llvm::ConstantInt::get(i32_type, 0u), + ::llvm::ConstantPointerNull::get(ptr_type), + ::llvm::ConstantPointerNull::get(ptr_type), + ::llvm::ConstantPointerNull::get(ptr_type)}); + coro_id->setName("coro.id"); + auto coro_needs_alloc = builder->CreateIntrinsic( + ::llvm::Intrinsic::coro_alloc, {}, {coro_id}); + coro_needs_alloc->setName("coro.needs.alloc"); + auto coro_dyn_alloc = ::llvm::BasicBlock::Create(_context, "coro.dyn.alloc", ir); + auto coro_begin = ::llvm::BasicBlock::Create(_context, "coro.begin", ir); + coro_dyn_alloc->moveAfter(entry_block); + coro_begin->moveAfter(coro_dyn_alloc); + builder->CreateCondBr(coro_needs_alloc, coro_dyn_alloc, coro_begin); + builder->SetInsertPoint(coro_dyn_alloc); + auto coro_size = builder->CreateIntrinsic( + ::llvm::Intrinsic::coro_size, {i32_type}, {}); + coro_size->setName("coro.size"); + auto coro_mem = ::llvm::CallInst::CreateMalloc( + coro_dyn_alloc, coro_size->getType(), i8_type, + coro_size, nullptr, nullptr, "coro.malloc"); + builder->Insert(coro_mem); + builder->CreateBr(coro_begin); + builder->SetInsertPoint(coro_begin); + auto phi = builder->CreatePHI(ptr_type, 2u, "coro.mem"); + phi->addIncoming(::llvm::ConstantPointerNull::get(ptr_type), entry_block); + phi->addIncoming(coro_mem, coro_dyn_alloc); + auto coro_handle = builder->CreateIntrinsic( + ::llvm::Intrinsic::coro_begin, {}, {coro_id, phi}); + // coro end + builder->SetInsertPoint(exit_block); + // last suspend + auto coro_state = builder->CreateIntrinsic( + ::llvm::Intrinsic::coro_suspend, {}, + {::llvm::ConstantTokenNone::get(_context), + ::llvm::ConstantInt::get(i1_type, true)}); + coro_state->setName("coro.state"); + coro_cleanup = ::llvm::BasicBlock::Create(_context, "coro.cleanup", ir); + coro_suspend = ::llvm::BasicBlock::Create(_context, "coro.suspend", ir); + auto coro_trap = ::llvm::BasicBlock::Create(_context, "coro.trap", ir); + coro_cleanup->moveAfter(exit_block); + coro_suspend->moveAfter(coro_cleanup); + coro_trap->moveAfter(coro_suspend); + auto coro_switch = builder->CreateSwitch(coro_state, coro_suspend, 2u); + coro_switch->addCase(::llvm::ConstantInt::get(i8_type, 0), coro_trap); + coro_switch->addCase(::llvm::ConstantInt::get(i8_type, 1), coro_cleanup); + // coro cleanup + builder->SetInsertPoint(coro_cleanup); + auto mem = builder->CreateIntrinsic( + ::llvm::Intrinsic::coro_free, {}, {coro_id, coro_handle}); + mem->setName("coro.free.mem"); + auto coro_needs_free = builder->CreateICmpNE( + mem, ::llvm::ConstantPointerNull::get(ptr_type), "coro.needs.free"); + auto coro_dyn_free = ::llvm::BasicBlock::Create(_context, "coro.dyn.free", ir); + coro_dyn_free->moveAfter(coro_cleanup); + builder->CreateCondBr(coro_needs_free, coro_dyn_free, coro_suspend); + builder->SetInsertPoint(coro_dyn_free); + auto coro_free = ::llvm::CallInst::CreateFree(mem, coro_dyn_free); + builder->Insert(coro_free); + builder->CreateBr(coro_suspend); + // coro suspend + builder->SetInsertPoint(coro_suspend); + builder->CreateIntrinsic( + ::llvm::Intrinsic::coro_end, {}, + {coro_handle, ::llvm::ConstantInt::get(i1_type, false)}); + builder->CreateRet(coro_handle); + // coro trap + builder->SetInsertPoint(coro_trap); + builder->CreateIntrinsic( + ::llvm::Intrinsic::trap, {}, {}); + builder->CreateUnreachable(); + builder->SetInsertPoint(coro_begin); + } else { + builder->SetInsertPoint(exit_block); + builder->CreateRetVoid(); + builder->SetInsertPoint(entry_block); + } + luisa::unordered_map variables; + auto make_alloca = [&](::llvm::Value *x, luisa::string_view name = "") noexcept { + auto p = builder->CreateAlloca( + x->getType(), nullptr, + ::llvm::StringRef{name.data(), name.size()}); + p->setAlignment(::llvm::Align{16}); + builder->CreateStore(x, p); + return p; + }; + for (auto i = 0u; i < f.arguments().size(); i++) { + auto lc_arg = f.arguments()[i]; + auto arg_name = _variable_name(lc_arg); + auto arg = static_cast<::llvm::Value *>(ir->getArg(i)); + if (lc_arg.tag() == Variable::Tag::LOCAL) { arg = make_alloca(arg); } + arg->setName(::llvm::StringRef{arg_name.data(), arg_name.size()}); + variables.emplace(lc_arg.uid(), arg); + } + auto builtin_offset = f.arguments().size(); + for (auto arg : f.builtin_variables()) { + switch (arg.tag()) { + case Variable::Tag::THREAD_ID: + variables.emplace(arg.uid(), make_alloca(ir->getArg(builtin_offset + 0), _variable_name(arg))); + break; + case Variable::Tag::BLOCK_ID: + variables.emplace(arg.uid(), make_alloca(ir->getArg(builtin_offset + 1), _variable_name(arg))); + break; + case Variable::Tag::DISPATCH_ID: + variables.emplace(arg.uid(), make_alloca(ir->getArg(builtin_offset + 2), _variable_name(arg))); + break; + case Variable::Tag::DISPATCH_SIZE: + variables.emplace(arg.uid(), make_alloca(ir->getArg(builtin_offset + 3), _variable_name(arg))); + break; + default: LUISA_ERROR_WITH_LOCATION("Invalid kernel argument type."); + } + } + // shared memory + auto smem = ir->getArg(builtin_offset + 4); + auto smem_offset = 0u; + for (auto s : f.shared_variables()) { + auto alignment = s.type()->alignment(); + smem_offset = (smem_offset + alignment - 1u) / alignment * alignment; + auto p = builder->CreateConstGEP1_32( + ::llvm::Type::getInt8Ty(_context), smem, smem_offset); + auto ptr = builder->CreatePointerCast(p, _create_type(s.type())->getPointerTo()); + variables.emplace(s.uid(), ptr); + smem_offset += s.type()->size(); + } + auto ctx = luisa::make_unique( + f, ir, nullptr, exit_block, + std::move(builder), std::move(variables), + coro_cleanup, coro_suspend); + return ctx; +} + +unique_ptr LLVMCodegen::_create_callable_context(Function f) noexcept { + auto is_out_reference = [&f](auto v) noexcept { + return v.tag() == Variable::Tag::REFERENCE && + (f.variable_usage(v.uid()) == Usage::WRITE || + f.variable_usage(v.uid()) == Usage::READ_WRITE); + }; + luisa::vector<::llvm::Type *> arg_types; + for (auto &&arg : f.arguments()) { + auto arg_type = _create_type(arg.type()); + if (is_out_reference(arg)) { + arg_type = ::llvm::PointerType::get(arg_type, 0); + } + arg_types.emplace_back(arg_type); + } + auto return_type = _create_type(f.return_type()); + ::llvm::ArrayRef<::llvm::Type *> arg_types_ref{arg_types.data(), arg_types.size()}; + auto function_type = ::llvm::FunctionType::get(return_type, arg_types_ref, false); + auto name = _function_name(f); + auto ir = ::llvm::Function::Create( + function_type, ::llvm::Function::InternalLinkage, + ::llvm::StringRef{name.data(), name.size()}, _module); + auto builder = luisa::make_unique<::llvm::IRBuilder<>>(_context); + auto body_block = ::llvm::BasicBlock::Create(_context, "entry", ir); + auto exit_block = ::llvm::BasicBlock::Create(_context, "exit", ir); + builder->SetInsertPoint(body_block); + auto i = 0u; + luisa::unordered_map variables; + for (auto &&arg : ir->args()) { + auto lc_arg = f.arguments()[i++]; + auto arg_name = _variable_name(lc_arg); + arg.setName(::llvm::StringRef{arg_name.data(), arg_name.size()}); + if (is_out_reference(lc_arg)) { + variables.emplace(lc_arg.uid(), &arg); + } else { + switch (lc_arg.tag()) { + case Variable::Tag::BUFFER: + case Variable::Tag::TEXTURE: + case Variable::Tag::BINDLESS_ARRAY: + case Variable::Tag::ACCEL: + variables.emplace(lc_arg.uid(), &arg); + break; + default: { + auto p_arg = builder->CreateAlloca(arg.getType()); + p_arg->setAlignment(::llvm::Align{16}); + builder->CreateStore(&arg, p_arg); + variables.emplace(lc_arg.uid(), p_arg); + break; + } + } + } + } + ::llvm::Value *ret = nullptr; + if (auto ret_type = f.return_type()) { + builder->SetInsertPoint(body_block); + auto p_ret = builder->CreateAlloca(return_type, nullptr, "retval.addr"); + p_ret->setAlignment(::llvm::Align{16}); + ret = p_ret; + builder->SetInsertPoint(exit_block); + builder->CreateRet(builder->CreateLoad(return_type, ret)); + } else {// return void + builder->SetInsertPoint(exit_block); + builder->CreateRetVoid(); + } + builder->SetInsertPoint(body_block); + return luisa::make_unique( + f, ir, ret, exit_block, + std::move(builder), std::move(variables)); +} + +::llvm::Function *LLVMCodegen::_create_function(Function f) noexcept { + auto name = _function_name(f); + ::llvm::StringRef name_ref{name.data(), name.size()}; + if (auto ir = _module->getFunction(name_ref)) { return ir; } + _function_stack.emplace_back( + f.tag() == Function::Tag::KERNEL ? + _create_kernel_context(f) : + _create_callable_context(f)); + _emit_function(); + auto ctx = std::move(_function_stack.back()); + _function_stack.pop_back(); + if (ctx->builder->GetInsertBlock()->getTerminator() == nullptr) { + ctx->builder->CreateBr(ctx->exit_block); + } + return ctx->ir; +} + +void LLVMCodegen::_emit_function() noexcept { + auto ctx = _current_context(); + for (auto v : ctx->function.local_variables()) { + auto p = _create_alloca(_create_type(v.type()), _variable_name(v)); + ctx->variables.emplace(v.uid(), p); + ctx->builder->CreateMemSet( + p, ctx->builder->getInt8(0), + v.type()->size(), ::llvm::Align{16}); + } + ctx->function.body()->accept(*this); +} + +}// namespace luisa::compute::llvm diff --git a/src/backends/fallback/llvm_codegen_stmt.cpp b/src/backends/fallback/llvm_codegen_stmt.cpp new file mode 100644 index 000000000..f2b98d995 --- /dev/null +++ b/src/backends/fallback/llvm_codegen_stmt.cpp @@ -0,0 +1,216 @@ +// +// Created by Mike Smith on 2022/6/6. +// + +#include + +namespace luisa::compute::fallback { + +void LLVMCodegen::visit(const BreakStmt *stmt) { + auto ctx = _current_context(); + LUISA_ASSERT(!ctx->break_targets.empty(), + "Invalid break statement."); + auto br = ctx->builder->CreateBr(ctx->break_targets.back()); +} + +void LLVMCodegen::visit(const ContinueStmt *stmt) { + auto ctx = _current_context(); + LUISA_ASSERT(!ctx->continue_targets.empty(), + "Invalid continue statement."); + auto br = ctx->builder->CreateBr(ctx->continue_targets.back()); +} + +void LLVMCodegen::visit(const ReturnStmt *stmt) { + auto ctx = _current_context(); + if (auto ret_val = stmt->expression()) { + _create_assignment( + ctx->function.return_type(), stmt->expression()->type(), + ctx->ret, _create_expr(stmt->expression())); + } + auto br = ctx->builder->CreateBr(ctx->exit_block); +} + +void LLVMCodegen::visit(const ScopeStmt *stmt) { + for (auto s : stmt->statements()) { + s->accept(*this); + if (auto block = _current_context()->builder->GetInsertBlock(); + block->getTerminator() != nullptr /* terminated */) { + break;// remaining code is dead + } + } +} + +void LLVMCodegen::visit(const IfStmt *stmt) { + auto ctx = _current_context(); + auto cond = _create_expr(stmt->condition()); + cond = _scalar_to_bool(stmt->condition()->type(), cond); + cond = ctx->builder->CreateICmpNE( + ctx->builder->CreateLoad(_create_type(Type::of()), cond, "cond"), + ctx->builder->getInt8(0), "cond.cmp"); + auto then_block = ::llvm::BasicBlock::Create(_context, "if.then", ctx->ir); + auto else_block = ::llvm::BasicBlock::Create(_context, "if.else", ctx->ir); + auto end_block = ::llvm::BasicBlock::Create(_context, "if.end", ctx->ir); + ctx->builder->CreateCondBr(cond, then_block, else_block); + // true branch + then_block->moveAfter(ctx->builder->GetInsertBlock()); + ctx->builder->SetInsertPoint(then_block); + stmt->true_branch()->accept(*this); + if (ctx->builder->GetInsertBlock()->getTerminator() == nullptr) { + ctx->builder->CreateBr(end_block); + } + // false branch + else_block->moveAfter(ctx->builder->GetInsertBlock()); + ctx->builder->SetInsertPoint(else_block); + stmt->false_branch()->accept(*this); + end_block->moveAfter(ctx->builder->GetInsertBlock()); + if (ctx->builder->GetInsertBlock()->getTerminator() == nullptr) { + ctx->builder->CreateBr(end_block); + } + // end + ctx->builder->SetInsertPoint(end_block); +} + +void LLVMCodegen::visit(const LoopStmt *stmt) { + auto ctx = _current_context(); + auto loop_block = ::llvm::BasicBlock::Create(_context, "loop", ctx->ir); + auto loop_exit_block = ::llvm::BasicBlock::Create(_context, "loop.exit", ctx->ir); + loop_block->moveAfter(ctx->builder->GetInsertBlock()); + ctx->continue_targets.emplace_back(loop_block); + ctx->break_targets.emplace_back(loop_exit_block); + ctx->builder->CreateBr(loop_block); + ctx->builder->SetInsertPoint(loop_block); + stmt->body()->accept(*this); + if (ctx->builder->GetInsertBlock()->getTerminator() == nullptr) { + ctx->builder->CreateBr(loop_block); + } + ctx->continue_targets.pop_back(); + ctx->break_targets.pop_back(); + loop_exit_block->moveAfter(ctx->builder->GetInsertBlock()); + ctx->builder->SetInsertPoint(loop_exit_block); +} + +void LLVMCodegen::visit(const ExprStmt *stmt) { + static_cast(_create_expr(stmt->expression())); +} + +void LLVMCodegen::visit(const SwitchStmt *stmt) { + auto ctx = _current_context(); + auto t = ctx->builder->getInt32Ty(); + auto cond = ctx->builder->CreateLoad(t, _create_expr(stmt->expression()), "switch.value"); + auto end_block = ::llvm::BasicBlock::Create(_context, "switch.end", ctx->ir); + auto inst = ctx->builder->CreateSwitch(cond, end_block); + ctx->break_targets.emplace_back(end_block); + ctx->switch_stack.emplace_back(inst); + for (auto c : stmt->body()->statements()) { c->accept(*this); } + ctx->break_targets.pop_back(); + ctx->switch_stack.pop_back(); + end_block->moveAfter(ctx->builder->GetInsertBlock()); + ctx->builder->SetInsertPoint(end_block); +} + +void LLVMCodegen::visit(const SwitchCaseStmt *stmt) { + LUISA_ASSERT(stmt->expression()->tag() == Expression::Tag::LITERAL, + "Switch case expression must be a literal."); + auto v = static_cast(stmt->expression())->value(); + LUISA_ASSERT(luisa::holds_alternative(v) || luisa::holds_alternative(v), + "Switch case expression must be an integer."); + auto value = luisa::holds_alternative(v) ? luisa::get(v) : luisa::get(v); + auto ctx = _current_context(); + LUISA_ASSERT(!ctx->switch_stack.empty(), "Case outside of switch."); + auto case_block = ::llvm::BasicBlock::Create(_context, "switch.case", ctx->ir); + case_block->moveAfter(ctx->builder->GetInsertBlock()); + ctx->switch_stack.back()->addCase(ctx->builder->getInt32(value), case_block); + ctx->builder->SetInsertPoint(case_block); + stmt->body()->accept(*this); + if (ctx->builder->GetInsertBlock()->getTerminator() == nullptr) { + ctx->builder->CreateBr(ctx->break_targets.back()); + } +} + +void LLVMCodegen::visit(const SwitchDefaultStmt *stmt) { + auto ctx = _current_context(); + LUISA_ASSERT(!ctx->switch_stack.empty(), "Default case outside of switch."); + auto default_block = ::llvm::BasicBlock::Create(_context, "switch.default", ctx->ir); + ctx->switch_stack.back()->setDefaultDest(default_block); + default_block->moveAfter(ctx->builder->GetInsertBlock()); + ctx->builder->SetInsertPoint(default_block); + stmt->body()->accept(*this); + if (ctx->builder->GetInsertBlock()->getTerminator() == nullptr) { + ctx->builder->CreateBr(ctx->break_targets.back()); + } +} + +void LLVMCodegen::visit(const AssignStmt *stmt) { + _create_assignment( + stmt->lhs()->type(), stmt->rhs()->type(), + _create_expr(stmt->lhs()), _create_expr(stmt->rhs())); +} + +void LLVMCodegen::visit(const ForStmt *stmt) { + auto var = _create_expr(stmt->variable()); + auto ctx = _current_context(); + auto loop_test = ::llvm::BasicBlock::Create(_context, "for.test", ctx->ir); + auto loop_body = ::llvm::BasicBlock::Create(_context, "for.body", ctx->ir); + auto loop_update = ::llvm::BasicBlock::Create(_context, "for.update", ctx->ir); + auto loop_exit = ::llvm::BasicBlock::Create(_context, "for.exit", ctx->ir); + loop_test->moveAfter(ctx->builder->GetInsertBlock()); + ctx->builder->CreateBr(loop_test); + ctx->builder->SetInsertPoint(loop_test); + auto cond = _create_expr(stmt->condition()); + cond = _scalar_to_bool(stmt->condition()->type(), cond); + cond = ctx->builder->CreateICmpNE( + ctx->builder->CreateLoad(ctx->builder->getInt8Ty(), cond, "for.cond"), + ctx->builder->getInt8(0), "for.cond.cmp"); + ctx->builder->CreateCondBr(cond, loop_body, loop_exit); + loop_body->moveAfter(ctx->builder->GetInsertBlock()); + ctx->builder->SetInsertPoint(loop_body); + ctx->continue_targets.emplace_back(loop_update); + ctx->break_targets.emplace_back(loop_exit); + stmt->body()->accept(*this); + if (ctx->builder->GetInsertBlock()->getTerminator() == nullptr) { + ctx->builder->CreateBr(loop_update); + } + ctx->continue_targets.pop_back(); + ctx->break_targets.pop_back(); + loop_update->moveAfter(ctx->builder->GetInsertBlock()); + ctx->builder->SetInsertPoint(loop_update); + auto vt = stmt->variable()->type(); + auto st = stmt->step()->type(); + auto step = _builtin_static_cast(vt, st, _create_expr(stmt->step())); + auto t = _create_type(vt); + auto next = [&] { + switch (vt->tag()) { + case Type::Tag::FLOAT: + return ctx->builder->CreateFAdd( + ctx->builder->CreateLoad(t, var, "for.var"), + ctx->builder->CreateLoad(t, step, "for.var.step"), "for.var.next"); + case Type::Tag::INT: + return ctx->builder->CreateNSWAdd( + ctx->builder->CreateLoad(t, var, "for.var"), + ctx->builder->CreateLoad(t, step, "for.var.step"), "for.var.next"); + case Type::Tag::UINT: + return ctx->builder->CreateAdd( + ctx->builder->CreateLoad(t, var, "for.var"), + ctx->builder->CreateLoad(t, step, "for.var.step"), "for.var.next"); + default: break; + } + LUISA_ERROR_WITH_LOCATION( + "Invalid loop variable type: {}.", + vt->description()); + }(); + ctx->builder->CreateStore(next, var); + ctx->builder->CreateBr(loop_test); + loop_exit->moveAfter(ctx->builder->GetInsertBlock()); + ctx->builder->SetInsertPoint(loop_exit); +} + +void LLVMCodegen::visit(const CommentStmt *stmt) { /* do nothing */ } + +void LLVMCodegen::_create_assignment(const Type *dst_type, const Type *src_type, ::llvm::Value *p_dst, ::llvm::Value *p_src) noexcept { + auto p_rhs = _builtin_static_cast(dst_type, src_type, p_src); + auto builder = _current_context()->builder.get(); + auto dst = builder->CreateLoad(_create_type(dst_type), p_rhs, "load"); + builder->CreateStore(dst, p_dst); +} + +}// namespace luisa::compute::llvm diff --git a/src/backends/fallback/llvm_codegen_type.cpp b/src/backends/fallback/llvm_codegen_type.cpp new file mode 100644 index 000000000..85f8e56ca --- /dev/null +++ b/src/backends/fallback/llvm_codegen_type.cpp @@ -0,0 +1,661 @@ +// +// Created by Mike Smith on 2022/5/23. +// + +#include + +namespace luisa::compute::fallback { + +::llvm::Value *LLVMCodegen::_scalar_to_bool(const Type *src_type, ::llvm::Value *p_src) noexcept { + LUISA_ASSERT(src_type->is_scalar(), "Invalid source type: {}.", src_type->description()); + auto builder = _current_context()->builder.get(); + switch (src_type->tag()) { + case Type::Tag::BOOL: return p_src; + case Type::Tag::FLOAT: return _create_stack_variable( + builder->CreateFCmpONE( + builder->CreateLoad(_create_type(src_type), p_src, "cast.float.to.bool.src"), + _literal(0.f), "cast.float.to.bool.cmp"), + "cast.float.to.bool.addr"); + case Type::Tag::INT: + case Type::Tag::UINT: return _create_stack_variable( + builder->CreateICmpNE( + builder->CreateLoad(_create_type(src_type), p_src, "cast.int.to.bool.src"), + _literal(0u), "cast.int.to.bool.cmp"), + "cast.int.to.bool.addr"); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid conversion: {} to bool.", + src_type->description()); +} + +::llvm::Value *LLVMCodegen::_scalar_to_float(const Type *src_type, ::llvm::Value *p_src) noexcept { + LUISA_ASSERT(src_type->is_scalar(), "Invalid source type: {}.", src_type->description()); + auto builder = _current_context()->builder.get(); + switch (src_type->tag()) { + case Type::Tag::BOOL: return _create_stack_variable( + builder->CreateSelect( + builder->CreateICmpEQ( + builder->CreateLoad(_create_type(src_type), p_src, "cast.bool.to.float.src"), + _literal(true), "cast.bool.to.float.cmp"), + _literal(1.f), _literal(0.f), "cast.bool.to.float.select"), + "cast.bool.to.float.addr"); + case Type::Tag::FLOAT: return p_src; + case Type::Tag::INT: return _create_stack_variable( + builder->CreateSIToFP( + builder->CreateLoad(_create_type(src_type), p_src, "cast.int.to.float.src"), + builder->getFloatTy(), "cast.int.to.float.cast"), + "cast.int.to.float.addr"); + case Type::Tag::UINT: return _create_stack_variable( + builder->CreateUIToFP( + builder->CreateLoad(_create_type(src_type), p_src, "cast.uint.to.float.src"), + builder->getFloatTy(), "cast.uint.to.float.cast"), + "cast.uint.to.float.addr"); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid conversion: {} to float.", + src_type->description()); +} + +::llvm::Value *LLVMCodegen::_scalar_to_int(const Type *src_type, ::llvm::Value *p_src) noexcept { + LUISA_ASSERT(src_type->is_scalar(), "Invalid source type: {}.", src_type->description()); + auto builder = _current_context()->builder.get(); + switch (src_type->tag()) { + case Type::Tag::BOOL: return _create_stack_variable( + builder->CreateZExt( + builder->CreateLoad(_create_type(src_type), p_src, "cast.bool.to.int.src"), + builder->getInt32Ty(), "cast.bool.to.int.cast"), + "cast.bool.to.int.addr"); + case Type::Tag::FLOAT: return _create_stack_variable( + builder->CreateFPToSI( + builder->CreateLoad(_create_type(src_type), p_src, "cast.float.to.int.src"), + builder->getInt32Ty(), "cast.float.to.int.cast"), + "cast.float.to.int.addr"); + case Type::Tag::INT: + case Type::Tag::UINT: return p_src; + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid conversion: {} to int.", + src_type->description()); +} + +::llvm::Value *LLVMCodegen::_scalar_to_uint(const Type *src_type, ::llvm::Value *p_src) noexcept { + LUISA_ASSERT(src_type->is_scalar(), "Invalid source type: {}.", src_type->description()); + auto builder = _current_context()->builder.get(); + switch (src_type->tag()) { + case Type::Tag::BOOL: return _create_stack_variable( + builder->CreateZExt( + builder->CreateLoad(_create_type(src_type), p_src, "cast.bool.to.uint.src"), + builder->getInt32Ty(), "cast.bool.to.uint.cast"), + "cast.bool.to.uint.addr"); + case Type::Tag::FLOAT: return _create_stack_variable( + builder->CreateFPToUI( + builder->CreateLoad(_create_type(src_type), p_src, "cast.float.to.uint.src"), + builder->getInt32Ty(), "cast.float.to.uint.cast"), + "cast.float.to.uint.addr"); + case Type::Tag::INT: + case Type::Tag::UINT: return p_src; + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid conversion: {} to uint.", + src_type->description()); +} + +::llvm::Value *LLVMCodegen::_vector_to_bool_vector(const Type *src_type, ::llvm::Value *p_src) noexcept { + LUISA_ASSERT(src_type->is_vector(), "Invalid source type: {}.", src_type->description()); + auto builder = _current_context()->builder.get(); + switch (src_type->element()->tag()) { + case Type::Tag::BOOL: return p_src; + case Type::Tag::FLOAT: { + switch (src_type->dimension()) { + case 2u: return _create_stack_variable( + builder->CreateFCmpONE( + builder->CreateLoad(_create_type(src_type), p_src, "cast.float2.to.bool2.src"), + _literal(make_float2(0.f)), "cast.float2.to.bool2.cmp"), + "cast.float2.to.bool2.addr"); + case 3u: return _create_stack_variable( + builder->CreateFCmpONE( + builder->CreateLoad(_create_type(src_type), p_src, "cast.float3.to.bool3.src"), + _literal(make_float3(0.f)), "cast.float3.to.bool3.cmp"), + "cast.float3.to.bool3.addr"); + case 4u: return _create_stack_variable( + builder->CreateFCmpONE( + builder->CreateLoad(_create_type(src_type), p_src, "cast.float4.to.bool4.src"), + _literal(make_float4(0.f)), "cast.float4.to.bool4.cmp"), + "cast.float4.to.bool4.addr"); + default: break; + } + break; + } + case Type::Tag::INT: + case Type::Tag::UINT: { + switch (src_type->dimension()) { + case 2u: return _create_stack_variable( + builder->CreateICmpNE( + builder->CreateLoad(_create_type(src_type), p_src, "cast.int2.to.bool2.src"), + _literal(make_uint2(0u)), "cast.int2.to.bool2.cmp"), + "cast.int2.to.bool2.addr"); + case 3u: return _create_stack_variable( + builder->CreateICmpNE( + builder->CreateLoad(_create_type(src_type), p_src, "cast.int3.to.bool3.src"), + _literal(make_uint3(0u)), "cast.int3.to.bool3.cmp"), + "cast.int3.to.bool3.addr"); + case 4u: return _create_stack_variable( + builder->CreateICmpNE( + builder->CreateLoad(_create_type(src_type), p_src, "cast.int4.to.bool4.src"), + _literal(make_uint4(0u)), "cast.int4.to.bool4.cmp"), + "cast.int4.to.bool4.addr"); + default: break; + } + break; + } + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid conversion: {} to bool vector.", + src_type->description()); +} + +::llvm::Value *LLVMCodegen::_vector_to_float_vector(const Type *src_type, ::llvm::Value *p_src) noexcept { + LUISA_ASSERT(src_type->is_vector(), "Invalid source type: {}.", src_type->description()); + auto builder = _current_context()->builder.get(); + switch (src_type->element()->tag()) { + case Type::Tag::BOOL: { + switch (src_type->dimension()) { + case 2u: return _create_stack_variable( + builder->CreateSelect( + builder->CreateICmpEQ(builder->CreateLoad(_create_type(src_type), p_src, "cast.bool2.to.float2.src"), + _literal(make_bool2(true)), "cast.bool2.to.float2.cmp"), + _literal(make_float2(1.f)), _literal(make_float2(0.f)), "cast.bool2.to.float2.select"), + "cast.bool2.to.float2.addr"); + case 3u: return _create_stack_variable( + builder->CreateSelect( + builder->CreateICmpEQ(builder->CreateLoad(_create_type(src_type), p_src, "cast.bool3.to.float3.src"), + _literal(make_bool2(true)), "cast.bool3.to.float3.cmp"), + _literal(make_float3(1.f)), _literal(make_float3(0.f)), "cast.bool3.to.float3.select"), + "cast.bool3.to.float3.addr"); + case 4u: return _create_stack_variable( + builder->CreateSelect( + builder->CreateICmpEQ(builder->CreateLoad(_create_type(src_type), p_src, "cast.bool4.to.float4.src"), + _literal(make_bool2(true)), "cast.bool4.to.float4.cmp"), + _literal(make_float4(1.f)), _literal(make_float4(0.f)), "cast.bool4.to.float4.select"), + "cast.bool4.to.float4.addr"); + default: break; + } + break; + } + case Type::Tag::FLOAT: return p_src; + case Type::Tag::INT: { + switch (src_type->dimension()) { + case 2u: return _create_stack_variable( + builder->CreateSIToFP( + builder->CreateLoad(_create_type(src_type), p_src, "cast.int2.to.float2.src"), + _create_type(Type::of()), "cast.int2.to.float2.cast"), + "cast.int2.to.float2.addr"); + case 3u: return _create_stack_variable( + builder->CreateSIToFP( + builder->CreateLoad(_create_type(src_type), p_src, "cast.int3.to.float3.src"), + _create_type(Type::of()), "cast.int3.to.float3.cast"), + "cast.int3.to.float3.addr"); + case 4u: return _create_stack_variable( + builder->CreateSIToFP( + builder->CreateLoad(_create_type(src_type), p_src, "cast.int4.to.float4.src"), + _create_type(Type::of()), "cast.int4.to.float4.cast"), + "cast.int4.to.float4.addr"); + default: break; + } + break; + } + case Type::Tag::UINT: { + switch (src_type->dimension()) { + case 2u: return _create_stack_variable( + builder->CreateUIToFP( + builder->CreateLoad(_create_type(src_type), p_src, "cast.uint2.to.float2.src"), + _create_type(Type::of()), "cast.uint2.to.float2.cast"), + "cast.uint2.to.float2.addr"); + case 3u: return _create_stack_variable( + builder->CreateUIToFP( + builder->CreateLoad(_create_type(src_type), p_src, "cast.uint3.to.float3.src"), + _create_type(Type::of()), "cast.uint3.to.float3.cast"), + "cast.uint3.to.float3.addr"); + case 4u: return _create_stack_variable( + builder->CreateUIToFP( + builder->CreateLoad(_create_type(src_type), p_src, "cast.uint4.to.float4.src"), + _create_type(Type::of()), "cast.uint4.to.float4.cast"), + "cast.uint4.to.float4.addr"); + default: break; + } + break; + } + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid conversion: {} to float vector.", + src_type->description()); +} + +::llvm::Value *LLVMCodegen::_vector_to_int_vector(const Type *src_type, ::llvm::Value *p_src) noexcept { + LUISA_ASSERT(src_type->is_vector(), "Invalid source type: {}.", src_type->description()); + auto builder = _current_context()->builder.get(); + switch (src_type->element()->tag()) { + case Type::Tag::BOOL: { + switch (src_type->dimension()) { + case 2u: return _create_stack_variable( + builder->CreateZExt( + builder->CreateLoad(_create_type(src_type), p_src, "cast.bool2.to.int2.src"), + _create_type(Type::of()), "cast.bool2.to.int2.cast"), + "cast.bool2.to.int2.addr"); + case 3u: return _create_stack_variable( + builder->CreateZExt( + builder->CreateLoad(_create_type(src_type), p_src, "cast.bool3.to.int3.src"), + _create_type(Type::of()), "cast.bool3.to.int3.cast"), + "cast.bool3.to.int3.addr"); + case 4u: return _create_stack_variable( + builder->CreateZExt( + builder->CreateLoad(_create_type(src_type), p_src, "cast.bool4.to.int4.src"), + _create_type(Type::of()), "cast.bool4.to.int4.cast"), + "cast.bool4.to.int4.addr"); + default: break; + } + break; + } + case Type::Tag::FLOAT: { + switch (src_type->dimension()) { + case 2u: return _create_stack_variable( + builder->CreateFPToSI( + builder->CreateLoad(_create_type(src_type), p_src, "cast.float2.to.int2.src"), + _create_type(Type::of()), "cast.float2.to.int2.cast"), + "cast.float2.to.int2.addr"); + case 3u: return _create_stack_variable( + builder->CreateFPToSI( + builder->CreateLoad(_create_type(src_type), p_src, "cast.float3.to.int3.src"), + _create_type(Type::of()), "cast.float3.to.int3.cast"), + "cast.float3.to.int3.addr"); + case 4u: return _create_stack_variable( + builder->CreateFPToSI( + builder->CreateLoad(_create_type(src_type), p_src, "cast.float4.to.int4.src"), + _create_type(Type::of()), "cast.float4.to.int4.cast"), + "cast.float4.to.int4.addr"); + default: break; + } + break; + } + case Type::Tag::INT: + case Type::Tag::UINT: return p_src; + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid conversion: {} to int vector.", + src_type->description()); +} + +::llvm::Value *LLVMCodegen::_vector_to_uint_vector(const Type *src_type, ::llvm::Value *p_src) noexcept { + LUISA_ASSERT(src_type->is_vector(), "Invalid source type: {}.", src_type->description()); + auto builder = _current_context()->builder.get(); + switch (src_type->element()->tag()) { + case Type::Tag::BOOL: { + switch (src_type->dimension()) { + case 2u: return _create_stack_variable( + builder->CreateZExt( + builder->CreateLoad(_create_type(src_type), p_src, "cast.bool2.to.uint2.src"), + _create_type(Type::of()), "cast.bool2.to.int2.cast"), + "cast.bool2.to.uint2.addr"); + case 3u: return _create_stack_variable( + builder->CreateZExt( + builder->CreateLoad(_create_type(src_type), p_src, "cast.bool3.to.uint3.src"), + _create_type(Type::of()), "cast.bool3.to.uint3.cast"), + "cast.bool3.to.uint3.addr"); + case 4u: return _create_stack_variable( + builder->CreateZExt( + builder->CreateLoad(_create_type(src_type), p_src, "cast.bool4.to.uint4.src"), + _create_type(Type::of()), "cast.bool4.to.uint4.cast"), + "cast.bool4.to.uint4.addr"); + default: break; + } + break; + } + case Type::Tag::FLOAT: { + switch (src_type->dimension()) { + case 2u: return _create_stack_variable( + builder->CreateFPToUI( + builder->CreateLoad(_create_type(src_type), p_src, "cast.float2.to.uint2.src"), + _create_type(Type::of()), "cast.float2.to.uint2.cast"), + "cast.float2.to.uint2.addr"); + case 3u: return _create_stack_variable( + builder->CreateFPToUI( + builder->CreateLoad(_create_type(src_type), p_src, "cast.float3.to.uint3.src"), + _create_type(Type::of()), "cast.float3.to.uint3.cast"), + "cast.float3.to.uint3.addr"); + case 4u: return _create_stack_variable( + builder->CreateFPToUI( + builder->CreateLoad(_create_type(src_type), p_src, "cast.float4.to.uint4.src"), + _create_type(Type::of()), "cast.float4.to.uint4.cast"), + "cast.float4.to.uint4.addr"); + default: break; + } + break; + } + case Type::Tag::INT: + case Type::Tag::UINT: return p_src; + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid conversion: {} to uint vector.", + src_type->description()); +} + +::llvm::Value *LLVMCodegen::_scalar_to_vector(const Type *dst_type, const Type *src_type, ::llvm::Value *p_src) noexcept { + LUISA_ASSERT(dst_type->is_vector(), "Invalid destination type: {}.", dst_type->description()); + LUISA_ASSERT(src_type->is_scalar(), "Invalid source type: {}.", src_type->description()); + if (*dst_type->element() != *src_type) { + return _scalar_to_vector(dst_type, dst_type->element(), + _builtin_static_cast(dst_type->element(), src_type, p_src)); + } + auto builder = _current_context()->builder.get(); + auto src = builder->CreateLoad(_create_type(src_type), p_src, "cast.scalar.to.vector.src"); + switch (src_type->tag()) { + case Type::Tag::BOOL: + case Type::Tag::FLOAT: + case Type::Tag::INT: + case Type::Tag::UINT: return _create_stack_variable( + builder->CreateVectorSplat(dst_type->dimension(), src, "cast.scalar.to.vector.splat"), + "cast.scalar.to.vector.addr"); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid conversion: {} to vector.", + src_type->description()); +} + +::llvm::Value *LLVMCodegen::_vector_to_vector(const Type *dst_type, const Type *src_type, ::llvm::Value *p_src) noexcept { + LUISA_ASSERT(src_type->is_vector(), "Invalid source type: {}.", src_type->description()); + LUISA_ASSERT(dst_type->is_vector(), "Invalid destination type: {}.", dst_type->description()); + auto builder = _current_context()->builder.get(); + if (dst_type->dimension() == 2u && src_type->dimension() > 2u) { + auto src = builder->CreateLoad(_create_type(src_type), p_src, "cast.vector.to.vector.src"); + auto shuffle = builder->CreateShuffleVector(src, {0, 1}, "cast.vector.to.vector.shuffle"); + return _vector_to_vector( + dst_type, Type::from(luisa::format("vector<{},2>", src_type->element()->description())), + _create_stack_variable(shuffle, "cast.vector.to.vector.addr")); + } + switch (dst_type->element()->tag()) { + case Type::Tag::BOOL: return _vector_to_bool_vector(src_type, p_src); + case Type::Tag::FLOAT: return _vector_to_float_vector(src_type, p_src); + case Type::Tag::INT: return _vector_to_int_vector(src_type, p_src); + case Type::Tag::UINT: return _vector_to_uint_vector(src_type, p_src); + default: break; + } + return nullptr; +} + +::llvm::Value *LLVMCodegen::_scalar_to_matrix(const Type *dst_type, const Type *src_type, ::llvm::Value *p_src) noexcept { + LUISA_ASSERT(dst_type->is_matrix(), "Invalid destination type: {}.", dst_type->description()); + LUISA_ASSERT(src_type->is_scalar(), "Invalid source type: {}.", src_type->description()); + auto p_src_cvt = _scalar_to_float(src_type, p_src); + auto zero = _create_stack_variable(_literal(0.f), "zero"); + switch (dst_type->dimension()) { + case 2u: return _make_float2x2( + _make_float2(p_src_cvt, zero), + _make_float2(zero, p_src_cvt)); + case 3u: return _make_float3x3( + _make_float3(p_src_cvt, zero, zero), + _make_float3(zero, p_src_cvt, zero), + _make_float3(zero, zero, p_src_cvt)); + case 4u: return _make_float4x4( + _make_float4(p_src_cvt, zero, zero, zero), + _make_float4(zero, p_src_cvt, zero, zero), + _make_float4(zero, zero, p_src_cvt, zero), + _make_float4(zero, zero, zero, p_src_cvt)); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid conversion: {} to matrix.", + src_type->description()); +} + +::llvm::Value *LLVMCodegen::_matrix_to_matrix(const Type *dst_type, const Type *src_type, ::llvm::Value *p_src) noexcept { + LUISA_ASSERT(src_type->is_matrix(), "Invalid source type: {}.", src_type->description()); + LUISA_ASSERT(dst_type->is_matrix(), "Invalid destination type: {}.", dst_type->description()); + LUISA_ASSERT(src_type->dimension() == dst_type->dimension(), "Invalid conversion from '{}' to '{}'.", + src_type->description(), dst_type->description()); + auto builder = _current_context()->builder.get(); + auto matrix_type = _create_type(dst_type); + auto zero = _create_stack_variable(_literal(0.f), "zero"); + auto one = _create_stack_variable(_literal(1.f), "one"); + switch (src_type->dimension()) { + case 2u: { + if (dst_type->dimension() == 2u) { return p_src; } + auto col_type = _create_type(Type::of()); + auto m0 = builder->CreateLoad( + col_type, builder->CreateStructGEP(matrix_type, p_src, 0, "cast.matrix.to.matrix.m0.addr"), + "cast.matrix.to.matrix.m0"); + auto m1 = builder->CreateLoad( + col_type, builder->CreateStructGEP(matrix_type, p_src, 1, "cast.matrix.to.matrix.m1.addr"), + "cast.matrix.to.matrix.m1"); + auto m00 = _create_stack_variable( + builder->CreateExtractElement(m0, static_cast(0u), "cast.matrix.to.matrix.m00"), + "cast.matrix.to.matrix.m00.addr"); + auto m01 = _create_stack_variable( + builder->CreateExtractElement(m0, static_cast(1u), "cast.matrix.to.matrix.m01"), + "cast.matrix.to.matrix.m01.addr"); + auto m10 = _create_stack_variable( + builder->CreateExtractElement(m1, static_cast(0u), "cast.matrix.to.matrix.m10"), + "cast.matrix.to.matrix.m10.addr"); + auto m11 = _create_stack_variable( + builder->CreateExtractElement(m1, static_cast(1u), "cast.matrix.to.matrix.m11"), + "cast.matrix.to.matrix.m11.addr"); + if (dst_type->dimension() == 3u) { + return _make_float3x3( + _make_float3(m00, m01, zero), + _make_float3(m10, m11, zero), + _make_float3(zero, zero, one)); + } + if (dst_type->dimension() == 4u) { + return _make_float4x4( + _make_float4(m00, m01, zero, zero), + _make_float4(m10, m11, zero, zero), + _make_float4(zero, zero, one, zero), + _make_float4(zero, zero, zero, one)); + } + break; + } + case 3u: { + if (dst_type->dimension() == 3u) { return p_src; } + auto col_type = _create_type(Type::of()); + auto m0 = builder->CreateLoad( + col_type, builder->CreateStructGEP(matrix_type, p_src, 0, "cast.matrix.to.matrix.m0.addr"), + "cast.matrix.to.matrix.m0"); + auto m1 = builder->CreateLoad( + col_type, builder->CreateStructGEP(matrix_type, p_src, 1, "cast.matrix.to.matrix.m1.addr"), + "cast.matrix.to.matrix.m1"); + auto m2 = builder->CreateLoad( + col_type, builder->CreateStructGEP(matrix_type, p_src, 2, "cast.matrix.to.matrix.m2.addr"), + "cast.matrix.to.matrix.m2"); + auto m00 = _create_stack_variable( + builder->CreateExtractElement(m0, static_cast(0u), "cast.matrix.to.matrix.m00"), + "cast.matrix.to.matrix.m00.addr"); + auto m01 = _create_stack_variable( + builder->CreateExtractElement(m0, static_cast(1u), "cast.matrix.to.matrix.m01"), + "cast.matrix.to.matrix.m01.addr"); + auto m02 = _create_stack_variable( + builder->CreateExtractElement(m0, static_cast(2u), "cast.matrix.to.matrix.m02"), + "cast.matrix.to.matrix.m02.addr"); + auto m10 = _create_stack_variable( + builder->CreateExtractElement(m1, static_cast(0u), "cast.matrix.to.matrix.m10"), + "cast.matrix.to.matrix.m10.addr"); + auto m11 = _create_stack_variable( + builder->CreateExtractElement(m1, static_cast(1u), "cast.matrix.to.matrix.m11"), + "cast.matrix.to.matrix.m11.addr"); + auto m12 = _create_stack_variable( + builder->CreateExtractElement(m1, static_cast(2u), "cast.matrix.to.matrix.m12"), + "cast.matrix.to.matrix.m12.addr"); + auto m20 = _create_stack_variable( + builder->CreateExtractElement(m2, static_cast(0u), "cast.matrix.to.matrix.m20"), + "cast.matrix.to.matrix.m20.addr"); + auto m21 = _create_stack_variable( + builder->CreateExtractElement(m2, static_cast(1u), "cast.matrix.to.matrix.m21"), + "cast.matrix.to.matrix.m21.addr"); + auto m22 = _create_stack_variable( + builder->CreateExtractElement(m2, static_cast(2u), "cast.matrix.to.matrix.m22"), + "cast.matrix.to.matrix.m22.addr"); + if (dst_type->dimension() == 2u) { + return _make_float2x2( + _make_float2(m00, m01), + _make_float2(m10, m11)); + } + if (dst_type->dimension() == 4u) { + return _make_float4x4( + _make_float4(m00, m01, m02, zero), + _make_float4(m10, m11, m12, zero), + _make_float4(m20, m21, m22, zero), + _make_float4(zero, zero, zero, one)); + } + break; + } + case 4u: { + if (dst_type->dimension() == 4u) { return p_src; } + auto col_type = _create_type(Type::of()); + auto m0 = builder->CreateLoad( + col_type, builder->CreateStructGEP(matrix_type, p_src, 0, "cast.matrix.to.matrix.m0.addr"), + "cast.matrix.to.matrix.m0"); + auto m1 = builder->CreateLoad( + col_type, builder->CreateStructGEP(matrix_type, p_src, 1, "cast.matrix.to.matrix.m1.addr"), + "cast.matrix.to.matrix.m1"); + auto m2 = builder->CreateLoad( + col_type, builder->CreateStructGEP(matrix_type, p_src, 2, "cast.matrix.to.matrix.m2.addr"), + "cast.matrix.to.matrix.m2"); + auto m3 = builder->CreateLoad( + col_type, builder->CreateStructGEP(matrix_type, p_src, 3, "cast.matrix.to.matrix.m3.addr"), + "cast.matrix.to.matrix.m3"); + auto m00 = _create_stack_variable( + builder->CreateExtractElement(m0, static_cast(0u), "cast.matrix.to.matrix.m00"), + "cast.matrix.to.matrix.m00.addr"); + auto m01 = _create_stack_variable( + builder->CreateExtractElement(m0, static_cast(1u), "cast.matrix.to.matrix.m01"), + "cast.matrix.to.matrix.m01.addr"); + auto m02 = _create_stack_variable( + builder->CreateExtractElement(m0, static_cast(2u), "cast.matrix.to.matrix.m02"), + "cast.matrix.to.matrix.m02.addr"); + auto m03 = _create_stack_variable( + builder->CreateExtractElement(m0, static_cast(3u), "cast.matrix.to.matrix.m03"), + "cast.matrix.to.matrix.m03.addr"); + auto m10 = _create_stack_variable( + builder->CreateExtractElement(m1, static_cast(0u), "cast.matrix.to.matrix.m10"), + "cast.matrix.to.matrix.m10.addr"); + auto m11 = _create_stack_variable( + builder->CreateExtractElement(m1, static_cast(1u), "cast.matrix.to.matrix.m11"), + "cast.matrix.to.matrix.m11.addr"); + auto m12 = _create_stack_variable( + builder->CreateExtractElement(m1, static_cast(2u), "cast.matrix.to.matrix.m12"), + "cast.matrix.to.matrix.m12.addr"); + auto m13 = _create_stack_variable( + builder->CreateExtractElement(m1, static_cast(3u), "cast.matrix.to.matrix.m13"), + "cast.matrix.to.matrix.m13.addr"); + auto m20 = _create_stack_variable( + builder->CreateExtractElement(m2, static_cast(0u), "cast.matrix.to.matrix.m20"), + "cast.matrix.to.matrix.m20.addr"); + auto m21 = _create_stack_variable( + builder->CreateExtractElement(m2, static_cast(1u), "cast.matrix.to.matrix.m21"), + "cast.matrix.to.matrix.m21.addr"); + auto m22 = _create_stack_variable( + builder->CreateExtractElement(m2, static_cast(2u), "cast.matrix.to.matrix.m22"), + "cast.matrix.to.matrix.m22.addr"); + auto m23 = _create_stack_variable( + builder->CreateExtractElement(m2, static_cast(3u), "cast.matrix.to.matrix.m23"), + "cast.matrix.to.matrix.m23.addr"); + auto m30 = _create_stack_variable( + builder->CreateExtractElement(m3, static_cast(0u), "cast.matrix.to.matrix.m30"), + "cast.matrix.to.matrix.m30.addr"); + auto m31 = _create_stack_variable( + builder->CreateExtractElement(m3, static_cast(1u), "cast.matrix.to.matrix.m31"), + "cast.matrix.to.matrix.m31.addr"); + auto m32 = _create_stack_variable( + builder->CreateExtractElement(m3, static_cast(2u), "cast.matrix.to.matrix.m32"), + "cast.matrix.to.matrix.m32.addr"); + auto m33 = _create_stack_variable( + builder->CreateExtractElement(m3, static_cast(3u), "cast.matrix.to.matrix.m33"), + "cast.matrix.to.matrix.m33.addr"); + if (dst_type->dimension() == 2u) { + return _make_float2x2( + _make_float2(m00, m01), + _make_float2(m10, m11)); + } + if (dst_type->dimension() == 3u) { + return _make_float3x3( + _make_float3(m00, m01, m02), + _make_float3(m10, m11, m12), + _make_float3(m20, m21, m22)); + } + break; + } + } + LUISA_ERROR_WITH_LOCATION("Invalid conversion: {} to matrix.", + src_type->description()); +} + +::llvm::Type *LLVMCodegen::_create_type(const Type *t) noexcept { + if (t == nullptr) { return ::llvm::Type::getVoidTy(_context); } + switch (t->tag()) { + case Type::Tag::BOOL: return ::llvm::Type::getInt8Ty(_context); + case Type::Tag::FLOAT: return ::llvm::Type::getFloatTy(_context); + case Type::Tag::INT: [[fallthrough]]; + case Type::Tag::UINT: return ::llvm::Type::getInt32Ty(_context); + case Type::Tag::VECTOR: return ::llvm::VectorType::get( + _create_type(t->element()), t->dimension(), false); + case Type::Tag::MATRIX: return ::llvm::ArrayType::get( + _create_type(Type::from(luisa::format( + "vector<{},{}>", t->element()->description(), t->dimension()))), + t->dimension()); + case Type::Tag::ARRAY: return ::llvm::ArrayType::get( + _create_type(t->element()), t->dimension()); + case Type::Tag::STRUCTURE: { + if (auto iter = _struct_types.find(t->hash()); iter != _struct_types.end()) { + return iter->second.type; + } + auto member_index = 0u; + luisa::vector<::llvm::Type *> field_types; + luisa::vector field_indices; + auto size = 0ul; + for (auto &member : t->members()) { + auto aligned_offset = luisa::align(size, member->alignment()); + if (aligned_offset > size) { + auto padding = ::llvm::ArrayType::get( + ::llvm::Type::getInt8Ty(_context), aligned_offset - size); + field_types.emplace_back(padding); + member_index++; + } + auto member_type = _create_type(member); + field_types.emplace_back(member_type); + field_indices.emplace_back(member_index++); + size = aligned_offset + member->size(); + } + if (t->size() > size) {// last padding + auto padding = ::llvm::ArrayType::get( + ::llvm::Type::getInt8Ty(_context), t->size() - size); + field_types.emplace_back(padding); + } + ::llvm::ArrayRef<::llvm::Type *> fields_ref{field_types.data(), field_types.size()}; + auto struct_type = ::llvm::StructType::get(_context, fields_ref); + _struct_types.emplace(t->hash(), LLVMStruct{struct_type, std::move(field_indices)}); + return struct_type; + } + case Type::Tag::BUFFER: return ::llvm::PointerType::get(_create_type(t->element()), 0); + case Type::Tag::TEXTURE: return ::llvm::StructType::get( + ::llvm::Type::getInt64Ty(_context), ::llvm::Type::getInt64Ty(_context)); + case Type::Tag::BINDLESS_ARRAY: return _bindless_item_type()->getPointerTo(); + case Type::Tag::ACCEL: return ::llvm::StructType::get( + ::llvm::Type::getInt64Ty(_context), + _create_type(Type::of())->getPointerTo()); + } + LUISA_ERROR_WITH_LOCATION("Invalid type: {}.", t->description()); +} + +::llvm::Type *LLVMCodegen::_bindless_item_type() noexcept { + return ::llvm::StructType::get( + ::llvm::Type::getInt8PtrTy(_context), + _bindless_texture_type()->getPointerTo(), + _bindless_texture_type()->getPointerTo(), + ::llvm::Type::getInt32Ty(_context), + ::llvm::Type::getInt32Ty(_context)); +} + +::llvm::Type *LLVMCodegen::_bindless_texture_type() noexcept { + return ::llvm::StructType::get( + ::llvm::Type::getInt64Ty(_context), + ::llvm::FixedVectorType::get(::llvm::Type::getInt16Ty(_context), 4)); +} + +}// namespace luisa::compute::llvm diff --git a/src/backends/fallback/llvm_codegen_value.cpp b/src/backends/fallback/llvm_codegen_value.cpp new file mode 100644 index 000000000..9cacc7ed6 --- /dev/null +++ b/src/backends/fallback/llvm_codegen_value.cpp @@ -0,0 +1,361 @@ +// +// Created by Mike Smith on 2022/5/23. +// + +#pragma clang diagnostic push +#pragma ide diagnostic ignored "cppcoreguidelines-pro-type-static-cast-downcast" + +#include + +#pragma clang diagnostic push +#pragma ide diagnostic ignored "cppcoreguidelines-pro-type-static-cast-downcast" + +namespace luisa::compute::fallback { + +::llvm::Value *LLVMCodegen::_literal(int x) noexcept { + return ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(_context), x); +} + +::llvm::Value *LLVMCodegen::_literal(uint x) noexcept { + return ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(_context), x); +} + +::llvm::Value *LLVMCodegen::_literal(bool x) noexcept { + return ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(_context), + static_cast(x)); +} + +::llvm::Value *LLVMCodegen::_literal(float x) noexcept { + return ::llvm::ConstantFP::get(::llvm::Type::getFloatTy(_context), x); +} + +::llvm::Value *LLVMCodegen::_literal(int2 x) noexcept { + return _literal(make_uint2(x)); +} + +::llvm::Value *LLVMCodegen::_literal(uint2 x) noexcept { + return ::llvm::ConstantVector::get({::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(_context), x.x), + ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(_context), x.y)}); +} + +::llvm::Value *LLVMCodegen::_literal(bool2 x) noexcept { + return ::llvm::ConstantVector::get({::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(_context), + static_cast(x.x)), + ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(_context), + static_cast(x.y))}); +} + +::llvm::Value *LLVMCodegen::_literal(float2 x) noexcept { + return ::llvm::ConstantVector::get({::llvm::ConstantFP::get(::llvm::Type::getFloatTy(_context), x.x), + ::llvm::ConstantFP::get(::llvm::Type::getFloatTy(_context), x.y)}); +} + +::llvm::Value *LLVMCodegen::_literal(int3 x) noexcept { + return _literal(make_uint3(x)); +} + +::llvm::Value *LLVMCodegen::_literal(uint3 x) noexcept { + return ::llvm::ConstantVector::get({::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(_context), x.x), + ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(_context), x.y), + ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(_context), x.z)}); +} + +::llvm::Value *LLVMCodegen::_literal(bool3 x) noexcept { + return ::llvm::ConstantVector::get({::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(_context), + static_cast(x.x)), + ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(_context), + static_cast(x.y)), + ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(_context), + static_cast(x.z))}); +} + +::llvm::Value *LLVMCodegen::_literal(float3 x) noexcept { + return ::llvm::ConstantVector::get({::llvm::ConstantFP::get(::llvm::Type::getFloatTy(_context), x.x), + ::llvm::ConstantFP::get(::llvm::Type::getFloatTy(_context), x.y), + ::llvm::ConstantFP::get(::llvm::Type::getFloatTy(_context), x.z)}); +} + +::llvm::Value *LLVMCodegen::_literal(int4 x) noexcept { + return _literal(make_uint4(x)); +} + +::llvm::Value *LLVMCodegen::_literal(uint4 x) noexcept { + return ::llvm::ConstantVector::get({::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(_context), x.x), + ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(_context), x.y), + ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(_context), x.z), + ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(_context), x.w)}); +} + +::llvm::Value *LLVMCodegen::_literal(bool4 x) noexcept { + return ::llvm::ConstantVector::get({::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(_context), + static_cast(x.x)), + ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(_context), + static_cast(x.y)), + ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(_context), + static_cast(x.z)), + ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(_context), + static_cast(x.w))}); +} + +::llvm::Value *LLVMCodegen::_literal(float4 x) noexcept { + return ::llvm::ConstantVector::get({::llvm::ConstantFP::get(::llvm::Type::getFloatTy(_context), x.x), + ::llvm::ConstantFP::get(::llvm::Type::getFloatTy(_context), x.y), + ::llvm::ConstantFP::get(::llvm::Type::getFloatTy(_context), x.z), + ::llvm::ConstantFP::get(::llvm::Type::getFloatTy(_context), x.w)}); +} + +::llvm::Value *LLVMCodegen::_literal(float2x2 x) noexcept { + return ::llvm::ConstantStruct::get( + static_cast<::llvm::StructType *>(_create_type(Type::of())), + static_cast<::llvm::Constant *>(_literal(x[0])), + static_cast<::llvm::Constant *>(_literal(x[1]))); +} + +::llvm::Value *LLVMCodegen::_literal(float3x3 x) noexcept { + return ::llvm::ConstantStruct::get( + static_cast<::llvm::StructType *>(_create_type(Type::of())), + static_cast<::llvm::Constant *>(_literal(x[0])), + static_cast<::llvm::Constant *>(_literal(x[1])), + static_cast<::llvm::Constant *>(_literal(x[2]))); +} + +::llvm::Value *LLVMCodegen::_literal(float4x4 x) noexcept { + return ::llvm::ConstantStruct::get( + static_cast<::llvm::StructType *>(_create_type(Type::of())), + static_cast<::llvm::Constant *>(_literal(x[0])), + static_cast<::llvm::Constant *>(_literal(x[1])), + static_cast<::llvm::Constant *>(_literal(x[2])), + static_cast<::llvm::Constant *>(_literal(x[3]))); +} + +::llvm::Value *LLVMCodegen::_create_alloca(::llvm::Type *t, luisa::string_view name) noexcept { + auto ctx = _current_context(); + auto p = ctx->builder->CreateAlloca(t, nullptr, ::llvm::StringRef{name.data(), name.size()}); + p->setAlignment(::llvm::Align{16u}); + return p; +} + +::llvm::Value *LLVMCodegen::_create_stack_variable(::llvm::Value *x, luisa::string_view name) noexcept { + auto builder = _current_context()->builder.get(); + auto t = x->getType(); + if (t->isIntegerTy(1)) { + // special handling for int1 + return _create_stack_variable( + builder->CreateZExt(x, builder->getInt8Ty(), "bit_to_bool"), name); + } + if (t->isVectorTy() && static_cast<::llvm::VectorType *>(t)->getElementType()->isIntegerTy(1)) { + // special handling for int1 vector + auto dim = static_cast<::llvm::VectorType *>(t)->getElementCount(); + auto dst_type = ::llvm::VectorType::get(builder->getInt8Ty(), dim); + return _create_stack_variable(builder->CreateZExt(x, dst_type, "bit_to_bool"), name); + } + auto p = _create_alloca(t, name); + builder->CreateStore(x, p); + return p; +} + +::llvm::Value *LLVMCodegen::_create_constant(ConstantData c) noexcept { + auto key = c.hash(); + if (auto iter = _constants.find(key); iter != _constants.end()) { + return iter->second; + } + auto value = luisa::visit( + [this](auto s) noexcept { + std::vector<::llvm::Constant *> elements; + elements.reserve(s.size()); + for (auto x : s) { elements.push_back(static_cast<::llvm::Constant *>(_literal(x))); } + using T = std::remove_cvref_t; + auto array_type = ::llvm::ArrayType::get( + _create_type(Type::of()), static_cast(elements.size())); + return ::llvm::ConstantArray::get(array_type, elements); + }, + c.view()); + auto name = luisa::format("constant_{:016x}", key); + _module->getOrInsertGlobal(::llvm::StringRef{name.data(), name.size()}, value->getType()); + auto global = _module->getNamedGlobal(::llvm::StringRef{name.data(), name.size()}); + global->setConstant(true); + global->setLinkage(::llvm::GlobalValue::InternalLinkage); + global->setInitializer(value); + global->setUnnamedAddr(::llvm::GlobalValue::UnnamedAddr::Global); + return _constants.emplace(key, static_cast<::llvm::Value *>(global)).first->second; +} + +::llvm::Value *LLVMCodegen::_make_int2(::llvm::Value *px, ::llvm::Value *py) noexcept { + auto b = _current_context()->builder.get(); + auto x = b->CreateLoad(b->getInt32Ty(), px, "v.x"); + auto y = b->CreateLoad(b->getInt32Ty(), py, "v.y"); + auto v = static_cast<::llvm::Value *>(::llvm::UndefValue::get( + _create_type(Type::of()))); + v = b->CreateInsertElement(v, x, static_cast(0u), "int2.x"); + v = b->CreateInsertElement(v, y, static_cast(1u), "int2.xy"); + return _create_stack_variable(v, "int2.addr"); +} + +::llvm::Value *LLVMCodegen::_make_int3(::llvm::Value *px, ::llvm::Value *py, ::llvm::Value *pz) noexcept { + auto b = _current_context()->builder.get(); + auto x = b->CreateLoad(b->getInt32Ty(), px, "v.x"); + auto y = b->CreateLoad(b->getInt32Ty(), py, "v.y"); + auto z = b->CreateLoad(b->getInt32Ty(), pz, "v.z"); + auto v = static_cast<::llvm::Value *>(::llvm::UndefValue::get( + _create_type(Type::of()))); + v = b->CreateInsertElement(v, x, static_cast(0u), "int3.x"); + v = b->CreateInsertElement(v, y, static_cast(1u), "int3.xy"); + v = b->CreateInsertElement(v, z, static_cast(2u), "int3.xyz"); + return _create_stack_variable(v, "int3.addr"); +} + +::llvm::Value *LLVMCodegen::_make_int4(::llvm::Value *px, ::llvm::Value *py, ::llvm::Value *pz, ::llvm::Value *pw) noexcept { + auto b = _current_context()->builder.get(); + auto x = b->CreateLoad(b->getInt32Ty(), px, "v.x"); + auto y = b->CreateLoad(b->getInt32Ty(), py, "v.y"); + auto z = b->CreateLoad(b->getInt32Ty(), pz, "v.z"); + auto w = b->CreateLoad(b->getInt32Ty(), pw, "v.w"); + auto v = static_cast<::llvm::Value *>(::llvm::UndefValue::get( + _create_type(Type::of()))); + v = b->CreateInsertElement(v, x, static_cast(0u), "int4.x"); + v = b->CreateInsertElement(v, y, static_cast(1u), "int4.xy"); + v = b->CreateInsertElement(v, z, static_cast(2u), "int4.xyz"); + v = b->CreateInsertElement(v, w, static_cast(3u), "int4.xyzw"); + return _create_stack_variable(v, "int4.addr"); +} + +::llvm::Value *LLVMCodegen::_make_bool2(::llvm::Value *px, ::llvm::Value *py) noexcept { + auto b = _current_context()->builder.get(); + auto x = b->CreateLoad(b->getInt8Ty(), px, "v.x"); + auto y = b->CreateLoad(b->getInt8Ty(), py, "v.y"); + auto v = static_cast<::llvm::Value *>(::llvm::UndefValue::get( + _create_type(Type::of()))); + v = b->CreateInsertElement(v, x, static_cast(0u), "bool2.x"); + v = b->CreateInsertElement(v, y, static_cast(1u), "bool2.xy"); + return _create_stack_variable(v, "bool2.addr"); +} + +::llvm::Value *LLVMCodegen::_make_bool3(::llvm::Value *px, ::llvm::Value *py, ::llvm::Value *pz) noexcept { + auto b = _current_context()->builder.get(); + auto x = b->CreateLoad(b->getInt8Ty(), px, "v.x"); + auto y = b->CreateLoad(b->getInt8Ty(), py, "v.y"); + auto z = b->CreateLoad(b->getInt8Ty(), pz, "v.z"); + auto v = static_cast<::llvm::Value *>(::llvm::UndefValue::get( + _create_type(Type::of()))); + v = b->CreateInsertElement(v, x, static_cast(0u), "bool3.x"); + v = b->CreateInsertElement(v, y, static_cast(1u), "bool3.xy"); + v = b->CreateInsertElement(v, z, static_cast(2u), "bool3.xyz"); + return _create_stack_variable(v, "bool3.addr"); +} + +::llvm::Value *LLVMCodegen::_make_bool4(::llvm::Value *px, ::llvm::Value *py, ::llvm::Value *pz, ::llvm::Value *pw) noexcept { + auto b = _current_context()->builder.get(); + auto x = b->CreateLoad(b->getInt8Ty(), px, "v.x"); + auto y = b->CreateLoad(b->getInt8Ty(), py, "v.y"); + auto z = b->CreateLoad(b->getInt8Ty(), pz, "v.z"); + auto w = b->CreateLoad(b->getInt8Ty(), pw, "v.w"); + auto v = static_cast<::llvm::Value *>(::llvm::UndefValue::get( + _create_type(Type::of()))); + v = b->CreateInsertElement(v, x, static_cast(0u), "bool4.x"); + v = b->CreateInsertElement(v, y, static_cast(1u), "bool4.xy"); + v = b->CreateInsertElement(v, z, static_cast(2u), "bool4.xyz"); + v = b->CreateInsertElement(v, w, static_cast(3u), "bool4.xyzw"); + return _create_stack_variable(v, "bool4.addr"); +} + +::llvm::Value *LLVMCodegen::_make_float2(::llvm::Value *px, ::llvm::Value *py) noexcept { + auto b = _current_context()->builder.get(); + auto x = b->CreateLoad(b->getFloatTy(), px, "v.x"); + auto y = b->CreateLoad(b->getFloatTy(), py, "v.y"); + auto v = static_cast<::llvm::Value *>(::llvm::UndefValue::get( + _create_type(Type::of()))); + v = b->CreateInsertElement(v, x, static_cast(0u), "float2.x"); + v = b->CreateInsertElement(v, y, static_cast(1u), "float2.xy"); + return _create_stack_variable(v, "float2.addr"); +} + +::llvm::Value *LLVMCodegen::_make_float3(::llvm::Value *px, ::llvm::Value *py, ::llvm::Value *pz) noexcept { + auto b = _current_context()->builder.get(); + auto x = b->CreateLoad(b->getFloatTy(), px, "v.x"); + auto y = b->CreateLoad(b->getFloatTy(), py, "v.y"); + auto z = b->CreateLoad(b->getFloatTy(), pz, "v.z"); + auto v = static_cast<::llvm::Value *>(::llvm::UndefValue::get( + _create_type(Type::of()))); + v = b->CreateInsertElement(v, x, static_cast(0u), "float3.x"); + v = b->CreateInsertElement(v, y, static_cast(1u), "float3.xy"); + v = b->CreateInsertElement(v, z, static_cast(2u), "float3.xyz"); + return _create_stack_variable(v, "float3.addr"); +} + +::llvm::Value *LLVMCodegen::_make_float4(::llvm::Value *px, ::llvm::Value *py, ::llvm::Value *pz, ::llvm::Value *pw) noexcept { + auto b = _current_context()->builder.get(); + auto x = b->CreateLoad(b->getFloatTy(), px, "v.x"); + auto y = b->CreateLoad(b->getFloatTy(), py, "v.y"); + auto z = b->CreateLoad(b->getFloatTy(), pz, "v.z"); + auto w = b->CreateLoad(b->getFloatTy(), pw, "v.w"); + auto v = static_cast<::llvm::Value *>(::llvm::UndefValue::get( + _create_type(Type::of()))); + v = b->CreateInsertElement(v, x, static_cast(0u), "float4.x"); + v = b->CreateInsertElement(v, y, static_cast(1u), "float4.xy"); + v = b->CreateInsertElement(v, z, static_cast(2u), "float4.xyz"); + v = b->CreateInsertElement(v, w, static_cast(3u), "float4.xyzw"); + return _create_stack_variable(v, "float4.addr"); +} + +::llvm::Value *LLVMCodegen::_make_float2x2(::llvm::Value *p0, ::llvm::Value *p1) noexcept { + auto b = _current_context()->builder.get(); + auto t = _create_type(Type::of()); + auto m = _create_alloca(t, "float2x2.addr"); + auto m0 = b->CreateStructGEP(t, m, 0u, "float2x2.a"); + auto m1 = b->CreateStructGEP(t, m, 1u, "float2x2.b"); + auto col_type = _create_type(Type::of()); + b->CreateStore(b->CreateLoad(col_type, p0, "m.a"), m0); + b->CreateStore(b->CreateLoad(col_type, p1, "m.b"), m1); + return m; +} + +::llvm::Value *LLVMCodegen::_make_float3x3(::llvm::Value *p0, ::llvm::Value *p1, ::llvm::Value *p2) noexcept { + auto b = _current_context()->builder.get(); + auto t = _create_type(Type::of()); + auto m = _create_alloca(t, "float3x3.addr"); + auto m0 = b->CreateStructGEP(t, m, 0u, "float3x3.a"); + auto m1 = b->CreateStructGEP(t, m, 1u, "float3x3.b"); + auto m2 = b->CreateStructGEP(t, m, 2u, "float3x3.c"); + auto col_type = _create_type(Type::of()); + b->CreateStore(b->CreateLoad(col_type, p0, "m.a"), m0); + b->CreateStore(b->CreateLoad(col_type, p1, "m.b"), m1); + b->CreateStore(b->CreateLoad(col_type, p2, "m.c"), m2); + return m; +} + +::llvm::Value *LLVMCodegen::_make_float4x4(::llvm::Value *p0, ::llvm::Value *p1, ::llvm::Value *p2, ::llvm::Value *p3) noexcept { + auto b = _current_context()->builder.get(); + auto t = _create_type(Type::of()); + auto m = _create_alloca(t, "float4x4.addr"); + auto m0 = b->CreateStructGEP(t, m, 0u, "float4x4.a"); + auto m1 = b->CreateStructGEP(t, m, 1u, "float4x4.b"); + auto m2 = b->CreateStructGEP(t, m, 2u, "float4x4.c"); + auto m3 = b->CreateStructGEP(t, m, 3u, "float4x4.d"); + auto col_type = _create_type(Type::of()); + b->CreateStore(b->CreateLoad(col_type, p0, "m.a"), m0); + b->CreateStore(b->CreateLoad(col_type, p1, "m.b"), m1); + b->CreateStore(b->CreateLoad(col_type, p2, "m.c"), m2); + b->CreateStore(b->CreateLoad(col_type, p3, "m.d"), m3); + return m; +} + +luisa::string LLVMCodegen::_variable_name(Variable v) const noexcept { + switch (v.tag()) { + case Variable::Tag::LOCAL: return luisa::format("v{}.local", v.uid()); + case Variable::Tag::SHARED: return luisa::format("v{}.shared", v.uid()); + case Variable::Tag::REFERENCE: return luisa::format("v{}.ref", v.uid()); + case Variable::Tag::BUFFER: return luisa::format("v{}.buffer", v.uid()); + case Variable::Tag::TEXTURE: return luisa::format("v{}.texture", v.uid()); + case Variable::Tag::BINDLESS_ARRAY: return luisa::format("v{}.bindless", v.uid()); + case Variable::Tag::ACCEL: return luisa::format("v{}.accel", v.uid()); + case Variable::Tag::THREAD_ID: return "thread.id"; + case Variable::Tag::BLOCK_ID: return "block.id"; + case Variable::Tag::DISPATCH_ID: return "dispatch.id"; + case Variable::Tag::DISPATCH_SIZE: return "dispatch.size"; + } + LUISA_ERROR_WITH_LOCATION("Invalid variable."); +} + +}// namespace luisa::compute::llvm + +#pragma clang diagnostic pop diff --git a/src/backends/fallback/llvm_event.cpp b/src/backends/fallback/llvm_event.cpp new file mode 100644 index 000000000..47c81b476 --- /dev/null +++ b/src/backends/fallback/llvm_event.cpp @@ -0,0 +1,25 @@ +// +// Created by Mike Smith on 2022/2/7. +// + +#include + +namespace luisa::compute::fallback { + +void LLVMEvent::wait() const noexcept { + if (auto f = future(); f.valid()) [[likely]] { + f.wait(); + } +} + +void LLVMEvent::signal(std::shared_future future) noexcept { + std::scoped_lock lock{_mutex}; + _future = std::move(future); +} + +std::shared_future LLVMEvent::future() const noexcept { + std::scoped_lock lock{_mutex}; + return _future; +} + +}// namespace luisa::compute::llvm diff --git a/src/backends/fallback/llvm_event.h b/src/backends/fallback/llvm_event.h new file mode 100644 index 000000000..17ba4efc8 --- /dev/null +++ b/src/backends/fallback/llvm_event.h @@ -0,0 +1,23 @@ +// +// Created by Mike Smith on 2022/2/7. +// + +#pragma once + +#include + +namespace luisa::compute::fallback { + +class LLVMEvent { + +private: + mutable std::mutex _mutex; + std::shared_future _future; + +public: + void wait() const noexcept; + void signal(std::shared_future future) noexcept; + [[nodiscard]] std::shared_future future() const noexcept; +}; + +}// namespace luisa::compute::llvm diff --git a/src/backends/fallback/llvm_shader.cpp b/src/backends/fallback/llvm_shader.cpp new file mode 100644 index 000000000..f8099cca3 --- /dev/null +++ b/src/backends/fallback/llvm_shader.cpp @@ -0,0 +1,204 @@ +// +// Created by Mike Smith on 2022/2/11. +// + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define LC_LLVM_CODEGEN_MAGIC ".codegen.0004" + +namespace luisa::compute::fallback { + +LLVMShader::LLVMShader(LLVMDevice *device, Function func) noexcept + : _name{luisa::format("kernel.{:016x}", func.hash())} { + // compute argument offsets + _argument_offsets.reserve(func.arguments().size()); + for (auto &&arg : func.arguments()) { + auto aligned_offset = luisa::align(_argument_buffer_size, 16u); + _argument_offsets.emplace(arg.uid(), aligned_offset); + if (arg.type()->is_buffer()) { + _argument_buffer_size = aligned_offset + LLVMCodegen::buffer_handle_size; + } else if (arg.type()->is_texture()) { + _argument_buffer_size = aligned_offset + LLVMCodegen::texture_handle_size; + } else if (arg.type()->is_accel()) { + _argument_buffer_size = aligned_offset + LLVMCodegen::accel_handle_size; + } else if (arg.type()->is_bindless_array()) { + _argument_buffer_size = aligned_offset + LLVMCodegen::bindless_array_handle_size; + } else { + _argument_buffer_size = aligned_offset + arg.type()->size(); + } + } + _argument_buffer_size = luisa::align(_argument_buffer_size, 16u); + _argument_buffer_size += 16u; // (trampoline, callbacks) + _argument_buffer_size = luisa::align(_argument_buffer_size, 16u); + + for (auto s : func.shared_variables()) { + _shared_memory_size = luisa::align(_shared_memory_size, s.type()->alignment()); + _shared_memory_size += s.type()->size(); + } + _shared_memory_size = luisa::align(_shared_memory_size, 16u); + + LUISA_VERBOSE_WITH_LOCATION( + "Generating kernel '{}' with {} bytes of " + "argument buffer and {} bytes of shared memory.", + _name, _argument_buffer_size, _shared_memory_size); + + auto jit = device->jit(); + auto main_name = luisa::format("kernel.{:016x}.main", func.hash()); + auto lookup_kernel_entry = [name = luisa::string_view{main_name}, jit, device]() noexcept -> ::llvm::Expected { + std::scoped_lock lock{device->jit_mutex()}; + auto addr = jit->lookup(::llvm::StringRef{name.data(), name.size()}); + if (addr) { +#if LLVM_VERSION_MAJOR >= 15 + return addr->toPtr(); +#else + return reinterpret_cast(addr->getAddress()); +#endif + } + return addr.takeError(); + }; + + // try to find the kernel entry in the JIT + if (auto entry = lookup_kernel_entry()) { + LUISA_INFO("Found kernel '{}' in JIT.", _name); + _kernel_entry = *entry; + return; + } + + // codegen + std::error_code ec; + auto context = std::make_unique<::llvm::LLVMContext>(); + context->setDiagnosticHandlerCallBack([](const ::llvm::DiagnosticInfo &info, void *) noexcept { + if (auto severity = info.getSeverity(); + severity == ::llvm::DS_Error || severity == ::llvm::DS_Warning) { + ::llvm::DiagnosticPrinterRawOStream printer{::llvm::errs()}; + info.print(printer); + printer << '\n'; + } + }); + auto file_path = device->context().cache_directory() / + luisa::format("kernel.llvm.{:016x}.opt.{:016x}.ll", + func.hash(), hash_value(LLVM_VERSION_STRING LC_LLVM_CODEGEN_MAGIC)); + ::llvm::SMDiagnostic diagnostic; + auto module = ::llvm::parseIRFile(file_path.string(), diagnostic, *context); + Clock clk; + auto machine = device->target_machine(); + if (module == nullptr) { + LUISA_WARNING_WITH_LOCATION( + "Failed to load LLVM IR from cache: {}.", + diagnostic.getMessage().str()); + LLVMCodegen codegen{*context}; + module = codegen.emit(func); + LUISA_INFO("Codegen: {} ms.", clk.toc()); + if (::llvm::verifyModule(*module, &::llvm::errs())) { + auto error_file_path = device->context().cache_directory() / + luisa::format("kernel.llvm.{:016x}.ll", func.hash()); + auto error_file_path_string = file_path.string(); + ::llvm::raw_fd_ostream file{error_file_path_string, ec}; + if (ec) { + LUISA_WARNING_WITH_LOCATION( + "Failed to create file '{}': {}.", + error_file_path_string, ec.message()); + } else { + LUISA_INFO("Saving LLVM kernel to '{}'.", + error_file_path_string); + module->print(file, nullptr); + } + LUISA_ERROR_WITH_LOCATION("Failed to verify module."); + } + module->setDataLayout(machine->createDataLayout()); + module->setTargetTriple(machine->getTargetTriple().str()); + + // optimize with the new pass manager + ::llvm::LoopAnalysisManager LAM; + ::llvm::FunctionAnalysisManager FAM; + ::llvm::CGSCCAnalysisManager CGAM; + ::llvm::ModuleAnalysisManager MAM; + ::llvm::PipelineTuningOptions PTO; + PTO.LoopInterleaving = true; + PTO.LoopVectorization = true; + PTO.SLPVectorization = true; + PTO.LoopUnrolling = true; + PTO.MergeFunctions = true; + ::llvm::PassBuilder PB{machine, PTO}; + FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); }); + PB.registerModuleAnalyses(MAM); + PB.registerCGSCCAnalyses(CGAM); + PB.registerFunctionAnalyses(FAM); + PB.registerLoopAnalyses(LAM); + PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); + machine->registerPassBuilderCallbacks(PB); + clk.tic(); + auto MPM = PB.buildPerModuleDefaultPipeline(::llvm::OptimizationLevel::O3); + MPM.run(*module, MAM); + LUISA_INFO("Optimize: {} ms.", clk.toc()); + if (::llvm::verifyModule(*module, &::llvm::errs())) { + LUISA_ERROR_WITH_LOCATION("Failed to verify module."); + } + + // dump optimized ir for debugging + { + auto file_path_string = file_path.string(); + ::llvm::raw_fd_ostream file_opt{file_path_string, ec}; + if (ec) { + LUISA_ERROR_WITH_LOCATION( + "Failed to create file '{}': {}.", + file_path_string, ec.message()); + } else { + LUISA_INFO("Saving optimized LLVM kernel to '{}'.", + file_path_string); + module->print(file_opt, nullptr); + } + } + } + + // compile to machine code + clk.tic(); + if (auto error = [jit, device, m = ::llvm::orc::ThreadSafeModule{std::move(module), std::move(context)}]() mutable noexcept { + std::scoped_lock lock{device->jit_mutex()}; + return jit->addIRModule(std::move(m)); + }()) { + ::llvm::handleAllErrors(std::move(error), [](const ::llvm::ErrorInfoBase &err) { + LUISA_WARNING_WITH_LOCATION("LLJIT::addIRModule(): {}", err.message()); + }); + } + if (auto entry = lookup_kernel_entry()) { + _kernel_entry = *entry; + } else { + ::llvm::handleAllErrors(entry.takeError(), [](const ::llvm::ErrorInfoBase &err) { + LUISA_WARNING_WITH_LOCATION("LLJIT::lookup(): {}", err.message()); + }); + LUISA_ERROR_WITH_LOCATION("Failed to find kernel entry."); + } + LUISA_INFO("Compile: {} ms.", clk.toc()); +} + +LLVMShader::~LLVMShader() noexcept = default; + +size_t LLVMShader::argument_offset(uint uid) const noexcept { + if (auto iter = _argument_offsets.find(uid); + iter != _argument_offsets.cend()) [[likely]] { + return iter->second; + } + LUISA_ERROR_WITH_LOCATION("Invalid argument uid {}.", uid); +} + +void LLVMShader::invoke(const std::byte *args, std::byte *shared_mem, + uint3 dispatch_size, uint3 block_id) const noexcept { + _kernel_entry(args, shared_mem, + dispatch_size.x, dispatch_size.y, dispatch_size.z, + block_id.x, block_id.y, block_id.z); +} + +}// namespace luisa::compute::llvm diff --git a/src/backends/fallback/llvm_shader.h b/src/backends/fallback/llvm_shader.h new file mode 100644 index 000000000..4f585b4fa --- /dev/null +++ b/src/backends/fallback/llvm_shader.h @@ -0,0 +1,49 @@ +// +// Created by Mike Smith on 2022/2/11. +// + +#pragma once + +#include +#include +#include +#include + +namespace llvm { +class LLVMContext; +class Module; +class ExecutionEngine; +}// namespace llvm + +namespace luisa::compute::fallback { + +using luisa::compute::detail::FunctionBuilder; +using CpuCallback = FunctionBuilder::CpuCallback; + +class LLVMDevice; + +class LLVMShader { + +public: + using kernel_entry_t = void(const std::byte *, std::byte *, uint, uint, uint, uint, uint, uint); + +private: + luisa::string _name; + luisa::unordered_map _argument_offsets; + kernel_entry_t *_kernel_entry{nullptr}; + size_t _argument_buffer_size{}; + luisa::vector _callbacks; + size_t _shared_memory_size{}; + +public: + LLVMShader(LLVMDevice *device, Function func) noexcept; + ~LLVMShader() noexcept; + [[nodiscard]] auto argument_buffer_size() const noexcept { return _argument_buffer_size; } + [[nodiscard]] auto shared_memory_size() const noexcept { return _shared_memory_size; } + [[nodiscard]] size_t argument_offset(uint uid) const noexcept; + [[nodiscard]] auto callbacks() const noexcept { return _callbacks.data(); } + void invoke(const std::byte *args, std::byte *shared_memory, + uint3 dispatch_size, uint3 block_id) const noexcept; +}; + +}// namespace luisa::compute::llvm diff --git a/src/backends/fallback/thread_pool.cpp b/src/backends/fallback/thread_pool.cpp new file mode 100644 index 000000000..f6500a6c3 --- /dev/null +++ b/src/backends/fallback/thread_pool.cpp @@ -0,0 +1,178 @@ +// +// Created by Mike Smith on 2021/12/23. +// + +#include +#include +#include +#include +#include + +#if (!defined(__clang_major__) || __clang_major__ >= 14) && defined(__cpp_lib_barrier) +#define LUISA_COMPUTE_USE_STD_BARRIER +#endif + +#ifdef LUISA_COMPUTE_USE_STD_BARRIER +#include +#endif + +#include +#include +#include +#include "thread_pool.h" + +namespace luisa { + +namespace detail { + +[[nodiscard]] static auto &is_worker_thread() noexcept { + static thread_local auto is_worker = false; + return is_worker; +} + +[[nodiscard]] static auto &worker_thread_index() noexcept { + static thread_local auto id = 0u; + return id; +} + +static inline void check_not_in_worker_thread(std::string_view f) noexcept { + if (is_worker_thread()) [[unlikely]] { + std::ostringstream oss; + oss << std::this_thread::get_id(); + LUISA_ERROR_WITH_LOCATION( + "Invoking ThreadPool::{}() " + "from worker thread {}.", + f, oss.str()); + } +} + +}// namespace detail + +#ifdef LUISA_COMPUTE_USE_STD_BARRIER +struct Barrier : std::barrier<> { + using std::barrier<>::barrier; +}; +#else +// reference: https://github.com/yohhoy/yamc/blob/master/include/yamc_barrier.hpp +class Barrier { +private: + uint _n; + uint _counter; + uint _phase; + std::condition_variable _cv; + std::mutex _mutex; + +public: + explicit Barrier(uint n) noexcept + : _n{n}, _counter{n}, _phase{0u} {} + void arrive_and_wait() noexcept { + std::unique_lock lock{_mutex}; + auto arrive_phase = _phase; + if (--_counter == 0u) { + _counter = _n; + _phase++; + _cv.notify_all(); + } + while (_phase <= arrive_phase) { + _cv.wait(lock); + } + } +}; +#endif + +struct ThreadPool::Impl { + luisa::vector threads; + luisa::queue> tasks; + std::mutex mutex; + luisa::unique_ptr synchronize_barrier; + luisa::unique_ptr dispatch_barrier; + std::condition_variable cv; + bool should_stop{false}; +}; + +ThreadPool::ThreadPool(size_t num_threads) noexcept + : _impl{luisa::make_unique()} { + if (num_threads == 0u) { + num_threads = std::max( + std::thread::hardware_concurrency(), 1u); + } + _impl->dispatch_barrier = luisa::make_unique(num_threads); + _impl->synchronize_barrier = luisa::make_unique(num_threads + 1u /* main thread */); + _impl->threads.reserve(num_threads); + for (auto i = 0u; i < num_threads; i++) { + _impl->threads.emplace_back(std::thread{[this, i] { + detail::is_worker_thread() = true; + detail::worker_thread_index() = i; + for (;;) { + std::unique_lock lock{_impl->mutex}; + _impl->cv.wait(lock, [this] { return !_impl->tasks.empty() || _impl->should_stop; }); + if (_impl->should_stop && _impl->tasks.empty()) [[unlikely]] { break; } + auto task = std::move(_impl->tasks.front()); + _impl->tasks.pop(); + lock.unlock(); + task(); + } + }}); + } + LUISA_INFO("Created thread pool with {} thread{}.", + num_threads, num_threads == 1u ? "" : "s"); +} + +void ThreadPool::barrier() noexcept { + detail::check_not_in_worker_thread("barrier"); + _dispatch_all([this] { _impl->dispatch_barrier->arrive_and_wait(); }); +} + +void ThreadPool::synchronize() noexcept { + detail::check_not_in_worker_thread("synchronize"); + while (task_count() != 0u) { + _dispatch_all([this] { _impl->synchronize_barrier->arrive_and_wait(); }); + _impl->synchronize_barrier->arrive_and_wait(); + } +} + +void ThreadPool::_dispatch(luisa::function task) noexcept { + { + std::scoped_lock lock{_impl->mutex}; + _impl->tasks.emplace(std::move(task)); + } + _impl->cv.notify_one(); +} + +void ThreadPool::_dispatch_all(luisa::function task, size_t max_threads) noexcept { + { + std::scoped_lock lock{_impl->mutex}; + for (auto i = 0u; i < std::min(_impl->threads.size(), max_threads) - 1u; i++) { + _impl->tasks.emplace(task); + } + _impl->tasks.emplace(std::move(task)); + } + _impl->cv.notify_all(); +} + +ThreadPool::~ThreadPool() noexcept { + { + std::scoped_lock lock{_impl->mutex}; + _impl->should_stop = true; + } + _impl->cv.notify_all(); + for (auto &&t : _impl->threads) { t.join(); } +} + +ThreadPool &ThreadPool::global() noexcept { + static ThreadPool pool; + return pool; +} + +uint ThreadPool::size() const noexcept { + return static_cast(_impl->threads.size()); +} + +uint ThreadPool::worker_thread_index() noexcept { + LUISA_ASSERT(detail::is_worker_thread(), + "ThreadPool::worker_thread_index() " + "called in non-worker thread."); + return detail::worker_thread_index(); +} + +}// namespace luisa diff --git a/src/backends/fallback/thread_pool.h b/src/backends/fallback/thread_pool.h new file mode 100644 index 000000000..c6004eff7 --- /dev/null +++ b/src/backends/fallback/thread_pool.h @@ -0,0 +1,117 @@ +// +// Created by Mike Smith on 2021/12/23. +// + +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace luisa { + +/// Thread pool class +class ThreadPool { + +public: + class Impl; + +private: + luisa::unique_ptr _impl; + std::atomic_uint _task_count; + +private: + void _dispatch(luisa::function task) noexcept; + void _dispatch_all(luisa::function task, size_t max_threads = std::numeric_limits::max()) noexcept; + +public: + /// Create a thread pool with num_threads threads + explicit ThreadPool(size_t num_threads = 0u) noexcept; + ~ThreadPool() noexcept; + ThreadPool(ThreadPool &&) noexcept = delete; + ThreadPool(const ThreadPool &) noexcept = delete; + ThreadPool &operator=(ThreadPool &&) noexcept = delete; + ThreadPool &operator=(const ThreadPool &) noexcept = delete; + /// Return global static ThreadPool instance + [[nodiscard]] static ThreadPool &global() noexcept; + [[nodiscard]] static uint worker_thread_index() noexcept; + +public: + /// Barrier all threads + void barrier() noexcept; + /// Synchronize all threads + void synchronize() noexcept; + /// Return size of threads + [[nodiscard]] uint size() const noexcept; + /// Return count of tasks + [[nodiscard]] uint task_count() const noexcept { return _task_count.load(); } + + /// Run a function async and return future of return value + template + requires std::is_invocable_v + auto async(F f) noexcept { + using R = std::invoke_result_t; + auto promise = luisa::make_shared>( + std::allocator_arg, luisa::allocator{}); + auto future = promise->get_future().share(); + _task_count.fetch_add(1u); + _dispatch([promise = std::move(promise), future, f = std::move(f), this]() mutable noexcept { + if constexpr (std::same_as) { + f(); + promise->set_value(); + } else { + promise->set_value(f()); + } + _task_count.fetch_sub(1u); + }); + return future; + } + + /// Run a function parallel + template + requires std::is_invocable_v + void parallel(uint n, F f) noexcept { + if (n > 0u) { + _task_count.fetch_add(1u); + auto counter = luisa::make_shared(0u); + _dispatch_all( + [=, this]() mutable noexcept { + auto i = 0u; + while ((i = counter->fetch_add(1u)) < n) { f(i); } + if (i == n) { _task_count.fetch_sub(1u); } + }, + n); + } + } + + /// Run a function 2D parallel + template + requires std::is_invocable_v + void parallel(uint nx, uint ny, F f) noexcept { + parallel(nx * ny, [=, f = std::move(f)](auto i) mutable noexcept { + f(i % nx, i / nx); + }); + } + + /// Run a function 3D parallel + template + requires std::is_invocable_v + void parallel(uint nx, uint ny, uint nz, F f) noexcept { + parallel(nx * ny * nz, [=, f = std::move(f)](auto i) mutable noexcept { + f(i % nx, i / nx % ny, i / nx / ny); + }); + } +}; + +/// Run a function async using global ThreadPool +template + requires std::is_invocable_v +inline auto async(F &&f) noexcept { + return ThreadPool::global().async(std::forward(f)); +} + +}// namespace luisa diff --git a/src/tests/test_path_tracing.cpp b/src/tests/test_path_tracing.cpp index 85299cbe8..5c1da2caa 100644 --- a/src/tests/test_path_tracing.cpp +++ b/src/tests/test_path_tracing.cpp @@ -1,341 +1,341 @@ -#include - -#include - -#include -#include - -#include "common/cornell_box.h" - -#define TINYOBJLOADER_IMPLEMENTATION -#include "common/tiny_obj_loader.h" - -using namespace luisa; -using namespace luisa::compute; - -struct Onb { - float3 tangent; - float3 binormal; - float3 normal; -}; - -LUISA_STRUCT(Onb, tangent, binormal, normal) { - [[nodiscard]] Float3 to_world(Expr v) const noexcept { - return v.x * tangent + v.y * binormal + v.z * normal; - } -}; - -int main(int argc, char *argv[]) { - - log_level_verbose(); - - Context context{argv[0]}; - if (argc <= 1) { - LUISA_INFO("Usage: {} . : cuda, dx, cpu, metal", argv[0]); - exit(1); - } - Device device = context.create_device(argv[1]); - - // load the Cornell Box scene - tinyobj::ObjReaderConfig obj_reader_config; - obj_reader_config.triangulate = true; - obj_reader_config.vertex_color = false; - tinyobj::ObjReader obj_reader; - if (!obj_reader.ParseFromString(obj_string, "", obj_reader_config)) { - luisa::string_view error_message = "unknown error."; - if (auto &&e = obj_reader.Error(); !e.empty()) { error_message = e; } - LUISA_ERROR_WITH_LOCATION("Failed to load OBJ file: {}", error_message); - } - if (auto &&e = obj_reader.Warning(); !e.empty()) { - LUISA_WARNING_WITH_LOCATION("{}", e); - } - - auto &&p = obj_reader.GetAttrib().vertices; - luisa::vector vertices; - vertices.reserve(p.size() / 3u); - for (uint i = 0u; i < p.size(); i += 3u) { - vertices.emplace_back(make_float3( - p[i + 0u], p[i + 1u], p[i + 2u])); - } - LUISA_INFO( - "Loaded mesh with {} shape(s) and {} vertices.", - obj_reader.GetShapes().size(), vertices.size()); - - BindlessArray heap = device.create_bindless_array(); - Stream stream = device.create_stream(StreamTag::GRAPHICS); - Buffer vertex_buffer = device.create_buffer(vertices.size()); - stream << vertex_buffer.copy_from(vertices.data()); - luisa::vector meshes; - luisa::vector> triangle_buffers; - for (auto &&shape : obj_reader.GetShapes()) { - uint index = static_cast(meshes.size()); - std::vector const &t = shape.mesh.indices; - uint triangle_count = t.size() / 3u; - LUISA_INFO( - "Processing shape '{}' at index {} with {} triangle(s).", - shape.name, index, triangle_count); - luisa::vector indices; - indices.reserve(t.size()); - for (tinyobj::index_t i : t) { indices.emplace_back(i.vertex_index); } - Buffer &triangle_buffer = triangle_buffers.emplace_back(device.create_buffer(triangle_count)); - Mesh &mesh = meshes.emplace_back(device.create_mesh(vertex_buffer, triangle_buffer)); - heap.emplace_on_update(index, triangle_buffer); - stream << triangle_buffer.copy_from(indices.data()) - << mesh.build(); - } - - Accel accel = device.create_accel({}); - for (Mesh &m : meshes) { - accel.emplace_back(m, make_float4x4(1.0f)); - } - stream << heap.update() - << accel.build() - << synchronize(); - - Constant materials{ - make_float3(0.725f, 0.710f, 0.680f),// floor - make_float3(0.725f, 0.710f, 0.680f),// ceiling - make_float3(0.725f, 0.710f, 0.680f),// back wall - make_float3(0.140f, 0.450f, 0.091f),// right wall - make_float3(0.630f, 0.065f, 0.050f),// left wall - make_float3(0.725f, 0.710f, 0.680f),// short box - make_float3(0.725f, 0.710f, 0.680f),// tall box - make_float3(0.000f, 0.000f, 0.000f),// light - }; - - Callable linear_to_srgb = [&](Var x) noexcept { - return saturate(select(1.055f * pow(x, 1.0f / 2.4f) - 0.055f, - 12.92f * x, - x <= 0.00031308f)); - }; - - Callable tea = [](UInt v0, UInt v1) noexcept { - UInt s0 = def(0u); - for (uint n = 0u; n < 4u; n++) { - s0 += 0x9e3779b9u; - v0 += ((v1 << 4) + 0xa341316cu) ^ (v1 + s0) ^ ((v1 >> 5u) + 0xc8013ea4u); - v1 += ((v0 << 4) + 0xad90777du) ^ (v0 + s0) ^ ((v0 >> 5u) + 0x7e95761eu); - } - return v0; - }; - - Kernel2D make_sampler_kernel = [&](ImageUInt seed_image) noexcept { - UInt2 p = dispatch_id().xy(); - UInt state = tea(p.x, p.y); - seed_image.write(p, make_uint4(state)); - }; - - Callable lcg = [](UInt &state) noexcept { - constexpr uint lcg_a = 1664525u; - constexpr uint lcg_c = 1013904223u; - state = lcg_a * state + lcg_c; - return cast(state & 0x00ffffffu) * - (1.0f / static_cast(0x01000000u)); - }; - - Callable make_onb = [](const Float3 &normal) noexcept { - Float3 binormal = normalize(ite( - abs(normal.x) > abs(normal.z), - make_float3(-normal.y, normal.x, 0.0f), - make_float3(0.0f, -normal.z, normal.y))); - Float3 tangent = normalize(cross(binormal, normal)); - return def(tangent, binormal, normal); - }; - - Callable generate_ray = [](Float2 p) noexcept { - static constexpr float fov = radians(27.8f); - static constexpr float3 origin = make_float3(-0.01f, 0.995f, 5.0f); - Float3 pixel = origin + make_float3(p * tan(0.5f * fov), -1.0f); - Float3 direction = normalize(pixel - origin); - return make_ray(origin, direction); - }; - - Callable cosine_sample_hemisphere = [](Float2 u) noexcept { - Float r = sqrt(u.x); - Float phi = 2.0f * constants::pi * u.y; - return make_float3(r * cos(phi), r * sin(phi), sqrt(1.0f - u.x)); - }; - - Callable balanced_heuristic = [](Float pdf_a, Float pdf_b) noexcept { - return pdf_a / max(pdf_a + pdf_b, 1e-4f); - }; - - auto spp_per_dispatch = device.backend_name() == "metal" || device.backend_name() == "cpu" ? 1u : 64u; - - Kernel2D raytracing_kernel = [&](ImageFloat image, ImageUInt seed_image, AccelVar accel, UInt2 resolution) noexcept { - set_block_size(16u, 16u, 1u); - UInt2 coord = dispatch_id().xy(); - Float frame_size = min(resolution.x, resolution.y).cast(); - UInt state = seed_image.read(coord).x; - Float rx = lcg(state); - Float ry = lcg(state); - Float2 pixel = (make_float2(coord) + make_float2(rx, ry)) / frame_size * 2.0f - 1.0f; - Float3 radiance = def(make_float3(0.0f)); - $for (i, spp_per_dispatch) { - Var ray = generate_ray(pixel * make_float2(1.0f, -1.0f)); - Float3 beta = def(make_float3(1.0f)); - Float pdf_bsdf = def(0.0f); - constexpr float3 light_position = make_float3(-0.24f, 1.98f, 0.16f); - constexpr float3 light_u = make_float3(-0.24f, 1.98f, -0.22f) - light_position; - constexpr float3 light_v = make_float3(0.23f, 1.98f, 0.16f) - light_position; - constexpr float3 light_emission = make_float3(17.0f, 12.0f, 4.0f); - Float light_area = length(cross(light_u, light_v)); - Float3 light_normal = normalize(cross(light_u, light_v)); - $for (depth, 10u) { - // trace - Var hit = accel.intersect(ray, {}); - reorder_shader_execution(); - $if (hit->miss()) { $break; }; - Var triangle = heap->buffer(hit.inst).read(hit.prim); - Float3 p0 = vertex_buffer->read(triangle.i0); - Float3 p1 = vertex_buffer->read(triangle.i1); - Float3 p2 = vertex_buffer->read(triangle.i2); - Float3 p = triangle_interpolate(hit.bary, p0, p1, p2); - Float3 n = normalize(cross(p1 - p0, p2 - p0)); - Float cos_wo = dot(-ray->direction(), n); - $if (cos_wo < 1e-4f) { $break; }; - - // hit light - $if (hit.inst == static_cast(meshes.size() - 1u)) { - $if (depth == 0u) { - radiance += light_emission; - } - $else { - Float pdf_light = length_squared(p - ray->origin()) / (light_area * cos_wo); - Float mis_weight = balanced_heuristic(pdf_bsdf, pdf_light); - radiance += mis_weight * beta * light_emission; - }; - $break; - }; - - // sample light - Float ux_light = lcg(state); - Float uy_light = lcg(state); - Float3 p_light = light_position + ux_light * light_u + uy_light * light_v; - Float3 pp = offset_ray_origin(p, n); - Float3 pp_light = offset_ray_origin(p_light, light_normal); - Float d_light = distance(pp, pp_light); - Float3 wi_light = normalize(pp_light - pp); - Var shadow_ray = make_ray(offset_ray_origin(pp, n), wi_light, 0.f, d_light); - Bool occluded = accel.intersect_any(shadow_ray, {}); - Float cos_wi_light = dot(wi_light, n); - Float cos_light = -dot(light_normal, wi_light); - Float3 albedo = materials.read(hit.inst); - $if (!occluded & cos_wi_light > 1e-4f & cos_light > 1e-4f) { - Float pdf_light = (d_light * d_light) / (light_area * cos_light); - Float pdf_bsdf = cos_wi_light * inv_pi; - Float mis_weight = balanced_heuristic(pdf_light, pdf_bsdf); - Float3 bsdf = albedo * inv_pi * cos_wi_light; - radiance += beta * bsdf * mis_weight * light_emission / max(pdf_light, 1e-4f); - }; - - // sample BSDF - Var onb = make_onb(n); - Float ux = lcg(state); - Float uy = lcg(state); - Float3 wi_local = cosine_sample_hemisphere(make_float2(ux, uy)); - Float cos_wi = abs(wi_local.z); - Float3 new_direction = onb->to_world(wi_local); - ray = make_ray(pp, new_direction); - pdf_bsdf = cos_wi * inv_pi; - beta *= albedo;// * cos_wi * inv_pi / pdf_bsdf => * 1.f - - // rr - Float l = dot(make_float3(0.212671f, 0.715160f, 0.072169f), beta); - $if (l == 0.0f) { $break; }; - Float q = max(l, 0.05f); - Float r = lcg(state); - $if (r >= q) { $break; }; - beta *= 1.0f / q; - }; - }; - radiance /= static_cast(spp_per_dispatch); - seed_image.write(coord, make_uint4(state)); - $if (any(dsl::isnan(radiance))) { radiance = make_float3(0.0f); }; - image.write(dispatch_id().xy(), make_float4(clamp(radiance, 0.0f, 30.0f), 1.0f)); - }; - - Kernel2D accumulate_kernel = [&](ImageFloat accum_image, ImageFloat curr_image) noexcept { - UInt2 p = dispatch_id().xy(); - Float4 accum = accum_image.read(p); - Float3 curr = curr_image.read(p).xyz(); - accum_image.write(p, accum + make_float4(curr, 1.f)); - }; - - Callable aces_tonemapping = [](Float3 x) noexcept { - static constexpr float a = 2.51f; - static constexpr float b = 0.03f; - static constexpr float c = 2.43f; - static constexpr float d = 0.59f; - static constexpr float e = 0.14f; - return clamp((x * (a * x + b)) / (x * (c * x + d) + e), 0.0f, 1.0f); - }; - - Kernel2D clear_kernel = [](ImageFloat image) noexcept { - image.write(dispatch_id().xy(), make_float4(0.0f)); - }; - - Kernel2D hdr2ldr_kernel = [&](ImageFloat hdr_image, ImageFloat ldr_image, Float scale, Bool is_hdr) noexcept { - UInt2 coord = dispatch_id().xy(); - Float4 hdr = hdr_image.read(coord); - Float3 ldr = hdr.xyz() / hdr.w * scale; - $if (!is_hdr) { - ldr = linear_to_srgb(ldr); - }; - ldr_image.write(coord, make_float4(ldr, 1.0f)); - }; - - ShaderOption o{.enable_debug_info = false}; - auto clear_shader = device.compile(clear_kernel, o); - auto hdr2ldr_shader = device.compile(hdr2ldr_kernel, o); - auto accumulate_shader = device.compile(accumulate_kernel, o); - auto raytracing_shader = device.compile(raytracing_kernel, ShaderOption{.name = "path_tracing"}); - auto make_sampler_shader = device.compile(make_sampler_kernel, o); - - static constexpr uint2 resolution = make_uint2(1024u); - Image framebuffer = device.create_image(PixelStorage::HALF4, resolution); - Image accum_image = device.create_image(PixelStorage::FLOAT4, resolution); - luisa::vector> host_image(resolution.x * resolution.y); - CommandList cmd_list; - Image seed_image = device.create_image(PixelStorage::INT1, resolution); - cmd_list << clear_shader(accum_image).dispatch(resolution) - << make_sampler_shader(seed_image).dispatch(resolution); - - Window window{"path tracing", resolution}; - Swapchain swap_chain = device.create_swapchain( - stream, - SwapchainOption{ - .display = window.native_display(), - .window = window.native_handle(), - .size = make_uint2(resolution), - .wants_hdr = false, - .wants_vsync = false, - .back_buffer_count = 8, - }); - Image ldr_image = device.create_image(swap_chain.backend_storage(), resolution); - double last_time = 0.0; - uint frame_count = 0u; - Clock clock; - - while (!window.should_close()) { - cmd_list << raytracing_shader(framebuffer, seed_image, accel, resolution) - .dispatch(resolution) - << accumulate_shader(accum_image, framebuffer) - .dispatch(resolution); - cmd_list << hdr2ldr_shader(accum_image, ldr_image, 1.0f, swap_chain.backend_storage() != PixelStorage::BYTE4).dispatch(resolution); - stream << cmd_list.commit() - << swap_chain.present(ldr_image) << synchronize(); - window.poll_events(); - double dt = clock.toc() - last_time; - last_time = clock.toc(); - frame_count += spp_per_dispatch; - LUISA_INFO("spp: {}, time: {} ms, spp/s: {}", - frame_count, dt, spp_per_dispatch / dt * 1000); - } - stream - << ldr_image.copy_to(host_image.data()) - << synchronize(); - - LUISA_INFO("FPS: {}", frame_count / clock.toc() * 1000); - stbi_write_png("test_path_tracing.png", resolution.x, resolution.y, 4, host_image.data(), 0); -} +#include + +#include + +#include +#include + +#include "common/cornell_box.h" + +#define TINYOBJLOADER_IMPLEMENTATION +#include "common/tiny_obj_loader.h" + +using namespace luisa; +using namespace luisa::compute; + +struct Onb { + float3 tangent; + float3 binormal; + float3 normal; +}; + +LUISA_STRUCT(Onb, tangent, binormal, normal) { + [[nodiscard]] Float3 to_world(Expr v) const noexcept { + return v.x * tangent + v.y * binormal + v.z * normal; + } +}; + +int main(int argc, char *argv[]) { + + log_level_verbose(); + + Context context{argv[0]}; + if (argc <= 1) { + LUISA_INFO("Usage: {} . : cuda, dx, cpu, metal", argv[0]); + exit(1); + } + Device device = context.create_device(argv[1]); + + // load the Cornell Box scene + tinyobj::ObjReaderConfig obj_reader_config; + obj_reader_config.triangulate = true; + obj_reader_config.vertex_color = false; + tinyobj::ObjReader obj_reader; + if (!obj_reader.ParseFromString(obj_string, "", obj_reader_config)) { + luisa::string_view error_message = "unknown error."; + if (auto &&e = obj_reader.Error(); !e.empty()) { error_message = e; } + LUISA_ERROR_WITH_LOCATION("Failed to load OBJ file: {}", error_message); + } + if (auto &&e = obj_reader.Warning(); !e.empty()) { + LUISA_WARNING_WITH_LOCATION("{}", e); + } + + auto &&p = obj_reader.GetAttrib().vertices; + luisa::vector vertices; + vertices.reserve(p.size() / 3u); + for (uint i = 0u; i < p.size(); i += 3u) { + vertices.emplace_back(make_float3( + p[i + 0u], p[i + 1u], p[i + 2u])); + } + LUISA_INFO( + "Loaded mesh with {} shape(s) and {} vertices.", + obj_reader.GetShapes().size(), vertices.size()); + + BindlessArray heap = device.create_bindless_array(); + Stream stream = device.create_stream(StreamTag::GRAPHICS); + Buffer vertex_buffer = device.create_buffer(vertices.size()); + stream << vertex_buffer.copy_from(vertices.data()); + luisa::vector meshes; + luisa::vector> triangle_buffers; + for (auto &&shape : obj_reader.GetShapes()) { + uint index = static_cast(meshes.size()); + std::vector const &t = shape.mesh.indices; + uint triangle_count = t.size() / 3u; + LUISA_INFO( + "Processing shape '{}' at index {} with {} triangle(s).", + shape.name, index, triangle_count); + luisa::vector indices; + indices.reserve(t.size()); + for (tinyobj::index_t i : t) { indices.emplace_back(i.vertex_index); } + Buffer &triangle_buffer = triangle_buffers.emplace_back(device.create_buffer(triangle_count)); + Mesh &mesh = meshes.emplace_back(device.create_mesh(vertex_buffer, triangle_buffer)); + heap.emplace_on_update(index, triangle_buffer); + stream << triangle_buffer.copy_from(indices.data()) + << mesh.build(); + } + + Accel accel = device.create_accel({}); + for (Mesh &m : meshes) { + accel.emplace_back(m, make_float4x4(1.0f)); + } + stream << heap.update() + << accel.build() + << synchronize(); + + Constant materials{ + make_float3(0.725f, 0.710f, 0.680f),// floor + make_float3(0.725f, 0.710f, 0.680f),// ceiling + make_float3(0.725f, 0.710f, 0.680f),// back wall + make_float3(0.140f, 0.450f, 0.091f),// right wall + make_float3(0.630f, 0.065f, 0.050f),// left wall + make_float3(0.725f, 0.710f, 0.680f),// short box + make_float3(0.725f, 0.710f, 0.680f),// tall box + make_float3(0.000f, 0.000f, 0.000f),// light + }; + + Callable linear_to_srgb = [&](Var x) noexcept { + return saturate(select(1.055f * pow(x, 1.0f / 2.4f) - 0.055f, + 12.92f * x, + x <= 0.00031308f)); + }; + + Callable tea = [](UInt v0, UInt v1) noexcept { + UInt s0 = def(0u); + for (uint n = 0u; n < 4u; n++) { + s0 += 0x9e3779b9u; + v0 += ((v1 << 4) + 0xa341316cu) ^ (v1 + s0) ^ ((v1 >> 5u) + 0xc8013ea4u); + v1 += ((v0 << 4) + 0xad90777du) ^ (v0 + s0) ^ ((v0 >> 5u) + 0x7e95761eu); + } + return v0; + }; + + Kernel2D make_sampler_kernel = [&](ImageUInt seed_image) noexcept { + UInt2 p = dispatch_id().xy(); + UInt state = tea(p.x, p.y); + seed_image.write(p, make_uint4(state)); + }; + + Callable lcg = [](UInt &state) noexcept { + constexpr uint lcg_a = 1664525u; + constexpr uint lcg_c = 1013904223u; + state = lcg_a * state + lcg_c; + return cast(state & 0x00ffffffu) * + (1.0f / static_cast(0x01000000u)); + }; + + Callable make_onb = [](const Float3 &normal) noexcept { + Float3 binormal = normalize(ite( + abs(normal.x) > abs(normal.z), + make_float3(-normal.y, normal.x, 0.0f), + make_float3(0.0f, -normal.z, normal.y))); + Float3 tangent = normalize(cross(binormal, normal)); + return def(tangent, binormal, normal); + }; + + Callable generate_ray = [](Float2 p) noexcept { + static constexpr float fov = radians(27.8f); + static constexpr float3 origin = make_float3(-0.01f, 0.995f, 5.0f); + Float3 pixel = origin + make_float3(p * tan(0.5f * fov), -1.0f); + Float3 direction = normalize(pixel - origin); + return make_ray(origin, direction); + }; + + Callable cosine_sample_hemisphere = [](Float2 u) noexcept { + Float r = sqrt(u.x); + Float phi = 2.0f * constants::pi * u.y; + return make_float3(r * cos(phi), r * sin(phi), sqrt(1.0f - u.x)); + }; + + Callable balanced_heuristic = [](Float pdf_a, Float pdf_b) noexcept { + return pdf_a / max(pdf_a + pdf_b, 1e-4f); + }; + + auto spp_per_dispatch = device.backend_name() == "metal" || device.backend_name() == "cpu" ? 1u : 64u; + + Kernel2D raytracing_kernel = [&](ImageFloat image, ImageUInt seed_image, AccelVar accel, UInt2 resolution) noexcept { + set_block_size(16u, 16u, 1u); + UInt2 coord = dispatch_id().xy(); + Float frame_size = min(resolution.x, resolution.y).cast(); + UInt state = seed_image.read(coord).x; + Float rx = lcg(state); + Float ry = lcg(state); + Float2 pixel = (make_float2(coord) + make_float2(rx, ry)) / frame_size * 2.0f - 1.0f; + Float3 radiance = def(make_float3(0.0f)); + $for (i, spp_per_dispatch) { + Var ray = generate_ray(pixel * make_float2(1.0f, -1.0f)); + Float3 beta = def(make_float3(1.0f)); + Float pdf_bsdf = def(0.0f); + constexpr float3 light_position = make_float3(-0.24f, 1.98f, 0.16f); + constexpr float3 light_u = make_float3(-0.24f, 1.98f, -0.22f) - light_position; + constexpr float3 light_v = make_float3(0.23f, 1.98f, 0.16f) - light_position; + constexpr float3 light_emission = make_float3(17.0f, 12.0f, 4.0f); + Float light_area = length(cross(light_u, light_v)); + Float3 light_normal = normalize(cross(light_u, light_v)); + $for (depth, 10u) { + // trace + Var hit = accel.intersect(ray, {}); + reorder_shader_execution(); + $if (hit->miss()) { $break; }; + Var triangle = heap->buffer(hit.inst).read(hit.prim); + Float3 p0 = vertex_buffer->read(triangle.i0); + Float3 p1 = vertex_buffer->read(triangle.i1); + Float3 p2 = vertex_buffer->read(triangle.i2); + Float3 p = triangle_interpolate(hit.bary, p0, p1, p2); + Float3 n = normalize(cross(p1 - p0, p2 - p0)); + Float cos_wo = dot(-ray->direction(), n); + $if (cos_wo < 1e-4f) { $break; }; + + // hit light + $if (hit.inst == static_cast(meshes.size() - 1u)) { + $if (depth == 0u) { + radiance += light_emission; + } + $else { + Float pdf_light = length_squared(p - ray->origin()) / (light_area * cos_wo); + Float mis_weight = balanced_heuristic(pdf_bsdf, pdf_light); + radiance += mis_weight * beta * light_emission; + }; + $break; + }; + + // sample light + Float ux_light = lcg(state); + Float uy_light = lcg(state); + Float3 p_light = light_position + ux_light * light_u + uy_light * light_v; + Float3 pp = offset_ray_origin(p, n); + Float3 pp_light = offset_ray_origin(p_light, light_normal); + Float d_light = distance(pp, pp_light); + Float3 wi_light = normalize(pp_light - pp); + Var shadow_ray = make_ray(offset_ray_origin(pp, n), wi_light, 0.f, d_light); + Bool occluded = accel.intersect_any(shadow_ray, {}); + Float cos_wi_light = dot(wi_light, n); + Float cos_light = -dot(light_normal, wi_light); + Float3 albedo = materials.read(hit.inst); + $if (!occluded & cos_wi_light > 1e-4f & cos_light > 1e-4f) { + Float pdf_light = (d_light * d_light) / (light_area * cos_light); + Float pdf_bsdf = cos_wi_light * inv_pi; + Float mis_weight = balanced_heuristic(pdf_light, pdf_bsdf); + Float3 bsdf = albedo * inv_pi * cos_wi_light; + radiance += beta * bsdf * mis_weight * light_emission / max(pdf_light, 1e-4f); + }; + + // sample BSDF + Var onb = make_onb(n); + Float ux = lcg(state); + Float uy = lcg(state); + Float3 wi_local = cosine_sample_hemisphere(make_float2(ux, uy)); + Float cos_wi = abs(wi_local.z); + Float3 new_direction = onb->to_world(wi_local); + ray = make_ray(pp, new_direction); + pdf_bsdf = cos_wi * inv_pi; + beta *= albedo;// * cos_wi * inv_pi / pdf_bsdf => * 1.f + + // rr + Float l = dot(make_float3(0.212671f, 0.715160f, 0.072169f), beta); + $if (l == 0.0f) { $break; }; + Float q = max(l, 0.05f); + Float r = lcg(state); + $if (r >= q) { $break; }; + beta *= 1.0f / q; + }; + }; + radiance /= static_cast(spp_per_dispatch); + seed_image.write(coord, make_uint4(state)); + $if (any(dsl::isnan(radiance))) { radiance = make_float3(0.0f); }; + image.write(dispatch_id().xy(), make_float4(clamp(radiance, 0.0f, 30.0f), 1.0f)); + }; + + Kernel2D accumulate_kernel = [&](ImageFloat accum_image, ImageFloat curr_image) noexcept { + UInt2 p = dispatch_id().xy(); + Float4 accum = accum_image.read(p); + Float3 curr = curr_image.read(p).xyz(); + accum_image.write(p, accum + make_float4(curr, 1.f)); + }; + + Callable aces_tonemapping = [](Float3 x) noexcept { + static constexpr float a = 2.51f; + static constexpr float b = 0.03f; + static constexpr float c = 2.43f; + static constexpr float d = 0.59f; + static constexpr float e = 0.14f; + return clamp((x * (a * x + b)) / (x * (c * x + d) + e), 0.0f, 1.0f); + }; + + Kernel2D clear_kernel = [](ImageFloat image) noexcept { + image.write(dispatch_id().xy(), make_float4(0.0f)); + }; + + Kernel2D hdr2ldr_kernel = [&](ImageFloat hdr_image, ImageFloat ldr_image, Float scale, Bool is_hdr) noexcept { + UInt2 coord = dispatch_id().xy(); + Float4 hdr = hdr_image.read(coord); + Float3 ldr = hdr.xyz() / hdr.w * scale; + $if (!is_hdr) { + ldr = linear_to_srgb(ldr); + }; + ldr_image.write(coord, make_float4(ldr, 1.0f)); + }; + + ShaderOption o{.enable_debug_info = false}; + auto clear_shader = device.compile(clear_kernel, o); + auto hdr2ldr_shader = device.compile(hdr2ldr_kernel, o); + auto accumulate_shader = device.compile(accumulate_kernel, o); + auto raytracing_shader = device.compile(raytracing_kernel, ShaderOption{.name = "path_tracing"}); + auto make_sampler_shader = device.compile(make_sampler_kernel, o); + + static constexpr uint2 resolution = make_uint2(1024u); + Image framebuffer = device.create_image(PixelStorage::HALF4, resolution); + Image accum_image = device.create_image(PixelStorage::FLOAT4, resolution); + luisa::vector> host_image(resolution.x * resolution.y); + CommandList cmd_list; + Image seed_image = device.create_image(PixelStorage::INT1, resolution); + cmd_list << clear_shader(accum_image).dispatch(resolution) + << make_sampler_shader(seed_image).dispatch(resolution); + + Window window{"path tracing", resolution}; + Swapchain swap_chain = device.create_swapchain( + stream, + SwapchainOption{ + .display = window.native_display(), + .window = window.native_handle(), + .size = make_uint2(resolution), + .wants_hdr = false, + .wants_vsync = false, + .back_buffer_count = 8, + }); + Image ldr_image = device.create_image(swap_chain.backend_storage(), resolution); + double last_time = 0.0; + uint frame_count = 0u; + Clock clock; + + while (!window.should_close()) { + cmd_list << raytracing_shader(framebuffer, seed_image, accel, resolution) + .dispatch(resolution) + << accumulate_shader(accum_image, framebuffer) + .dispatch(resolution); + cmd_list << hdr2ldr_shader(accum_image, ldr_image, 1.0f, swap_chain.backend_storage() != PixelStorage::BYTE4).dispatch(resolution); + stream << cmd_list.commit() + << swap_chain.present(ldr_image) << synchronize(); + window.poll_events(); + double dt = clock.toc() - last_time; + last_time = clock.toc(); + frame_count += spp_per_dispatch; + LUISA_INFO("spp: {}, time: {} ms, spp/s: {}", + frame_count, dt, spp_per_dispatch / dt * 1000); + } + stream + << ldr_image.copy_to(host_image.data()) + << synchronize(); + + LUISA_INFO("FPS: {}", frame_count / clock.toc() * 1000); + stbi_write_png("test_path_tracing.png", resolution.x, resolution.y, 4, host_image.data(), 0); +} diff --git a/src/tests/test_xir_builder.cpp b/src/tests/test_xir_builder.cpp index 030481e0e..926fec1b9 100644 --- a/src/tests/test_xir_builder.cpp +++ b/src/tests/test_xir_builder.cpp @@ -11,9 +11,9 @@ int main() { auto module = xir::Module{}; module.add_comment("My very simple test module."); module.set_name("TestModule"); - auto u32_zero = module.create_constant(0u); - auto f32_one = module.create_constant(1.f); - auto bool_false = module.create_constant(false); + auto u32_zero = module.create_constant_zero(Type::of()); + auto f32_one = module.create_constant_one(Type::of()); + auto bool_false = module.create_constant_zero(Type::of()); bool_false->add_comment("bool constant false"); auto b = xir::Builder{}; @@ -61,7 +61,7 @@ int main() { b.return_(mul); auto k = module.create_kernel(); - auto buffer = k->create_value_argument(Type::of>()); + auto buffer = k->create_resource_argument(Type::of>()); b.set_insertion_point(k->create_body_block()); auto va = b.alloca_local(Type::of()); auto vb = b.alloca_local(Type::of()); diff --git a/src/vstl/xmake.lua b/src/vstl/xmake.lua index d574a5805..145d5b127 100644 --- a/src/vstl/xmake.lua +++ b/src/vstl/xmake.lua @@ -1,15 +1,22 @@ target("lc-vstl") -_config_project({ - project_kind = "static", - no_rtti = true, - batch_size = 4 -}) +if is_plat("macosx") then + _config_project({ + project_kind = "shared", + batch_size = 4 + }) +else + _config_project({ + project_kind = "static", + no_rtti = true, + batch_size = 4 + }) + add_defines("LUISA_VSTL_STATIC_LIB", { + public = true + }) +end add_deps("lc-core", "lmdb") set_pcxxheader("pch.h") add_headerfiles("../../include/luisa/vstl/**.h") -add_defines("LUISA_VSTL_STATIC_LIB", { - public = true -}) add_files("**.cpp") if is_plat("windows") then add_syslinks("Ole32", { diff --git a/src/xir/CMakeLists.txt b/src/xir/CMakeLists.txt index 280fefa4f..c941207c2 100644 --- a/src/xir/CMakeLists.txt +++ b/src/xir/CMakeLists.txt @@ -16,6 +16,7 @@ set(LUISA_COMPUTE_XIR_SOURCES # derived instructions instructions/alloca.cpp instructions/assert.cpp + instructions/assume.cpp instructions/call.cpp instructions/cast.cpp instructions/gep.cpp diff --git a/src/xir/builder.cpp b/src/xir/builder.cpp index 92f190051..4b888f693 100644 --- a/src/xir/builder.cpp +++ b/src/xir/builder.cpp @@ -62,6 +62,10 @@ AssertInst *Builder::assert_(Value *condition, luisa::string_view message) noexc return _create_and_append_instruction(condition, luisa::string{message}); } +AssumeInst *Builder::assume_(Value *condition, luisa::string_view message) noexcept { + return _create_and_append_instruction(condition, luisa::string{message}); +} + ReturnInst *Builder::return_(Value *value) noexcept { return _create_and_append_instruction(value); } @@ -150,6 +154,7 @@ LoadInst *Builder::load(const Type *type, Value *variable) noexcept { StoreInst *Builder::store(Value *variable, Value *value) noexcept { LUISA_ASSERT(variable->is_lvalue(), "Store destination must be an lvalue."); + LUISA_ASSERT(!value->is_lvalue(), "Store source cannot be an lvalue."); return _create_and_append_instruction(variable, value); } diff --git a/src/xir/constant.cpp b/src/xir/constant.cpp index 27060a820..4381a1693 100644 --- a/src/xir/constant.cpp +++ b/src/xir/constant.cpp @@ -89,16 +89,84 @@ static void xir_constant_fill_data(const Type *t, const void *raw, void *data) n } } +static void xir_constant_fill_one(const Type *t, void *data) noexcept { + LUISA_DEBUG_ASSERT(t != nullptr && data != nullptr, "Invalid arguments."); + if (t->is_bool()) { + auto value = static_cast(1u); + memmove(data, &value, 1); + } else if (t->is_scalar()) { + auto do_copy = [data, t](T x) noexcept { + LUISA_DEBUG_ASSERT(Type::of() == t, "Type mismatch."); + memmove(data, &x, sizeof(T)); + }; + switch (t->tag()) { + case Type::Tag::INT8: do_copy(static_cast(1)); break; + case Type::Tag::UINT8: do_copy(static_cast(1)); break; + case Type::Tag::INT16: do_copy(static_cast(1)); break; + case Type::Tag::UINT16: do_copy(static_cast(1)); break; + case Type::Tag::INT32: do_copy(static_cast(1)); break; + case Type::Tag::UINT32: do_copy(static_cast(1)); break; + case Type::Tag::INT64: do_copy(static_cast(1)); break; + case Type::Tag::UINT64: do_copy(static_cast(1)); break; + case Type::Tag::FLOAT16: do_copy(static_cast(1.0f)); break; + case Type::Tag::FLOAT32: do_copy(static_cast(1.0f)); break; + case Type::Tag::FLOAT64: do_copy(static_cast(1.0)); break; + default: LUISA_ERROR_WITH_LOCATION("Unsupported scalar type."); + } + } else { + switch (t->tag()) { + case Type::Tag::VECTOR: { + auto elem_type = t->element(); + auto dim = t->dimension(); + for (auto i = 0u; i < dim; i++) { + auto offset = i * elem_type->size(); + auto data_elem = static_cast(data) + offset; + xir_constant_fill_one(elem_type, data_elem); + } + break; + } + case Type::Tag::MATRIX: { + auto elem_type = t->element(); + auto dim = t->dimension(); + auto col_type = Type::vector(elem_type, dim); + for (auto i = 0u; i < dim; i++) { + auto offset = i * col_type->size(); + auto data_col = static_cast(data) + offset; + xir_constant_fill_one(col_type, data_col); + } + break; + } + case Type::Tag::ARRAY: { + auto elem_type = t->element(); + auto dim = t->dimension(); + for (auto i = 0u; i < dim; i++) { + auto offset = i * elem_type->size(); + auto data_elem = static_cast(data) + offset; + xir_constant_fill_one(elem_type, data_elem); + } + break; + } + case Type::Tag::STRUCTURE: { + size_t offset = 0u; + for (auto m : t->members()) { + offset = luisa::align(offset, m->alignment()); + auto data_member = static_cast(data) + offset; + xir_constant_fill_one(m, data_member); + offset += m->size(); + } + break; + } + default: LUISA_ERROR_WITH_LOCATION("Unsupported constant type."); + } + } +} + }// namespace detail void Constant::set_data(const void *data) noexcept { memset(this->data(), 0, type()->size()); - _hash = 0u; - if (data != nullptr) { - detail::xir_constant_fill_data(type(), data, this->data()); - auto hv = luisa::hash64(this->data(), type()->size(), luisa::hash64_default_seed); - _hash = luisa::hash_combine({type()->hash(), hv}); - } + if (data != nullptr) { detail::xir_constant_fill_data(type(), data, this->data()); } + _update_hash(); } void *Constant::data() noexcept { @@ -109,8 +177,23 @@ const void *Constant::data() const noexcept { return const_cast(this)->data(); } +void Constant::set_zero() noexcept { + set_data(nullptr); +} + +void Constant::set_one() noexcept { + memset(this->data(), 0, type()->size()); + detail::xir_constant_fill_one(type(), this->data()); + _update_hash(); +} + void Constant::_check_reinterpret_cast_type_size(size_t size) const noexcept { LUISA_ASSERT(type()->size() == size, "Type size mismatch."); } +void Constant::_update_hash() noexcept { + auto hv = luisa::hash64(this->data(), type()->size(), luisa::hash64_default_seed); + _hash = luisa::hash_combine({type()->hash(), hv}); +} + }// namespace luisa::compute::xir diff --git a/src/xir/instructions/assume.cpp b/src/xir/instructions/assume.cpp new file mode 100644 index 000000000..fdfef5b6a --- /dev/null +++ b/src/xir/instructions/assume.cpp @@ -0,0 +1,30 @@ +#include + +namespace luisa::compute::xir { + +AssumeInst::AssumeInst(Value *condition, luisa::string message) noexcept + : DerivedInstruction{nullptr}, _message{std::move(message)} { + set_operands(std::array{condition}); +} + +void AssumeInst::set_condition(Value *condition) noexcept { + set_operand(operand_index_condition, condition); +} + +Value *AssumeInst::condition() noexcept { + return operand(operand_index_condition); +} + +const Value *AssumeInst::condition() const noexcept { + return operand(operand_index_condition); +} + +void AssumeInst::set_message(luisa::string_view message) noexcept { + _message = message; +} + +luisa::string_view AssumeInst::message() const noexcept { + return _message; +} + +}// namespace luisa::compute::xir diff --git a/src/xir/instructions/intrinsic_name_map.inl.h b/src/xir/instructions/intrinsic_name_map.inl.h index 870929488..769dc0f87 100644 --- a/src/xir/instructions/intrinsic_name_map.inl.h +++ b/src/xir/instructions/intrinsic_name_map.inl.h @@ -27,8 +27,6 @@ luisa::string to_string(IntrinsicOp op) noexcept { case IntrinsicOp::BINARY_GREATER_EQUAL: return "binary_greater_equal"; case IntrinsicOp::BINARY_EQUAL: return "binary_equal"; case IntrinsicOp::BINARY_NOT_EQUAL: return "binary_not_equal"; - case IntrinsicOp::ASSUME: return "assume"; - case IntrinsicOp::ASSERT: return "assert"; case IntrinsicOp::THREAD_ID: return "thread_id"; case IntrinsicOp::BLOCK_ID: return "block_id"; case IntrinsicOp::WARP_LANE_ID: return "warp_lane_id"; @@ -84,6 +82,7 @@ luisa::string to_string(IntrinsicOp op) noexcept { case IntrinsicOp::FRACT: return "fract"; case IntrinsicOp::TRUNC: return "trunc"; case IntrinsicOp::ROUND: return "round"; + case IntrinsicOp::RINT: return "rint"; case IntrinsicOp::FMA: return "fma"; case IntrinsicOp::COPYSIGN: return "copysign"; case IntrinsicOp::CROSS: return "cross"; @@ -98,12 +97,15 @@ luisa::string to_string(IntrinsicOp op) noexcept { case IntrinsicOp::REDUCE_MIN: return "reduce_min"; case IntrinsicOp::REDUCE_MAX: return "reduce_max"; case IntrinsicOp::OUTER_PRODUCT: return "outer_product"; + case IntrinsicOp::MATRIX_COMP_NEG: return "matrix_comp_neg"; + case IntrinsicOp::MATRIX_COMP_ADD: return "matrix_comp_add"; + case IntrinsicOp::MATRIX_COMP_SUB: return "matrix_comp_sub"; case IntrinsicOp::MATRIX_COMP_MUL: return "matrix_comp_mul"; - case IntrinsicOp::DETERMINANT: return "determinant"; - case IntrinsicOp::TRANSPOSE: return "transpose"; - case IntrinsicOp::INVERSE: return "inverse"; - case IntrinsicOp::ZERO: return "zero"; - case IntrinsicOp::ONE: return "one"; + case IntrinsicOp::MATRIX_COMP_DIV: return "matrix_comp_div"; + case IntrinsicOp::MATRIX_LINALG_MUL: return "matrix_linalg_mul"; + case IntrinsicOp::MATRIX_DETERMINANT: return "matrix_determinant"; + case IntrinsicOp::MATRIX_TRANSPOSE: return "matrix_transpose"; + case IntrinsicOp::MATRIX_INVERSE: return "matrix_inverse"; case IntrinsicOp::ATOMIC_EXCHANGE: return "atomic_exchange"; case IntrinsicOp::ATOMIC_COMPARE_EXCHANGE: return "atomic_compare_exchange"; case IntrinsicOp::ATOMIC_FETCH_ADD: return "atomic_fetch_add"; @@ -264,8 +266,6 @@ IntrinsicOp intrinsic_op_from_string(luisa::string_view name) noexcept { {"binary_greater_equal", IntrinsicOp::BINARY_GREATER_EQUAL}, {"binary_equal", IntrinsicOp::BINARY_EQUAL}, {"binary_not_equal", IntrinsicOp::BINARY_NOT_EQUAL}, - {"assume", IntrinsicOp::ASSUME}, - {"assert", IntrinsicOp::ASSERT}, {"thread_id", IntrinsicOp::THREAD_ID}, {"block_id", IntrinsicOp::BLOCK_ID}, {"warp_lane_id", IntrinsicOp::WARP_LANE_ID}, @@ -321,6 +321,7 @@ IntrinsicOp intrinsic_op_from_string(luisa::string_view name) noexcept { {"fract", IntrinsicOp::FRACT}, {"trunc", IntrinsicOp::TRUNC}, {"round", IntrinsicOp::ROUND}, + {"rint", IntrinsicOp::RINT}, {"fma", IntrinsicOp::FMA}, {"copysign", IntrinsicOp::COPYSIGN}, {"cross", IntrinsicOp::CROSS}, @@ -335,12 +336,15 @@ IntrinsicOp intrinsic_op_from_string(luisa::string_view name) noexcept { {"reduce_min", IntrinsicOp::REDUCE_MIN}, {"reduce_max", IntrinsicOp::REDUCE_MAX}, {"outer_product", IntrinsicOp::OUTER_PRODUCT}, + {"matrix_comp_neg", IntrinsicOp::MATRIX_COMP_NEG}, + {"matrix_comp_add", IntrinsicOp::MATRIX_COMP_ADD}, + {"matrix_comp_sub", IntrinsicOp::MATRIX_COMP_SUB}, {"matrix_comp_mul", IntrinsicOp::MATRIX_COMP_MUL}, - {"determinant", IntrinsicOp::DETERMINANT}, - {"transpose", IntrinsicOp::TRANSPOSE}, - {"inverse", IntrinsicOp::INVERSE}, - {"zero", IntrinsicOp::ZERO}, - {"one", IntrinsicOp::ONE}, + {"matrix_comp_div", IntrinsicOp::MATRIX_COMP_DIV}, + {"matrix_linalg_mul", IntrinsicOp::MATRIX_LINALG_MUL}, + {"matrix_determinant", IntrinsicOp::MATRIX_DETERMINANT}, + {"matrix_transpose", IntrinsicOp::MATRIX_TRANSPOSE}, + {"matrix_inverse", IntrinsicOp::MATRIX_INVERSE}, {"atomic_exchange", IntrinsicOp::ATOMIC_EXCHANGE}, {"atomic_compare_exchange", IntrinsicOp::ATOMIC_COMPARE_EXCHANGE}, {"atomic_fetch_add", IntrinsicOp::ATOMIC_FETCH_ADD}, diff --git a/src/xir/module.cpp b/src/xir/module.cpp index 2330176d1..84a1baedc 100644 --- a/src/xir/module.cpp +++ b/src/xir/module.cpp @@ -36,6 +36,18 @@ Constant *Module::create_constant(const Type *type, const void *data) noexcept { return c; } +Constant *Module::create_constant_zero(const Type *type) noexcept { + auto c = create_constant(type); + c->set_zero(); + return c; +} + +Constant *Module::create_constant_one(const Type *type) noexcept { + auto c = create_constant(type); + c->set_one(); + return c; +} + void Module::add_function(Function *function) noexcept { LUISA_DEBUG_ASSERT(!function->is_linked(), "Function is already linked."); _functions.insert_front(function); diff --git a/src/xir/translators/ast2xir.cpp b/src/xir/translators/ast2xir.cpp index 4a58ee50c..f23168aba 100644 --- a/src/xir/translators/ast2xir.cpp +++ b/src/xir/translators/ast2xir.cpp @@ -66,11 +66,23 @@ class AST2XIRContext { luisa::unordered_map _generated_functions; luisa::unordered_map _generated_constants; luisa::unordered_map _generated_literals; + luisa::unordered_map _generated_zero_constants; + luisa::unordered_map _generated_one_constants; Current _current; private: [[nodiscard]] Value *_translate_unary_expr(Builder &b, const UnaryExpr *expr) noexcept { auto operand = _translate_expression(b, expr->operand(), true); + // matrices need special handling + if (operand->type()->is_matrix()) { + switch (expr->op()) { + case UnaryOp::PLUS: return operand; + case UnaryOp::MINUS: return b.call(expr->type(), IntrinsicOp::MATRIX_COMP_NEG, {operand}); + default: break; + } + LUISA_ERROR_WITH_LOCATION("Invalid unary operation."); + } + // normal cases auto op = [unary_op = expr->op()] { switch (unary_op) { case UnaryOp::PLUS: return IntrinsicOp::UNARY_PLUS; @@ -93,10 +105,11 @@ class AST2XIRContext { // vector to vector cast if (value->type()->is_vector() && type->is_vector()) { LUISA_ASSERT(value->type()->dimension() >= type->dimension(), "Vector cast dimension mismatch."); + auto value_elem_type = value->type()->element(); luisa::fixed_vector elements; for (auto i = 0u; i < type->dimension(); i++) { auto idx = _translate_constant_access_index(i); - auto elem = b.call(type->element(), IntrinsicOp::EXTRACT, {value, idx}); + auto elem = b.call(value_elem_type, IntrinsicOp::EXTRACT, {value, idx}); elements.emplace_back(b.static_cast_if_necessary(type->element(), elem)); } return b.call(type, IntrinsicOp::AGGREGATE, elements); @@ -112,12 +125,19 @@ class AST2XIRContext { } [[nodiscard]] Value *_translate_binary_expr(Builder &b, const BinaryExpr *expr) noexcept { - auto op = [binary_op = expr->op()] { + auto type_promotion = promote_types(expr->op(), expr->lhs()->type(), expr->rhs()->type()); + auto op = [binary_op = expr->op(), lhs = expr->lhs(), rhs = expr->rhs()] { + auto has_matrix = lhs->type()->is_matrix() || rhs->type()->is_matrix(); switch (binary_op) { - case BinaryOp::ADD: return IntrinsicOp::BINARY_ADD; - case BinaryOp::SUB: return IntrinsicOp::BINARY_SUB; - case BinaryOp::MUL: return IntrinsicOp::BINARY_MUL; - case BinaryOp::DIV: return IntrinsicOp::BINARY_DIV; + case BinaryOp::ADD: return has_matrix ? IntrinsicOp::MATRIX_COMP_ADD : IntrinsicOp::BINARY_ADD; + case BinaryOp::SUB: return has_matrix ? IntrinsicOp::MATRIX_COMP_SUB : IntrinsicOp::BINARY_SUB; + case BinaryOp::MUL: { + if (lhs->type()->is_matrix() && (rhs->type()->is_matrix() || rhs->type()->is_vector())) { + return IntrinsicOp::MATRIX_LINALG_MUL; + } + return has_matrix ? IntrinsicOp::MATRIX_COMP_MUL : IntrinsicOp::BINARY_MUL; + } + case BinaryOp::DIV: return has_matrix ? IntrinsicOp::MATRIX_COMP_DIV : IntrinsicOp::BINARY_DIV; case BinaryOp::MOD: return IntrinsicOp::BINARY_MOD; case BinaryOp::BIT_AND: return IntrinsicOp::BINARY_BIT_AND; case BinaryOp::BIT_OR: return IntrinsicOp::BINARY_BIT_OR; @@ -135,7 +155,6 @@ class AST2XIRContext { } LUISA_ERROR_WITH_LOCATION("Unexpected binary operation."); }(); - auto type_promotion = promote_types(expr->op(), expr->lhs()->type(), expr->rhs()->type()); auto lhs = _translate_expression(b, expr->lhs(), true); auto rhs = _translate_expression(b, expr->rhs(), true); lhs = _type_cast_if_necessary(b, type_promotion.lhs, lhs); @@ -211,7 +230,7 @@ class AST2XIRContext { iter->second = luisa::visit( [this, t = key.type](T v) noexcept { LUISA_ASSERT(t == Type::of(), "Literal type mismatch."); - return _module->create_constant(v); + return _module->create_constant(t, &v); }, key.value); } @@ -223,7 +242,7 @@ class AST2XIRContext { return _translate_typed_literal(key); } - [[nodiscard]] Value *_translate_builtin_variable(Builder &b, Variable ast_var) noexcept { + [[nodiscard]] static Value *_translate_builtin_variable(Builder &b, Variable ast_var) noexcept { LUISA_ASSERT(ast_var.is_builtin(), "Unresolved variable reference."); auto op = [tag = ast_var.tag(), t = ast_var.type()] { switch (tag) { @@ -277,6 +296,78 @@ class AST2XIRContext { return iter->second; } + [[nodiscard]] Value *_translate_zero_or_one(const Type *type, int value) noexcept { + + // zero or one scalar +#define LUISA_AST2XIR_ZERO_ONE_SCALAR(T) \ + if (type == Type::of()) { \ + return _translate_typed_literal( \ + {type, static_cast(value)}); \ + } + LUISA_AST2XIR_ZERO_ONE_SCALAR(bool) + LUISA_AST2XIR_ZERO_ONE_SCALAR(byte) + LUISA_AST2XIR_ZERO_ONE_SCALAR(ubyte) + LUISA_AST2XIR_ZERO_ONE_SCALAR(short) + LUISA_AST2XIR_ZERO_ONE_SCALAR(ushort) + LUISA_AST2XIR_ZERO_ONE_SCALAR(int) + LUISA_AST2XIR_ZERO_ONE_SCALAR(uint) + LUISA_AST2XIR_ZERO_ONE_SCALAR(slong) + LUISA_AST2XIR_ZERO_ONE_SCALAR(ulong) + LUISA_AST2XIR_ZERO_ONE_SCALAR(half) + LUISA_AST2XIR_ZERO_ONE_SCALAR(float) + LUISA_AST2XIR_ZERO_ONE_SCALAR(double) +#undef LUISA_AST2XIR_ZERO_ONE_SCALAR + + // zero or one vector +#define LUISA_AST2XIR_ZERO_ONE_VECTOR_N(T, N) \ + if (type == Type::of()) { \ + return _translate_typed_literal( \ + {type, luisa::make_##T##N(static_cast(value))}); \ + } +#define LUISA_AST2XIR_ZERO_ONE_VECTOR(T) \ + LUISA_AST2XIR_ZERO_ONE_VECTOR_N(T, 2) \ + LUISA_AST2XIR_ZERO_ONE_VECTOR_N(T, 3) \ + LUISA_AST2XIR_ZERO_ONE_VECTOR_N(T, 4) + LUISA_AST2XIR_ZERO_ONE_VECTOR(bool) + LUISA_AST2XIR_ZERO_ONE_VECTOR(byte) + LUISA_AST2XIR_ZERO_ONE_VECTOR(ubyte) + LUISA_AST2XIR_ZERO_ONE_VECTOR(short) + LUISA_AST2XIR_ZERO_ONE_VECTOR(ushort) + LUISA_AST2XIR_ZERO_ONE_VECTOR(int) + LUISA_AST2XIR_ZERO_ONE_VECTOR(uint) + LUISA_AST2XIR_ZERO_ONE_VECTOR(slong) + LUISA_AST2XIR_ZERO_ONE_VECTOR(ulong) + LUISA_AST2XIR_ZERO_ONE_VECTOR(half) + LUISA_AST2XIR_ZERO_ONE_VECTOR(float) + LUISA_AST2XIR_ZERO_ONE_VECTOR(double) +#undef LUISA_AST2XIR_ZERO_ONE_VECTOR +#undef LUISA_AST2XIR_ZERO_ONE_VECTOR_N + + // zero or one matrix +#define LUISA_AST2XIR_ZERO_ONE_MATRIX(N) \ + if (type == Type::of()) { \ + return _translate_typed_literal( \ + {type, luisa::make_float##N##x##N(static_cast(value))}); \ + } + LUISA_AST2XIR_ZERO_ONE_MATRIX(2) + LUISA_AST2XIR_ZERO_ONE_MATRIX(3) + LUISA_AST2XIR_ZERO_ONE_MATRIX(4) +#undef LUISA_AST2XIR_ZERO_ONE_MATRIX + + // fall back to generic zero constant + if (value == 0) { + auto iter = _generated_zero_constants.try_emplace(type, nullptr).first; + if (iter->second == nullptr) { iter->second = _module->create_constant_zero(type); } + return iter->second; + } + if (value == 1) { + auto iter = _generated_one_constants.try_emplace(type, nullptr).first; + if (iter->second == nullptr) { iter->second = _module->create_constant_one(type); } + return iter->second; + } + LUISA_ERROR_WITH_LOCATION("Unexpected zero or one constant."); + } + [[nodiscard]] Value *_translate_call_expr(Builder &b, const CallExpr *expr) noexcept { if (expr->is_external()) { auto ast = expr->external(); @@ -344,9 +435,10 @@ class AST2XIRContext { args.emplace_back(_type_cast_if_necessary(b, elem_type, arg)); } else { LUISA_ASSERT(arg->type()->is_vector(), "Vector call argument type mismatch."); + auto arg_elem_type = arg->type()->element(); for (auto i = 0u; i < arg->type()->dimension(); i++) { auto idx = _translate_constant_access_index(i); - auto elem = b.call(expr->type()->element(), IntrinsicOp::EXTRACT, {arg, idx}); + auto elem = b.call(arg_elem_type, IntrinsicOp::EXTRACT, {arg, idx}); args.emplace_back(_type_cast_if_necessary(b, elem_type, elem)); } } @@ -431,9 +523,9 @@ class AST2XIRContext { case CallOp::REDUCE_MAX: return pure_call(IntrinsicOp::REDUCE_MAX); case CallOp::OUTER_PRODUCT: return pure_call(IntrinsicOp::OUTER_PRODUCT); case CallOp::MATRIX_COMPONENT_WISE_MULTIPLICATION: return pure_call(IntrinsicOp::MATRIX_COMP_MUL); - case CallOp::DETERMINANT: return pure_call(IntrinsicOp::DETERMINANT); - case CallOp::TRANSPOSE: return pure_call(IntrinsicOp::TRANSPOSE); - case CallOp::INVERSE: return pure_call(IntrinsicOp::INVERSE); + case CallOp::DETERMINANT: return pure_call(IntrinsicOp::MATRIX_DETERMINANT); + case CallOp::TRANSPOSE: return pure_call(IntrinsicOp::MATRIX_TRANSPOSE); + case CallOp::INVERSE: return pure_call(IntrinsicOp::MATRIX_INVERSE); case CallOp::SYNCHRONIZE_BLOCK: return pure_call(IntrinsicOp::SYNCHRONIZE_BLOCK); case CallOp::ATOMIC_EXCHANGE: return resource_call(IntrinsicOp::ATOMIC_EXCHANGE); case CallOp::ATOMIC_COMPARE_EXCHANGE: return resource_call(IntrinsicOp::ATOMIC_COMPARE_EXCHANGE); @@ -539,7 +631,14 @@ class AST2XIRContext { case CallOp::ASSUME: { LUISA_ASSERT(!expr->arguments().empty(), "Assume requires at least one argument."); auto cond = _translate_expression(b, expr->arguments()[0], true); - return b.call(nullptr, IntrinsicOp::ASSUME, {cond}); + luisa::string_view message; + if (expr->arguments().size() >= 2u) { + auto ast_msg_id = expr->arguments()[1]; + LUISA_ASSERT(ast_msg_id->tag() == Expression::Tag::STRING_ID, "Assume message must be a string."); + auto msg_id = static_cast(ast_msg_id); + message = msg_id->data(); + } + return b.assume_(cond, message); } case CallOp::UNREACHABLE: { luisa::string_view message; @@ -551,8 +650,8 @@ class AST2XIRContext { } return b.unreachable_(message); } - case CallOp::ZERO: return pure_call(IntrinsicOp::ZERO); - case CallOp::ONE: return pure_call(IntrinsicOp::ONE); + case CallOp::ZERO: return _translate_zero_or_one(expr->type(), 0); + case CallOp::ONE: return _translate_zero_or_one(expr->type(), 1); case CallOp::PACK: LUISA_NOT_IMPLEMENTED(); case CallOp::UNPACK: LUISA_NOT_IMPLEMENTED(); case CallOp::REQUIRES_GRADIENT: LUISA_NOT_IMPLEMENTED(); @@ -845,92 +944,84 @@ class AST2XIRContext { } void _translate_statements(Builder &b, luisa::span stmts) noexcept { - if (stmts.empty()) { return; } - auto car = stmts.front(); - auto cdr = stmts.subspan(1); - switch (car->tag()) { - case Statement::Tag::BREAK: { - auto break_target = _current.break_continue_target.break_target; - LUISA_ASSERT(break_target != nullptr, "Invalid break statement."); - _commented(b.break_(break_target)); - break; - } - case Statement::Tag::CONTINUE: { - auto continue_target = _current.break_continue_target.continue_target; - LUISA_ASSERT(continue_target != nullptr, "Invalid continue statement."); - _commented(b.continue_(continue_target)); - break; - } - case Statement::Tag::RETURN: { - if (auto ast_expr = static_cast(car)->expression()) { - auto value = _translate_expression(b, ast_expr, true); - _commented(b.return_(value)); - } else { - _commented(b.return_void()); + while (!stmts.empty()) { + auto car = stmts.front(); + auto cdr = stmts.subspan(1); + switch (car->tag()) { + case Statement::Tag::BREAK: { + auto break_target = _current.break_continue_target.break_target; + LUISA_ASSERT(break_target != nullptr, "Invalid break statement."); + return static_cast(_commented(b.break_(break_target))); } - break; - } - case Statement::Tag::SCOPE: LUISA_ERROR_WITH_LOCATION("Unexpected scope statement."); - case Statement::Tag::IF: { - auto ast_if = static_cast(car); - _translate_if_stmt(b, ast_if, cdr); - break; - } - case Statement::Tag::LOOP: { - auto ast_loop = static_cast(car); - _translate_loop_stmt(b, ast_loop, cdr); - break; - } - case Statement::Tag::EXPR: { - auto ast_expr = static_cast(car)->expression(); - auto last = _commented(_translate_expression(b, ast_expr, false)); - if (last->derived_value_tag() != DerivedValueTag::INSTRUCTION || - !static_cast(last)->is_terminator()) { - _translate_statements(b, cdr); + case Statement::Tag::CONTINUE: { + auto continue_target = _current.break_continue_target.continue_target; + LUISA_ASSERT(continue_target != nullptr, "Invalid continue statement."); + return static_cast(_commented(b.continue_(continue_target))); } - break; - } - case Statement::Tag::SWITCH: { - auto ast_switch = static_cast(car); - _translate_switch_stmt(b, ast_switch, cdr); - break; - } - case Statement::Tag::SWITCH_CASE: LUISA_ERROR_WITH_LOCATION("Unexpected switch case statement."); - case Statement::Tag::SWITCH_DEFAULT: LUISA_ERROR_WITH_LOCATION("Unexpected switch default statement."); - case Statement::Tag::ASSIGN: { - auto assign = static_cast(car); - auto variable = _translate_expression(b, assign->lhs(), false); - auto value = _translate_expression(b, assign->rhs(), true); - _commented(b.store(variable, value)); - _translate_statements(b, cdr); - break; - } - case Statement::Tag::FOR: { - auto ast_for = static_cast(car); - _translate_for_stmt(b, ast_for, cdr); - break; - } - case Statement::Tag::COMMENT: { - _collect_comment(car); - _translate_statements(b, cdr); - break; - } - case Statement::Tag::RAY_QUERY: { - auto ast_ray_query = static_cast(car); - _translate_ray_query_stmt(b, ast_ray_query, cdr); - break; - } - case Statement::Tag::AUTO_DIFF: LUISA_NOT_IMPLEMENTED(); - case Statement::Tag::PRINT: { - auto ast_print = static_cast(car); - luisa::fixed_vector args; - for (auto ast_arg : ast_print->arguments()) { - args.emplace_back(_translate_expression(b, ast_arg, true)); + case Statement::Tag::RETURN: { + if (auto ast_expr = static_cast(car)->expression()) { + auto value = _translate_expression(b, ast_expr, true); + return static_cast(_commented(b.return_(value))); + } + return static_cast(_commented(b.return_void())); + } + case Statement::Tag::SCOPE: LUISA_ERROR_WITH_LOCATION("Unexpected scope statement."); + case Statement::Tag::IF: { + auto ast_if = static_cast(car); + return _translate_if_stmt(b, ast_if, cdr); + } + case Statement::Tag::LOOP: { + auto ast_loop = static_cast(car); + return _translate_loop_stmt(b, ast_loop, cdr); + } + case Statement::Tag::EXPR: { + auto ast_expr = static_cast(car)->expression(); + _commented(_translate_expression(b, ast_expr, false)); + // in case the expression is a terminator, e.g., unreachable, we should stop here + if (b.insertion_point()->is_terminator()) { return; } + // otherwise, continue to the next statement + break; + } + case Statement::Tag::SWITCH: { + auto ast_switch = static_cast(car); + return _translate_switch_stmt(b, ast_switch, cdr); + } + case Statement::Tag::SWITCH_CASE: LUISA_ERROR_WITH_LOCATION("Unexpected switch case statement."); + case Statement::Tag::SWITCH_DEFAULT: LUISA_ERROR_WITH_LOCATION("Unexpected switch default statement."); + case Statement::Tag::ASSIGN: { + auto assign = static_cast(car); + if (assign->lhs() != assign->rhs()) { + auto variable = _translate_expression(b, assign->lhs(), false); + auto value = _translate_expression(b, assign->rhs(), true); + _commented(b.store(variable, value)); + } + break; + } + case Statement::Tag::FOR: { + auto ast_for = static_cast(car); + return _translate_for_stmt(b, ast_for, cdr); + } + case Statement::Tag::COMMENT: { + _collect_comment(car); + break; + } + case Statement::Tag::RAY_QUERY: { + auto ast_ray_query = static_cast(car); + return _translate_ray_query_stmt(b, ast_ray_query, cdr); + } + case Statement::Tag::AUTO_DIFF: LUISA_NOT_IMPLEMENTED(); + case Statement::Tag::PRINT: { + auto ast_print = static_cast(car); + luisa::fixed_vector args; + for (auto ast_arg : ast_print->arguments()) { + args.emplace_back(_translate_expression(b, ast_arg, true)); + } + _commented(b.print(luisa::string{ast_print->format()}, args)); + break; } - _commented(b.print(luisa::string{ast_print->format()}, args)); - _translate_statements(b, cdr); - break; } + // update the statement list + stmts = cdr; } } @@ -942,7 +1033,7 @@ class AST2XIRContext { for (auto ast_arg : _current.ast->arguments()) { auto arg = _current.f->create_argument(ast_arg.type(), ast_arg.is_reference()); if (auto ast_usage = _current.ast->variable_usage(ast_arg.uid()); - arg->is_value() && ast_usage == Usage::WRITE || ast_usage == Usage::READ_WRITE) { + arg->is_value() && (ast_usage == Usage::WRITE || ast_usage == Usage::READ_WRITE)) { // AST allows update of the argument, so we need to copy it to a local variable auto local = b.alloca_local(arg->type()); local->add_comment("Local copy of argument"); @@ -986,17 +1077,20 @@ class AST2XIRContext { // return the function if it has been translated if (!just_inserted) { return iter->second; } // create a new function - FunctionDefinition *def = nullptr; - switch (f.tag()) { - case ASTFunction::Tag::KERNEL: - def = _module->create_kernel(); - break; - case ASTFunction::Tag::CALLABLE: - def = _module->create_callable(f.return_type()); - break; - case ASTFunction::Tag::RASTER_STAGE: - LUISA_NOT_IMPLEMENTED(); - } + auto def = [&]() noexcept -> FunctionDefinition * { + switch (f.tag()) { + case ASTFunction::Tag::KERNEL: { + auto kernel = _module->create_kernel(); + kernel->set_block_size(f.block_size()); + return kernel; + } + case ASTFunction::Tag::CALLABLE: { + return _module->create_callable(f.return_type()); + } + case ASTFunction::Tag::RASTER_STAGE: LUISA_NOT_IMPLEMENTED(); + } + LUISA_ERROR_WITH_LOCATION("Invalid function tag."); + }(); iter->second = def; // translate the function auto old = std::exchange(_current, {.f = def, .ast = &f}); diff --git a/src/xir/translators/xir2text.cpp b/src/xir/translators/xir2text.cpp index dc594e94b..a0ae04263 100644 --- a/src/xir/translators/xir2text.cpp +++ b/src/xir/translators/xir2text.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -232,6 +233,15 @@ class XIR2TextTranslator final { _main << " " << _value_ident(inst->condition()); } + void _emit_assume_inst(const AssumeInst *inst) noexcept { + _main << "assume"; + if (!inst->message().empty()) { + _main << " "; + _emit_string_escaped(_main, inst->message()); + } + _main << " " << _value_ident(inst->condition()); + } + void _emit_if_inst(const IfInst *inst, int indent) noexcept { _main << "if " << _value_ident(inst->condition()) << ", then "; _emit_basic_block(inst->true_block(), indent); @@ -450,6 +460,9 @@ class XIR2TextTranslator final { case DerivedInstructionTag::ASSERT: _emit_assert_inst(static_cast(inst)); break; + case DerivedInstructionTag::ASSUME: + _emit_assume_inst(static_cast(inst)); + break; } _main << ";"; _emit_use_debug_info(_main, inst->use_list());