/*
 * 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 <= std::numeric_limits<uint64_t>::max();
}

bool wasm::isSInteger64(double x) {
  return isInteger(x) && x >= std::numeric_limits<int64_t>::min() &&
         x <= 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::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::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);
}
