github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/common/int128_conversion.h (about)

     1  // Copyright (C) 2018 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or
     6  // modify
     7  // it under the terms of the GNU General Public License as published by
     8  // the Free Software Foundation, either version 3 of the License, or
     9  // (at your option) any later version.
    10  //
    11  // the go-nebulas library is distributed in the hope that it will be useful,
    12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  // GNU General Public License for more details.
    15  //
    16  // You should have received a copy of the GNU General Public License
    17  // along with the go-nebulas library.  If not, see
    18  // <http://www.gnu.org/licenses/>.
    19  //
    20  
    21  #pragma once
    22  #include "common/common.h"
    23  #include "common/math.h"
    24  
    25  namespace neb {
    26  
    27  namespace internal {
    28  class int128_conversion_helper {
    29  public:
    30    inline int128_conversion_helper() { m_data.m_data = 0; }
    31    inline int128_conversion_helper(const int128_t &data) {
    32      m_data.m_data = data;
    33    }
    34  
    35    template <typename T> inline T to_float() {
    36      T one = softfloat_cast<uint32_t, typename T::value_type>(1);
    37      T limits = softfloat_cast<uint64_t, typename T::value_type>(
    38          std::numeric_limits<uint64_t>::max());
    39  
    40      return T(m_data.m_detail.m_low) +
    41             T(m_data.m_detail.m_high) * (limits + one);
    42    }
    43  
    44    template <typename T> inline int128_t from_float(const T &x) {
    45      T one = softfloat_cast<uint32_t, typename T::value_type>(1);
    46      T limits = softfloat_cast<uint64_t, typename T::value_type>(
    47          std::numeric_limits<uint64_t>::max());
    48  
    49      if (x < limits) {
    50        m_data.m_detail.m_low =
    51            softfloat_cast<typename T::value_type, uint64_t>(x);
    52        m_data.m_detail.m_high = 0;
    53        return m_data.m_data;
    54      }
    55  
    56      m_data.m_detail.m_high =
    57          softfloat_cast<typename T::value_type, int64_t>(x / (limits + one));
    58      m_data.m_detail.m_low = softfloat_cast<typename T::value_type, uint64_t>(
    59          x - m_data.m_detail.m_high * (limits + one));
    60      return m_data.m_data;
    61    }
    62  
    63    inline const int128_t &data() const { return m_data.m_data; }
    64    inline int128_t &data() { return m_data.m_data; }
    65  
    66    inline const uint64_t &low() const { return m_data.m_detail.m_low; }
    67    inline uint64_t &low() { return m_data.m_detail.m_low; }
    68  
    69    inline const int64_t &high() const { return m_data.m_detail.m_high; }
    70    inline int64_t &high() { return m_data.m_detail.m_high; }
    71  
    72  private:
    73    union _int128_t {
    74      _int128_t() { m_data = 0; }
    75      int128_t m_data;
    76      struct _detail_t {
    77        uint64_t m_low;
    78        int64_t m_high;
    79      };
    80      _detail_t m_detail;
    81    };
    82  
    83    _int128_t m_data;
    84  };
    85  } // namespace internal
    86  
    87  template <typename T> inline T to_float(const int128_t &data) {
    88    internal::int128_conversion_helper ch(data);
    89    return ch.to_float<T>();
    90  }
    91  template <typename T> inline int128_t from_float(const T &x) {
    92    internal::int128_conversion_helper ch;
    93    return ch.from_float(x);
    94  }
    95  
    96  } // namespace neb