mirror of
				https://github.com/ton-blockchain/ton
				synced 2025-03-09 15:40:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			145 lines
		
	
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
    This file is part of TON Blockchain Library.
 | 
						|
 | 
						|
    TON Blockchain Library is free software: you can redistribute it and/or modify
 | 
						|
    it under the terms of the GNU Lesser General Public License as published by
 | 
						|
    the Free Software Foundation, either version 2 of the License, or
 | 
						|
    (at your option) any later version.
 | 
						|
 | 
						|
    TON Blockchain Library is distributed in the hope that it will be useful,
 | 
						|
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
    GNU Lesser General Public License for more details.
 | 
						|
 | 
						|
    You should have received a copy of the GNU Lesser General Public License
 | 
						|
    along with TON Blockchain Library.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
 | 
						|
    Copyright 2017-2020 Telegram Systems LLP
 | 
						|
*/
 | 
						|
#pragma once
 | 
						|
 | 
						|
#include "common/refint.h"
 | 
						|
 | 
						|
namespace td {
 | 
						|
 | 
						|
class NegExpBinTable {
 | 
						|
  int precision, maxpw2, minpw2;
 | 
						|
  std::vector<td::BigInt256> exp_pw2_table;      // table of 2^precision * exp(- 2^k) for k = max_pw2-1 .. min_pw2
 | 
						|
  std::vector<td::RefInt256> exp_pw2_ref_table;  // same data
 | 
						|
  td::BigInt256 One;
 | 
						|
 | 
						|
 public:
 | 
						|
  NegExpBinTable(int _precision, int _maxpw2, int _minpw2) : precision(255), maxpw2(_maxpw2), minpw2(_minpw2) {
 | 
						|
    (_precision > 0 && _precision < 256 && _minpw2 <= 0 && _maxpw2 > 0 && _maxpw2 <= 256 && _minpw2 >= -256 && init() &&
 | 
						|
     adjust_precision(_precision)) ||
 | 
						|
        invalidate();
 | 
						|
  }
 | 
						|
  bool is_valid() const {
 | 
						|
    return minpw2 < maxpw2;
 | 
						|
  }
 | 
						|
  int get_precision() const {
 | 
						|
    return precision;
 | 
						|
  }
 | 
						|
  int get_exponent_precision() const {
 | 
						|
    return -minpw2;
 | 
						|
  }
 | 
						|
  int get_exponent_max_log2() const {
 | 
						|
    return maxpw2;
 | 
						|
  }
 | 
						|
  const td::BigInt256* exp_pw2(int k) const {  // returns 2^precision * exp(-2^k) or null
 | 
						|
    return (k >= minpw2 && k < maxpw2) ? &exp_pw2_table[k - minpw2] : nullptr;
 | 
						|
  }
 | 
						|
  td::RefInt256 exp_pw2_ref(int k) const {
 | 
						|
    if (k >= minpw2 && k < maxpw2) {
 | 
						|
      return exp_pw2_ref_table[k - minpw2];
 | 
						|
    } else {
 | 
						|
      return {};
 | 
						|
    }
 | 
						|
  }
 | 
						|
  bool nexpf(td::BigInt256& res, long long x, int k) const;  // res := 2^precision * exp(-x * 2^k)
 | 
						|
  td::RefInt256 nexpf(long long x, int k) const;
 | 
						|
 | 
						|
 private:
 | 
						|
  bool init();
 | 
						|
  bool init_one();
 | 
						|
  bool adjust_precision(int new_precision, int rmode = 0);
 | 
						|
  bool invalidate() {
 | 
						|
    minpw2 = maxpw2 = 0;
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  td::BigInt256 series_exp(int k) const;  // returns 2^precision * exp(-2^(-k)), k >= 0
 | 
						|
};
 | 
						|
 | 
						|
struct SuperFloat {
 | 
						|
  struct SetZero {};
 | 
						|
  struct SetOne {};
 | 
						|
  struct SetNan {};
 | 
						|
  td::uint128 m;
 | 
						|
  int s;
 | 
						|
  SuperFloat() = default;
 | 
						|
  SuperFloat(SetZero) : m(0, 0), s(0) {
 | 
						|
  }
 | 
						|
  SuperFloat(SetOne) : m(0, 1), s(0) {
 | 
						|
  }
 | 
						|
  SuperFloat(SetNan) : m(0, 0), s(std::numeric_limits<int>::min()) {
 | 
						|
  }
 | 
						|
  SuperFloat(td::uint128 _m, int _s = 0) : m(_m), s(_s) {
 | 
						|
  }
 | 
						|
  SuperFloat(td::uint64 _m, int _s = 0) : m(0, _m), s(_s) {
 | 
						|
  }
 | 
						|
  explicit SuperFloat(BigInt256 x);
 | 
						|
  static SuperFloat Zero() {
 | 
						|
    return SetZero{};
 | 
						|
  }
 | 
						|
  static SuperFloat One() {
 | 
						|
    return SetOne{};
 | 
						|
  }
 | 
						|
  static SuperFloat NaN() {
 | 
						|
    return SetNan{};
 | 
						|
  }
 | 
						|
  void set_zero() {
 | 
						|
    m = td::uint128(0, 0);
 | 
						|
    s = 0;
 | 
						|
  }
 | 
						|
  void set_one() {
 | 
						|
    m = td::uint128(0, 1);
 | 
						|
    s = 0;
 | 
						|
  }
 | 
						|
  void set_nan() {
 | 
						|
    s = std::numeric_limits<int>::min();
 | 
						|
  }
 | 
						|
  bool is_nan() const {
 | 
						|
    return s == std::numeric_limits<int>::min();
 | 
						|
  }
 | 
						|
  bool is_zero() const {
 | 
						|
    return m.is_zero();
 | 
						|
  }
 | 
						|
  bool normalize();
 | 
						|
  td::uint64 top() const {
 | 
						|
    return m.rounded_hi();
 | 
						|
  }
 | 
						|
  static td::uint128 as_uint128(const td::BigInt256& x);
 | 
						|
  static td::uint64 as_uint64(const td::BigInt256& x);
 | 
						|
};
 | 
						|
 | 
						|
class NegExpInt64Table {
 | 
						|
  enum { max_exp = 45 };
 | 
						|
  unsigned char table0_shift[max_exp + 1];
 | 
						|
  td::uint64 table0[max_exp + 1], table1[256], table2[256];
 | 
						|
 | 
						|
 public:
 | 
						|
  NegExpInt64Table();
 | 
						|
  // compute x * exp(-k / 2^16);
 | 
						|
  // more precisely: computes 0 <= y <= x for 0 <= x < 2^60, s.that |y - x * exp(-k / 2^16)| < 1
 | 
						|
  // two different implementations of this functions would return values differing by at most one
 | 
						|
  td::uint64 umulnexps32(td::uint64 x, unsigned k, bool trunc = false) const;
 | 
						|
  td::int64 mulnexps32(td::int64 x, unsigned k, bool trunc = false) const;
 | 
						|
  static const NegExpInt64Table& table();
 | 
						|
 | 
						|
 private:
 | 
						|
};
 | 
						|
 | 
						|
td::uint64 umulnexps32(td::uint64 x, unsigned k, bool trunc = false);  // compute x * exp(-k / 2^16)
 | 
						|
td::int64 mulnexps32(td::int64 x, unsigned k, bool trunc = false);
 | 
						|
 | 
						|
}  // namespace td
 |