blob: b91666560c8c58c0079914460506dafafe0d38a6 [file] [edit]
/*
* 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