// 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/writer/float_to_string.h"

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

#include "src/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
