| /* |
| * Copyright 2016 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. |
| */ |
| |
| #include <cassert> |
| #include <cmath> |
| #include <limits> |
| |
| #include "support/safe_integer.h" |
| |
| using namespace wasm; |
| |
| bool wasm::isInteger(double x) { return trunc(x) == x && !std::isinf(x); } |
| |
| bool wasm::isUInteger32(double x) { |
| return !std::signbit(x) && isInteger(x) && |
| x <= std::numeric_limits<uint32_t>::max(); |
| } |
| |
| bool wasm::isSInteger32(double x) { |
| return isInteger(x) && x >= std::numeric_limits<int32_t>::min() && |
| x <= std::numeric_limits<int32_t>::max(); |
| } |
| |
| uint32_t wasm::toUInteger32(double x) { |
| return std::signbit(x) ? 0 |
| : (x < std::numeric_limits<uint32_t>::max() |
| ? (uint32_t)x |
| : std::numeric_limits<uint32_t>::max()); |
| } |
| |
| int32_t wasm::toSInteger32(double x) { |
| return (x > std::numeric_limits<int32_t>::min() && |
| x < std::numeric_limits<int32_t>::max()) |
| ? (int32_t)x |
| : (std::signbit(x) ? std::numeric_limits<int32_t>::min() |
| : std::numeric_limits<int32_t>::max()); |
| } |
| |
| bool wasm::isUInteger64(double x) { |
| return !std::signbit(x) && isInteger(x) && |
| x <= static_cast<double>(std::numeric_limits<uint64_t>::max()); |
| } |
| |
| bool wasm::isSInteger64(double x) { |
| return isInteger(x) && x >= std::numeric_limits<int64_t>::min() && |
| x <= static_cast<double>(std::numeric_limits<int64_t>::max()); |
| } |
| |
| uint64_t wasm::toUInteger64(double x) { |
| return std::signbit(x) ? 0 |
| : (x < (double)std::numeric_limits<uint64_t>::max() |
| ? (uint64_t)x |
| : std::numeric_limits<uint64_t>::max()); |
| } |
| |
| int64_t wasm::toSInteger64(double x) { |
| return (x > (double)std::numeric_limits<int64_t>::min() && |
| x < (double)std::numeric_limits<int64_t>::max()) |
| ? (int64_t)x |
| : (std::signbit(x) ? std::numeric_limits<int64_t>::min() |
| : std::numeric_limits<int64_t>::max()); |
| } |
| |
| /* 3 32222222 222...00 |
| * 1 09876543 210...10 |
| * ------------------- |
| * 0 00000000 000...00 => 0x00000000 => 0 |
| * 0 10011101 111...11 => 0x4effffff => 2147483520 (~INT32_MAX) |
| * 0 10011110 000...00 => 0x4f000000 => 2147483648 |
| * 0 10011110 111...11 => 0x4f7fffff => 4294967040 (~UINT32_MAX) |
| * 0 10111110 111...11 => 0x5effffff => 9223371487098961920 (~INT64_MAX) |
| * 0 10111110 000...00 => 0x5f000000 => 9223372036854775808 |
| * 0 10111111 111...11 => 0x5f7fffff => 18446742974197923840 (~UINT64_MAX) |
| * 0 10111111 000...00 => 0x5f800000 => 18446744073709551616 |
| * 0 11111111 000...00 => 0x7f800000 => inf |
| * 0 11111111 000...01 => 0x7f800001 => nan(0x1) |
| * 0 11111111 111...11 => 0x7fffffff => nan(0x7fffff) |
| * 1 00000000 000...00 => 0x80000000 => -0 |
| * 1 01111110 111...11 => 0xbf7fffff => -1 + ulp (~UINT32_MIN, ~UINT64_MIN) |
| * 1 01111111 000...00 => 0xbf800000 => -1 |
| * 1 10011110 000...00 => 0xcf000000 => -2147483648 (INT32_MIN) |
| * 1 10111110 000...00 => 0xdf000000 => -9223372036854775808 (INT64_MIN) |
| * 1 11111111 000...00 => 0xff800000 => -inf |
| * 1 11111111 000...01 => 0xff800001 => -nan(0x1) |
| * 1 11111111 111...11 => 0xffffffff => -nan(0x7fffff) |
| */ |
| |
| bool wasm::isInRangeI16TruncS(int32_t i) { |
| uint32_t u = i; |
| return (u < 0x47000000U) || (u >= 0x80000000U && u <= 0xc7000000U); |
| } |
| |
| bool wasm::isInRangeI32TruncS(int32_t i) { |
| uint32_t u = i; |
| return (u < 0x4f000000U) || (u >= 0x80000000U && u <= 0xcf000000U); |
| } |
| |
| bool wasm::isInRangeI64TruncS(int32_t i) { |
| uint32_t u = i; |
| return (u < 0x5f000000U) || (u >= 0x80000000U && u <= 0xdf000000U); |
| } |
| |
| bool wasm::isInRangeI16TruncU(int32_t i) { |
| uint32_t u = i; |
| return (u < 0x47800000) || (u >= 0x80000000U && u < 0xbf800000U); |
| } |
| |
| bool wasm::isInRangeI32TruncU(int32_t i) { |
| uint32_t u = i; |
| return (u < 0x4f800000U) || (u >= 0x80000000U && u < 0xbf800000U); |
| } |
| |
| bool wasm::isInRangeI64TruncU(int32_t i) { |
| uint32_t u = i; |
| return (u < 0x5f800000U) || (u >= 0x80000000U && u < 0xbf800000U); |
| } |
| |
| /* clang-format off */ |
| /* |
| * 6 66655555555 5544...222221...000 |
| * 3 21098765432 1098...432109...210 |
| * --------------------------------- |
| * 0 00000000000 0000...000000...000 0x0000000000000000 => 0 |
| * 0 10000011101 1111...111000...111 0x41dfffffffffffff => 2147483647.9999998 (rounds down to INT32_MAX) |
| * 0 10000011110 1111...111111...111 0x41efffffffffffff => 4294967295.9999995 (rounds down to UINT32_MAX) |
| * 0 10000111101 1111...111111...111 0x43dfffffffffffff => 9223372036854774784 (~INT64_MAX) |
| * 0 10000111110 0000...000000...000 0x43e0000000000000 => 9223372036854775808 |
| * 0 10000111110 1111...111111...111 0x43efffffffffffff => 18446744073709549568 (~UINT64_MAX) |
| * 0 10000111111 0000...000000...000 0x43f0000000000000 => 18446744073709551616 |
| * 0 11111111111 0000...000000...000 0x7ff0000000000000 => inf |
| * 0 11111111111 0000...000000...001 0x7ff0000000000001 => nan(0x1) |
| * 0 11111111111 1111...111111...111 0x7fffffffffffffff => nan(0xfff...) |
| * 1 00000000000 0000...000000...000 0x8000000000000000 => -0 |
| * 1 01111111110 1111...111111...111 0xbfefffffffffffff => -1 + ulp (~UINT32_MIN, ~UINT64_MIN) |
| * 1 01111111111 0000...000000...000 0xbff0000000000000 => -1 |
| * 1 10000011110 0000...000000...111 0xc1e00000001fffff => -2147483648.9999995 (rounds up to INT32_MIN) |
| * 1 10000111110 0000...000000...000 0xc3e0000000000000 => -9223372036854775808 (INT64_MIN) |
| * 1 11111111111 0000...000000...000 0xfff0000000000000 => -inf |
| * 1 11111111111 0000...000000...001 0xfff0000000000001 => -nan(0x1) |
| * 1 11111111111 1111...111111...111 0xffffffffffffffff => -nan(0xfff...) |
| */ |
| /* clang-format on */ |
| |
| bool wasm::isInRangeI32TruncS(int64_t i) { |
| uint64_t u = i; |
| return (u <= 0x41dfffffffffffffULL) || |
| (u >= 0x8000000000000000ULL && u <= 0xc1e00000001fffffULL); |
| } |
| |
| bool wasm::isInRangeI32TruncU(int64_t i) { |
| uint64_t u = i; |
| return (u <= 0x41efffffffffffffULL) || |
| (u >= 0x8000000000000000ULL && u <= 0xbfefffffffffffffULL); |
| } |
| |
| bool wasm::isInRangeI64TruncS(int64_t i) { |
| uint64_t u = i; |
| return (u < 0x43e0000000000000ULL) || |
| (u >= 0x8000000000000000ULL && u <= 0xc3e0000000000000ULL); |
| } |
| |
| bool wasm::isInRangeI64TruncU(int64_t i) { |
| uint64_t u = i; |
| return (u < 0x43f0000000000000ULL) || |
| (u >= 0x8000000000000000ULL && u <= 0xbfefffffffffffffULL); |
| } |