// Copyright 2020 The Tint Authors.
//
// 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 "src/tint/writer/float_to_string.h"

#include <cmath>
#include <cstring>
#include <functional>
#include <iomanip>
#include <limits>
#include <sstream>

#include "src/tint/debug.h"

namespace tint {
namespace writer {

std::string FloatToString(float f) {
  // Try printing the float in fixed point, with a smallish limit on the
  // precision
  std::stringstream fixed;
  fixed.flags(fixed.flags() | std::ios_base::showpoint | std::ios_base::fixed);
  fixed.precision(9);
  fixed << f;

  // If this string can be parsed without loss of information, use it
  auto float_equal_no_warning = std::equal_to<float>();
  if (float_equal_no_warning(std::stof(fixed.str()), f)) {
    auto str = fixed.str();
    while (str.length() >= 2 && str[str.size() - 1] == '0' &&
           str[str.size() - 2] != '.') {
      str.pop_back();
    }

    return str;
  }

  // Resort to scientific, with the minimum precision needed to preserve the
  // whole float
  std::stringstream sci;
  sci.precision(std::numeric_limits<float>::max_digits10);
  sci << f;
  return sci.str();
}

std::string FloatToBitPreservingString(float f) {
  // For the NaN case, avoid handling the number as a floating point value.
  // Some machines will modify the top bit in the mantissa of a NaN.

  std::stringstream ss;

  uint32_t float_bits = 0u;
  std::memcpy(&float_bits, &f, sizeof(float_bits));

  // Handle the sign.
  const uint32_t kSignMask = 1u << 31;
  if (float_bits & kSignMask) {
    // If `f` is -0.0 print -0.0.
    ss << '-';
    // Strip sign bit.
    float_bits = float_bits & (~kSignMask);
  }

  switch (std::fpclassify(f)) {
    case FP_ZERO:
    case FP_NORMAL:
      std::memcpy(&f, &float_bits, sizeof(float_bits));
      ss << FloatToString(f);
      break;

    default: {
      // Infinity, NaN, and Subnormal
      // TODO(dneto): It's unclear how Infinity and NaN should be handled.
      // See https://github.com/gpuweb/gpuweb/issues/1769

      // std::hexfloat prints 'nan' and 'inf' instead of an
      // explicit representation like we want. Split it out
      // manually.
      const int kExponentBias = 127;
      const int kExponentMask = 0x7f800000;
      const int kMantissaMask = 0x007fffff;
      const int kMantissaBits = 23;

      int mantissaNibbles = (kMantissaBits + 3) / 4;

      const int biased_exponent =
          static_cast<int>((float_bits & kExponentMask) >> kMantissaBits);
      int exponent = biased_exponent - kExponentBias;
      uint32_t mantissa = float_bits & kMantissaMask;

      ss << "0x";

      if (exponent == 128) {
        if (mantissa == 0) {
          //  Infinity case.
          ss << "1p+128";
        } else {
          //  NaN case.
          //  Emit the mantissa bits as if they are left-justified after the
          //  binary point.  This is what SPIRV-Tools hex float emitter does,
          //  and it's a justifiable choice independent of the bit width
          //  of the mantissa.
          mantissa <<= (4 - (kMantissaBits % 4));
          // Remove trailing zeroes, for tidyness.
          while (0 == (0xf & mantissa)) {
            mantissa >>= 4;
            mantissaNibbles--;
          }
          ss << "1." << std::hex << std::setfill('0')
             << std::setw(mantissaNibbles) << mantissa << "p+128";
        }
      } else {
        // Subnormal, and not zero.
        TINT_ASSERT(Writer, mantissa != 0);
        const int kTopBit = (1 << kMantissaBits);

        // Shift left until we get 1.x
        while (0 == (kTopBit & mantissa)) {
          mantissa <<= 1;
          exponent--;
        }
        // Emit the leading 1, and remove it from the mantissa.
        ss << "1";
        mantissa = mantissa ^ kTopBit;
        mantissa <<= 1;
        exponent++;

        // Emit the fractional part.
        if (mantissa) {
          // Remove trailing zeroes, for tidyness
          while (0 == (0xf & mantissa)) {
            mantissa >>= 4;
            mantissaNibbles--;
          }
          ss << "." << std::hex << std::setfill('0')
             << std::setw(mantissaNibbles) << mantissa;
        }
        // Emit the exponent
        ss << "p" << std::showpos << std::dec << exponent;
      }
    }
  }
  return ss.str();
}

}  // namespace writer
}  // namespace tint
