| /* |
| * Copyright 2026 WebAssembly Community Group participants |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef wasm_support_i65_h |
| #define wasm_support_i65_h |
| |
| #include <cstdint> |
| #include <iostream> |
| #include <limits> |
| |
| namespace wasm { |
| |
| // An integer capable of representing numbers in the combined range of 32 and |
| // 64-bit integers, both signed and unsigned. That is, in the range |
| // |
| // std::numeric_limits<int64_t>::min() .. std::numeric_limits<uint64_t>::max() |
| // |
| // This is basically an i64 combined with a u64 in terms of range, hence "IU64". |
| struct IU64 { |
| // A 64-bit payload with an extra 65th sign bit. |
| uint64_t value = 0; |
| bool negative = false; |
| |
| constexpr IU64() = default; |
| |
| // Unsigned values are simple. |
| constexpr IU64(uint32_t x) : value(x) {} |
| constexpr IU64(uint64_t x) : value(x) {} |
| |
| // Signed values need to be checked for being negative. |
| constexpr IU64(int32_t x) { |
| if (x >= 0) { |
| value = x; |
| } else { |
| negative = true; |
| value = -int64_t(x); |
| } |
| } |
| constexpr IU64(int64_t x) { |
| if (x >= 0) { |
| value = x; |
| } else { |
| negative = true; |
| |
| // One does not simply negate MIN_INT64. |
| if (x == std::numeric_limits<int64_t>::min()) { |
| value = uint64_t(1) << 63; |
| } else { |
| value = -int64_t(x); |
| } |
| } |
| } |
| |
| constexpr bool operator==(const IU64& other) const { |
| return value == other.value && negative == other.negative; |
| } |
| constexpr bool operator!=(const IU64& other) const { |
| return !(*this == other); |
| } |
| |
| constexpr bool operator<(const IU64& other) const { |
| if (negative) { |
| if (other.negative) { |
| // Both negative; we are smaller if absolute value is larger. |
| return value > other.value; |
| } else { |
| // Only we are negative, so we are smaller. |
| return true; |
| } |
| } else { |
| if (other.negative) { |
| // Only the other is negative, so we are larger. |
| return false; |
| } else { |
| // Both positive; we are smaller if absolute value is smaller. |
| return value < other.value; |
| } |
| } |
| } |
| constexpr bool operator<=(const IU64& other) const { |
| return *this < other || *this == other; |
| } |
| constexpr bool operator>(const IU64& other) const { |
| return !(*this <= other); |
| } |
| constexpr bool operator>=(const IU64& other) const { |
| return !(*this < other); |
| } |
| }; |
| |
| inline std::ostream& operator<<(std::ostream& os, const IU64& x) { |
| if (x.negative) { |
| os << '-'; |
| } |
| return os << x.value; |
| } |
| |
| } // namespace wasm |
| |
| namespace std { |
| |
| template<> class numeric_limits<wasm::IU64> { |
| public: |
| static constexpr bool is_specialized = true; |
| static constexpr bool is_signed = true; |
| static constexpr bool is_integer = true; |
| static constexpr bool is_exact = true; |
| static constexpr bool has_infinity = false; |
| static constexpr bool has_quiet_NaN = false; |
| static constexpr bool has_signaling_NaN = false; |
| static constexpr float_denorm_style has_denorm = denorm_absent; |
| static constexpr bool has_denorm_loss = false; |
| static constexpr float_round_style round_style = round_toward_zero; |
| static constexpr bool is_iec559 = false; |
| static constexpr bool is_bounded = true; |
| static constexpr bool is_modulo = false; |
| static constexpr int digits = 65; |
| static constexpr int digits10 = 19; |
| static constexpr int max_digits10 = 0; |
| static constexpr int radix = 2; |
| static constexpr int min_exponent = 0; |
| static constexpr int min_exponent10 = 0; |
| static constexpr int max_exponent = 0; |
| static constexpr int max_exponent10 = 0; |
| static constexpr bool traps = false; |
| static constexpr bool tinyness_before = false; |
| |
| static constexpr wasm::IU64 min() noexcept { |
| return wasm::IU64(std::numeric_limits<int64_t>::min()); |
| } |
| static constexpr wasm::IU64 lowest() noexcept { return min(); } |
| static constexpr wasm::IU64 max() noexcept { |
| return wasm::IU64(std::numeric_limits<uint64_t>::max()); |
| } |
| }; |
| |
| } // namespace std |
| |
| #endif // wasm_support_i65_h |