Program Listing for File floats.h

Return to documentation for file (src/functional/floats.h)

#pragma once

#include "functional/defs.h"
#include "functional/operands.h"

namespace marian {
namespace functional {

namespace float2unsigned {
constexpr float abs(float x) {
  return x < 0 ? -x : x;
}

// clang-format off
constexpr int exponent(float x) {
  return abs(x) >= 2 ? exponent(x / 2) + 1 :
                       abs(x) < 1 ? exponent(x * 2) - 1 :
                                    0;
}

constexpr float scalbn(float value, int exponent) {
  return exponent == 0  ? value :
                         exponent > 0 ? scalbn(value * 2, exponent - 1) :
                                        scalbn(value / 2, exponent + 1);
}
// clang-format on

constexpr unsigned mantissa(float x, int exp) {
  // remove hidden 1 and bias the exponent to get integer
  return abs(x) < std::numeric_limits<float>::infinity()
             ? scalbn(scalbn(abs(x), -exp) - 1, 23)
             : 0;
}

constexpr unsigned to_binary(float x, unsigned sign, int exp) {
  return sign * (1u << 31) + (exp + 127) * (1u << 23) + mantissa(x, exp);
}

constexpr unsigned to_binary(float x) {
  return x == 0 ? 0 : to_binary(x, x < 0, exponent(x));
}
}  // namespace float2unsigned

namespace unsigned2float {

constexpr float sign(unsigned i) {
  return (i & (1u << 31)) ? -1.f : 1.f;
}

constexpr int exponent(unsigned i) {
  return int((i >> 23) & 255u) - 127;
}

constexpr float sig(unsigned i, unsigned shift) {
  return ((i >> shift) & 1u) * 1.f / (1u << (23 - shift))
         + (shift > 0 ? sig(i, shift - 1) : 0);
}

constexpr float powr(int exp) {
  return exp > 0 ? 2.f * powr(exp - 1) : 1.f;
}

constexpr float pow(int exp) {
  return exp < 0 ? 1.f / powr(-exp) : powr(exp);
}

constexpr float from_binary(unsigned i) {
  return (1.f + sig(i, 22u)) * pow(exponent(i)) * sign(i);
}
}  // namespace unsigned2float

constexpr unsigned f2i(float x) {
  return float2unsigned::to_binary(x);
}

constexpr float i2f(float x) {
  return unsigned2float::from_binary(x);
}

template <unsigned V>
struct F {
  static constexpr auto value = i2f(V);
  static constexpr auto binary = V;

  template <typename... Args>
  HOST_DEVICE_INLINE constexpr float operator()(Args&&... args) const {
    return value;
  }

  std::string to_string() { return "F<" + std::to_string(value) + ">"; }
};
}  // namespace functional
}  // namespace marian