Gav Wood
11 years ago
9 changed files with 1542 additions and 71 deletions
@ -0,0 +1,22 @@ |
|||
#include "Common.h" |
|||
#include "PatriciaTree.h" |
|||
using namespace std; |
|||
using namespace eth; |
|||
|
|||
PatriciaTree::PatriciaTree(RLP const& _data) |
|||
{ |
|||
// Make tree based on _data
|
|||
assert(_data.isList()); |
|||
if (_data.isEmpty()) |
|||
{ |
|||
// NULL node.
|
|||
} |
|||
else if (_data.isList() && _data.itemCount() == 2) |
|||
{ |
|||
// Key-value pair
|
|||
} |
|||
else if (_data.isList() && _data.itemCount() == 17) |
|||
{ |
|||
// Branch
|
|||
} |
|||
} |
@ -0,0 +1,198 @@ |
|||
#pragma once |
|||
|
|||
#include <map> |
|||
#include "RLP.h" |
|||
|
|||
namespace eth |
|||
{ |
|||
|
|||
using StringMap = std::map<std::string, std::string>; |
|||
using HexMap = std::map<bytes, std::string>; |
|||
|
|||
/*
|
|||
* Hex-prefix Notation. First nibble has flags: oddness = 2^0 & termination = 2^1 |
|||
* [0,0,1,2,3,4,5] 0x10012345 |
|||
* [0,1,2,3,4,5] 0x00012345 |
|||
* [1,2,3,4,5] 0x112345 |
|||
* [0,0,1,2,3,4] 0x00001234 |
|||
* [0,1,2,3,4] 0x101234 |
|||
* [1,2,3,4] 0x001234 |
|||
* [0,0,1,2,3,4,5,T] 0x30012345 |
|||
* [0,0,1,2,3,4,T] 0x20001234 |
|||
* [0,1,2,3,4,5,T] 0x20012345 |
|||
* [1,2,3,4,5,T] 0x312345 |
|||
* [1,2,3,4,T] 0x201234 |
|||
*/ |
|||
|
|||
std::string fromHex(bytes const& _hexVector, bool _forceTerminated = false) |
|||
{ |
|||
uint begin = 0; |
|||
uint end = _hexVector.size(); |
|||
bool termed = _forceTerminated; |
|||
bool odd = _hexVector.size() % 2; |
|||
|
|||
std::string ret(((termed ? 2 : 0) | (odd ? 1 : 0)) * 16, 1); |
|||
if (odd) |
|||
{ |
|||
ret[0] |= _hexVector[0]; |
|||
begin = 1; |
|||
} |
|||
else if (leadingZero) |
|||
for (uint i = begin; i < end; i += 2) |
|||
ret += _hexVector[i] * 16 + _hexVector[i + 1]; |
|||
return ret; |
|||
} |
|||
|
|||
template <class _T, class ... _Ts> bytes encodeRLP(_T _t, _Ts ... _ts) |
|||
{ |
|||
|
|||
} |
|||
|
|||
struct rlplist { rlplist(uint _count): count(_count) {} uint count; }; |
|||
|
|||
class RLPStream |
|||
{ |
|||
public: |
|||
RLPStream() {} |
|||
|
|||
void append(uint _s) { appendNumeric(_s); } |
|||
void append(u256 _s) { appendNumeric(_s); } |
|||
void append(bigint _s) { appendNumeric(_s); } |
|||
|
|||
void append(std::string const& _s) |
|||
{ |
|||
if (_s.size() < 0x38) |
|||
m_out.push_back(_count | 0x40); |
|||
else |
|||
pushCount(_count, 0x40); |
|||
uint os = m_out.size(); |
|||
m_out.resize(m_out.size() + _s.size()); |
|||
memcpy(m_out.data() + os, _s.data(), _s.size()); |
|||
} |
|||
|
|||
void appendList(uint _count) |
|||
{ |
|||
if (_s.size() < 0x38) |
|||
m_out.push_back(_count | 0x80); |
|||
else |
|||
pushCount(_count, 0x80); |
|||
} |
|||
|
|||
RLPStream operator<<(uint _t) { append(_i); } |
|||
RLPStream operator<<(u256 _t) { append(_i); } |
|||
RLPStream operator<<(bigint _t) { append(_i); } |
|||
RLPStream operator<<(std::string const& _s) { append(_s); } |
|||
RLPStream operator<<(rlplist _l) { m_lists.push_back(_l.count); appendList(_l.count); } |
|||
|
|||
private: |
|||
void appendNumeric(uint _i) |
|||
{ |
|||
if (_i < 0x18) |
|||
m_out.push_back(_i); |
|||
else |
|||
m_out.push_back(bytesRequired(_i) + 0x17); // max 8 bytes.
|
|||
} |
|||
|
|||
void appendNumeric(u256 _i) |
|||
{ |
|||
if (_i < 0x18) |
|||
m_out.push_back(_i); |
|||
else |
|||
m_out.push_back(bytesRequired(_i) + 0x17); // max 32 bytes.
|
|||
} |
|||
|
|||
void appendNumeric(bigint _i) |
|||
{ |
|||
if (_i < 0x18) |
|||
m_out.push_back(_i); |
|||
else |
|||
{ |
|||
uint br = bytesRequired(_i); |
|||
if (br <= 32) |
|||
m_out.push_back(bytesRequired(_i) + 0x17); // max 32 bytes.
|
|||
else |
|||
m_out.push_back(0x37 + bytesRequired(br)); |
|||
} |
|||
for (uint i = 0; i < ) |
|||
m_out.push_back() |
|||
} |
|||
|
|||
void pushCount(uint _count, byte _base) |
|||
{ |
|||
m_out.push_back(bytesRequired(_i) + 0x17); // max 8 bytes.
|
|||
} |
|||
|
|||
template <class _T> static uint bytesRequired(_T _i) |
|||
{ |
|||
_i >>= 8; |
|||
uint i = 1; |
|||
for (; _i != 0; ++i, _i >>= 8) {} |
|||
return i; |
|||
} |
|||
|
|||
bytes m_out; |
|||
}; |
|||
|
|||
template <> bytes encodeRLP(_T _t) |
|||
{ |
|||
|
|||
} |
|||
|
|||
u256 hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen) |
|||
{ |
|||
unsigned c = 0; |
|||
for (auto i = _begin; i != _end; ++i, ++c) {} |
|||
|
|||
assert(c > 0); |
|||
if (c == 1) |
|||
return sha256(encodeRLP()); |
|||
|
|||
|
|||
|
|||
for (auto i = 0; i < 16; ++i) |
|||
{ |
|||
} |
|||
} |
|||
|
|||
bytes toHex(std::string const& _s) |
|||
{ |
|||
std::vector<uint8_t> ret(_s.size() * 2 + 1); |
|||
for (auto i: _s) |
|||
{ |
|||
ret.push_back(i / 16); |
|||
ret.push_back(i % 16); |
|||
} |
|||
ret.push_back(16); |
|||
return ret; |
|||
} |
|||
|
|||
u256 hash256(StringMap const& _s) |
|||
{ |
|||
// build patricia tree.
|
|||
if (_s.empty()) |
|||
return 0; |
|||
HexMap hexMap; |
|||
for (auto const& i: _s) |
|||
hexMap[toHex(i.first)] = i.second; |
|||
return hash256aux(hexMap, hexMap.cbegin(), hexMap.cend(), 0); |
|||
} |
|||
|
|||
/**
|
|||
* @brief Merkle Patricia Tree: a modifed base-16 Radix tree. |
|||
*/ |
|||
class PatriciaTree |
|||
{ |
|||
public: |
|||
PatriciaTree() {} |
|||
~PatriciaTree() {} |
|||
|
|||
void fromRLP(RLP const& _data); |
|||
std::string toRLP(); |
|||
|
|||
private: |
|||
|
|||
}; |
|||
|
|||
} |
|||
|
|||
|
@ -0,0 +1,600 @@ |
|||
/*
|
|||
uint128_t.h |
|||
An unsigned 128 bit integer library for C++ |
|||
By Jason Lee @ calccrypto@yahoo.com |
|||
with much help from Auston Sterling |
|||
|
|||
And thanks to Stefan Deigmüller for finding |
|||
a bug in operator*. |
|||
|
|||
From http://calccrypto.wikidot.com/programming:uint128-t
|
|||
Licenced http://creativecommons.org/licenses/by-sa/3.0/
|
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <cstdlib> |
|||
#include <iostream> |
|||
#include <stdint.h> |
|||
|
|||
class uint128_t{ |
|||
private: |
|||
uint64_t UPPER, LOWER; |
|||
|
|||
public: |
|||
// Constructors
|
|||
uint128_t(){ |
|||
UPPER = 0; |
|||
LOWER = 0; |
|||
} |
|||
|
|||
template <typename T> |
|||
uint128_t(T rhs){ |
|||
UPPER = 0; |
|||
LOWER = (uint64_t) rhs; |
|||
} |
|||
|
|||
template <typename S, typename T> |
|||
uint128_t(const S upper_rhs, const T lower_rhs){ |
|||
UPPER = (uint64_t) upper_rhs; |
|||
LOWER = (uint64_t) lower_rhs; |
|||
} |
|||
|
|||
uint128_t(const uint128_t & rhs){ |
|||
UPPER = rhs.UPPER; |
|||
LOWER = rhs.LOWER; |
|||
} |
|||
|
|||
// RHS input args only
|
|||
|
|||
// Assignment Operator
|
|||
template <typename T> uint128_t operator=(T rhs){ |
|||
UPPER = 0; |
|||
LOWER = (uint64_t) rhs; |
|||
return *this; |
|||
} |
|||
|
|||
uint128_t operator=(uint128_t rhs){ |
|||
UPPER = rhs.UPPER; |
|||
LOWER = rhs.LOWER; |
|||
return *this; |
|||
} |
|||
|
|||
// Typecast Operators
|
|||
operator bool(){ |
|||
return (bool) (UPPER | LOWER); |
|||
} |
|||
|
|||
operator char(){ |
|||
return (char) LOWER; |
|||
} |
|||
|
|||
operator int(){ |
|||
return (int) LOWER; |
|||
} |
|||
|
|||
operator uint8_t(){ |
|||
return (uint8_t) LOWER; |
|||
} |
|||
|
|||
operator uint16_t(){ |
|||
return (uint16_t) LOWER; |
|||
} |
|||
|
|||
operator uint32_t(){ |
|||
return (uint32_t) LOWER; |
|||
} |
|||
|
|||
operator uint64_t(){ |
|||
return LOWER; |
|||
} |
|||
|
|||
// Bitwise Operators
|
|||
template <typename T> uint128_t operator&(T rhs){ |
|||
return uint128_t(0, LOWER & (uint64_t) rhs); |
|||
} |
|||
|
|||
uint128_t operator&(uint128_t rhs){ |
|||
return uint128_t(UPPER & rhs.UPPER, LOWER & rhs.LOWER); |
|||
} |
|||
|
|||
template <typename T> uint128_t operator|(T rhs){ |
|||
return uint128_t(UPPER, LOWER | (uint64_t) rhs); |
|||
} |
|||
|
|||
uint128_t operator|(uint128_t rhs){ |
|||
return uint128_t(UPPER | rhs.UPPER, LOWER | rhs.LOWER); |
|||
} |
|||
|
|||
template <typename T> uint128_t operator^(T rhs){ |
|||
return uint128_t(UPPER, LOWER ^ (uint64_t) rhs); |
|||
} |
|||
|
|||
uint128_t operator^(uint128_t rhs){ |
|||
return uint128_t(UPPER ^ rhs.UPPER, LOWER ^ rhs.LOWER); |
|||
} |
|||
|
|||
template <typename T> uint128_t operator&=(T rhs){ |
|||
UPPER = 0; |
|||
LOWER &= rhs; |
|||
return *this; |
|||
} |
|||
|
|||
uint128_t operator&=(uint128_t rhs){ |
|||
UPPER &= rhs.UPPER; |
|||
LOWER &= rhs.LOWER; |
|||
return *this; |
|||
} |
|||
|
|||
template <typename T> uint128_t operator|=(T rhs){ |
|||
LOWER |= (uint64_t) rhs; |
|||
return *this; |
|||
} |
|||
|
|||
uint128_t operator|=(uint128_t rhs){ |
|||
UPPER |= rhs.UPPER; |
|||
LOWER |= rhs.LOWER; |
|||
return *this; |
|||
} |
|||
|
|||
template <typename T> uint128_t operator^=(T rhs){ |
|||
LOWER ^= (uint64_t) rhs; |
|||
return *this; |
|||
} |
|||
|
|||
uint128_t operator^=(const uint128_t rhs){ |
|||
UPPER ^= rhs.UPPER; |
|||
LOWER ^= rhs.LOWER; |
|||
return *this; |
|||
} |
|||
|
|||
uint128_t operator~(){ |
|||
return uint128_t(~UPPER, ~LOWER); |
|||
} |
|||
|
|||
// Bit Shift Operators
|
|||
template <typename T> |
|||
uint128_t operator<<(const T shift){ |
|||
if (shift >= 128) |
|||
return uint128_t(0, 0); |
|||
else if (shift == 64) |
|||
return uint128_t(LOWER, 0); |
|||
else if (shift == 0) |
|||
return *this; |
|||
else if (shift < 64) |
|||
return uint128_t((UPPER << shift) + (LOWER >> (64 - shift)), LOWER << shift); |
|||
else if ((128 > shift) && (shift > 64)) |
|||
return uint128_t(LOWER << (shift - 64), 0); |
|||
else |
|||
return uint128_t(0); |
|||
} |
|||
|
|||
template <typename T> |
|||
uint128_t operator>>(const T shift){ |
|||
if (shift >= 128) |
|||
return uint128_t(0, 0); |
|||
else if (shift == 64) |
|||
return uint128_t(0, UPPER); |
|||
else if (shift == 0) |
|||
return *this; |
|||
else if (shift < 64) |
|||
return uint128_t(UPPER >> shift, (UPPER << (64 - shift)) + (LOWER >> shift)); |
|||
else if ((128 > shift) && (shift > 64)) |
|||
return uint128_t(0, (UPPER >> (shift - 64))); |
|||
else |
|||
return uint128_t(0); |
|||
} |
|||
|
|||
uint128_t operator<<=(int shift){ |
|||
*this = *this << shift; |
|||
return *this; |
|||
} |
|||
|
|||
uint128_t operator>>=(int shift){ |
|||
*this = *this >> shift; |
|||
return *this; |
|||
} |
|||
|
|||
// Logical Operators
|
|||
bool operator!(){ |
|||
return !(bool) (UPPER | LOWER); |
|||
} |
|||
|
|||
template <typename T> bool operator&&(T rhs){ |
|||
return (bool) *this && rhs; |
|||
} |
|||
|
|||
template <typename T> bool operator&&(uint128_t rhs){ |
|||
return (bool) *this && (bool) rhs; |
|||
} |
|||
|
|||
template <typename T> bool operator||(T rhs){ |
|||
return ((bool) *this) || rhs; |
|||
|
|||
} |
|||
|
|||
template <typename T> bool operator||(uint128_t rhs){ |
|||
return ((bool) *this) || (bool) rhs; |
|||
} |
|||
|
|||
// Comparison Operators
|
|||
template <typename T> bool operator==(T rhs){ |
|||
return (!UPPER && (LOWER == (uint64_t) rhs)); |
|||
} |
|||
|
|||
bool operator==(uint128_t rhs){ |
|||
return ((UPPER == rhs.UPPER) && (LOWER == rhs.LOWER)); |
|||
} |
|||
|
|||
template <typename T> bool operator!=(T rhs){ |
|||
return (UPPER | (LOWER != (uint64_t) rhs)); |
|||
} |
|||
|
|||
bool operator!=(uint128_t rhs){ |
|||
return ((UPPER != rhs.UPPER) | (LOWER != rhs.LOWER)); |
|||
} |
|||
|
|||
template <typename T> bool operator>(T rhs){ |
|||
if (UPPER) |
|||
return true; |
|||
return (LOWER > (uint64_t) rhs); |
|||
} |
|||
|
|||
bool operator>(uint128_t rhs){ |
|||
if (UPPER == rhs.UPPER) |
|||
return (LOWER > rhs.LOWER); |
|||
if (UPPER > rhs.UPPER) |
|||
return true; |
|||
return false; |
|||
} |
|||
|
|||
template <typename T> bool operator<(T rhs){ |
|||
if (!UPPER) |
|||
return (LOWER < (uint64_t) rhs); |
|||
return false; |
|||
} |
|||
|
|||
bool operator<(uint128_t rhs){ |
|||
if (UPPER == rhs.UPPER) |
|||
return (LOWER < rhs.LOWER); |
|||
if (UPPER < rhs.UPPER) |
|||
return true; |
|||
return false; |
|||
} |
|||
|
|||
template <typename T> bool operator>=(T rhs){ |
|||
return ((*this > rhs) | (*this == rhs)); |
|||
} |
|||
|
|||
bool operator>=(uint128_t rhs){ |
|||
return ((*this > rhs) | (*this == rhs)); |
|||
} |
|||
|
|||
template <typename T> bool operator<=(T rhs){ |
|||
return ((*this < rhs) | (*this == rhs)); |
|||
} |
|||
|
|||
bool operator<=(uint128_t rhs){ |
|||
return ((*this < rhs) | (*this == rhs)); |
|||
} |
|||
|
|||
// Arithmetic Operators
|
|||
template <typename T> uint128_t operator+(T rhs){ |
|||
return uint128_t(UPPER + ((LOWER + (uint64_t) rhs) < LOWER), LOWER + (uint64_t) rhs); |
|||
} |
|||
|
|||
uint128_t operator+(uint128_t rhs){ |
|||
return uint128_t(rhs.UPPER + UPPER + ((LOWER + rhs.LOWER) < LOWER), LOWER + rhs.LOWER); |
|||
} |
|||
|
|||
template <typename T> uint128_t operator+=(T rhs){ |
|||
UPPER = UPPER + ((LOWER + rhs) < LOWER); |
|||
LOWER = LOWER + rhs; |
|||
return *this; |
|||
} |
|||
|
|||
uint128_t operator+=(uint128_t rhs){ |
|||
UPPER = rhs.UPPER + UPPER + ((LOWER + rhs.LOWER) < LOWER); |
|||
LOWER = LOWER + rhs.LOWER; |
|||
return *this; |
|||
} |
|||
|
|||
template <typename T> uint128_t operator-(T rhs){ |
|||
return uint128_t((uint64_t) (UPPER - ((LOWER - rhs) > LOWER)), (uint64_t) (LOWER - rhs)); |
|||
} |
|||
|
|||
uint128_t operator-(uint128_t rhs){ |
|||
return uint128_t(UPPER - rhs.UPPER - ((LOWER - rhs.LOWER) > LOWER), LOWER - rhs.LOWER); |
|||
} |
|||
|
|||
template <typename T> uint128_t operator-=(T rhs){ |
|||
*this = *this - rhs; |
|||
return *this; |
|||
} |
|||
|
|||
uint128_t operator-=(uint128_t rhs){ |
|||
*this = *this - rhs; |
|||
return *this; |
|||
} |
|||
|
|||
template <typename T> uint128_t operator*(T rhs){ |
|||
return *this * uint128_t(rhs); |
|||
} |
|||
|
|||
uint128_t operator*(uint128_t rhs){ |
|||
// split values into 4 32-bit parts
|
|||
uint64_t top[4] = {UPPER >> 32, UPPER % 0x100000000ULL, LOWER >> 32, LOWER % 0x100000000ULL}; |
|||
uint64_t bottom[4] = {rhs.upper() >> 32, rhs.upper() % 0x100000000ULL, rhs.lower() >> 32, rhs.lower() % 0x100000000ULL}; |
|||
uint64_t products[4][4]; |
|||
|
|||
for(int y = 3; y > -1; y--) |
|||
for(int x = 3; x > -1; x--){ |
|||
products[3 - x][y] = top[x] * bottom[y]; |
|||
} |
|||
|
|||
// initial row
|
|||
uint64_t fourth32 = products[0][3] % 0x100000000ULL; |
|||
uint64_t third32 = products[0][2] % 0x100000000ULL + (products[0][3] >> 32); |
|||
uint64_t second32 = products[0][1] % 0x100000000ULL + (products[0][2] >> 32); |
|||
uint64_t first32 = products[0][0] % 0x100000000ULL + (products[0][1] >> 32); |
|||
|
|||
// second row
|
|||
third32 += products[1][3] % 0x100000000ULL; |
|||
second32 += (products[1][2] % 0x100000000ULL) + (products[1][3] >> 32); |
|||
first32 += (products[1][1] % 0x100000000ULL) + (products[1][2] >> 32); |
|||
|
|||
// third row
|
|||
second32 += products[2][3] % 0x100000000ULL; |
|||
first32 += (products[2][2] % 0x100000000ULL) + (products[2][3] >> 32); |
|||
|
|||
// fourth row
|
|||
first32 += products[3][3] % 0x100000000ULL; |
|||
|
|||
// combines the values, taking care of carry over
|
|||
return uint128_t(first32 << 32, 0) + uint128_t(third32 >> 32, third32 << 32) + uint128_t(second32, 0) + uint128_t(fourth32); |
|||
} |
|||
|
|||
template <typename T> uint128_t operator*=(T rhs){ |
|||
*this = *this * uint128_t(rhs); |
|||
return *this; |
|||
} |
|||
|
|||
uint128_t operator*=(uint128_t rhs){ |
|||
*this = *this * rhs; |
|||
return *this; |
|||
} |
|||
|
|||
template <typename T> uint128_t operator/(T rhs){ |
|||
return *this / uint128_t(rhs); |
|||
} |
|||
|
|||
uint128_t operator/(uint128_t rhs){ |
|||
// Save some calculations /////////////////////
|
|||
if (rhs == 0){ |
|||
std::cout << "Error: division or modulus by zero" << std::endl; |
|||
exit(1); |
|||
} |
|||
if (rhs == 1) |
|||
return *this; |
|||
if (*this == rhs) |
|||
return uint128_t(1); |
|||
if ((*this == 0) | (*this < rhs)) |
|||
return uint128_t(0); |
|||
// Checks for divisors that are powers of two
|
|||
uint16_t s = 0; |
|||
uint128_t copyd(rhs); |
|||
while ((copyd.LOWER & 1) == 0){ |
|||
copyd >>= 1; |
|||
s++; |
|||
} |
|||
if (copyd == 1) |
|||
return *this >> s; |
|||
////////////////////////////////////////////////
|
|||
uint128_t copyn(*this), quotient = 0; |
|||
while (copyn >= rhs){ |
|||
uint128_t copyd(rhs), temp(1); |
|||
// shift the divsor to match the highest bit
|
|||
while ((copyn >> 1) > copyd){ |
|||
copyd <<= 1; |
|||
temp <<= 1; |
|||
} |
|||
copyn -= copyd; |
|||
quotient += temp; |
|||
} |
|||
return quotient; |
|||
} |
|||
|
|||
template <typename T> uint128_t operator/=(T rhs){ |
|||
*this = *this / uint128_t(rhs); |
|||
return *this; |
|||
} |
|||
|
|||
uint128_t operator/=(uint128_t rhs){ |
|||
*this = *this / rhs; |
|||
return *this; |
|||
} |
|||
|
|||
template <typename T> uint128_t operator%(T rhs){ |
|||
return *this - (rhs * (*this / rhs)); |
|||
} |
|||
|
|||
uint128_t operator%(uint128_t rhs){ |
|||
return *this - (rhs * (*this / rhs)); |
|||
} |
|||
|
|||
template <typename T> uint128_t operator%=(T rhs){ |
|||
*this = *this % uint128_t(rhs); |
|||
return *this; |
|||
} |
|||
|
|||
uint128_t operator%=(uint128_t rhs){ |
|||
*this = *this % rhs; |
|||
return *this; |
|||
} |
|||
|
|||
// Increment Operator
|
|||
uint128_t operator++(){ |
|||
*this += 1; |
|||
return *this; |
|||
} |
|||
|
|||
uint128_t operator++(int){ |
|||
uint128_t temp(*this); |
|||
++*this; |
|||
return temp; |
|||
} |
|||
|
|||
// Decrement Operator
|
|||
uint128_t operator--(){ |
|||
*this -= 1; |
|||
return *this; |
|||
} |
|||
|
|||
uint128_t operator--(int){ |
|||
uint128_t temp(*this); |
|||
--*this; |
|||
return temp; |
|||
} |
|||
|
|||
// get private values
|
|||
uint64_t upper(){ |
|||
return UPPER; |
|||
} |
|||
|
|||
uint64_t lower(){ |
|||
return LOWER; |
|||
} |
|||
}; |
|||
// lhs type T as first arguemnt
|
|||
|
|||
// Bitwise Operators
|
|||
template <typename T> T operator&(T lhs, uint128_t rhs){ |
|||
T out = lhs & (T) rhs.lower(); |
|||
return out; |
|||
} |
|||
|
|||
template <typename T> T operator|(T lhs, uint128_t rhs){ |
|||
T out = lhs | (T) rhs.lower(); |
|||
return out; |
|||
} |
|||
|
|||
template <typename T> T operator^(T lhs, uint128_t rhs){ |
|||
T out = lhs ^ (T) rhs.lower(); |
|||
return out; |
|||
} |
|||
|
|||
template <typename T> T operator&=(T & lhs, uint128_t rhs){ |
|||
lhs &= (T) rhs.lower(); |
|||
return lhs; |
|||
} |
|||
|
|||
template <typename T> T operator|=(T & lhs, uint128_t rhs){ |
|||
lhs |= (T) rhs.lower(); |
|||
return lhs; |
|||
} |
|||
|
|||
template <typename T> T operator^=(T & lhs, uint128_t rhs){ |
|||
lhs ^= (T) rhs.lower(); |
|||
return lhs; |
|||
} |
|||
|
|||
// Comparison Operators
|
|||
template <typename T> bool operator==(T lhs, uint128_t rhs){ |
|||
return (!rhs.upper() && ((uint64_t) lhs == rhs.lower())); |
|||
} |
|||
|
|||
template <typename T> bool operator!=(T lhs, uint128_t rhs){ |
|||
return (rhs.upper() | ((uint64_t) lhs != rhs.lower())); |
|||
} |
|||
|
|||
template <typename T> bool operator>(T lhs, uint128_t rhs){ |
|||
if (rhs.upper()) |
|||
return false; |
|||
return ((uint64_t) lhs > rhs.lower()); |
|||
} |
|||
|
|||
template <typename T> bool operator<(T lhs, uint128_t rhs){ |
|||
if (rhs.upper()) |
|||
return true; |
|||
return ((uint64_t) lhs < rhs.lower()); |
|||
} |
|||
|
|||
template <typename T> bool operator>=(T lhs, uint128_t rhs){ |
|||
if (rhs.upper()) |
|||
return false; |
|||
return ((uint64_t) lhs >= rhs.lower()); |
|||
} |
|||
|
|||
template <typename T> bool operator<=(T lhs, uint128_t rhs){ |
|||
if (rhs.upper()) |
|||
return true; |
|||
return ((uint64_t) lhs <= rhs.lower()); |
|||
} |
|||
|
|||
// Arithmetic Operators
|
|||
template <typename T> T operator+(T lhs, uint128_t rhs){ |
|||
return (T) (rhs + lhs); |
|||
} |
|||
|
|||
template <typename T> T & operator+=(T & lhs, uint128_t rhs){ |
|||
lhs = (T) (rhs + lhs); |
|||
return lhs; |
|||
} |
|||
|
|||
template <typename T> T operator-(T lhs, uint128_t rhs){ |
|||
return (T) (rhs - lhs); |
|||
} |
|||
|
|||
template <typename T> T & operator-=(T & lhs, uint128_t rhs){ |
|||
lhs = (T) (rhs - lhs); |
|||
return lhs; |
|||
} |
|||
|
|||
template <typename T> T operator*(T lhs, uint128_t rhs){ |
|||
return lhs * rhs.lower(); |
|||
} |
|||
|
|||
template <typename T> T & operator*=(T & lhs, uint128_t rhs){ |
|||
lhs = (T) (rhs.lower() * lhs); |
|||
return lhs; |
|||
} |
|||
|
|||
template <typename T> T operator/(T lhs, uint128_t rhs){ |
|||
return (T) (uint128_t(lhs) / rhs); |
|||
} |
|||
|
|||
template <typename T> T & operator/=(T & lhs, uint128_t rhs){ |
|||
lhs = (T) (uint128_t(lhs) / rhs); |
|||
return lhs; |
|||
} |
|||
|
|||
template <typename T> T operator%(T lhs, uint128_t rhs){ |
|||
return (T) (uint128_t(lhs) % rhs); |
|||
} |
|||
|
|||
template <typename T> T & operator%=(T & lhs, uint128_t rhs){ |
|||
lhs = (T) (uint128_t(lhs) % rhs); |
|||
return lhs; |
|||
} |
|||
|
|||
// IO Operator
|
|||
inline std::ostream & operator<<(std::ostream & stream, uint128_t rhs){ |
|||
std::string out = ""; |
|||
if (rhs == 0) |
|||
out = "0"; |
|||
else { |
|||
int div = 10; |
|||
if (stream.flags() & stream.oct) |
|||
div = 8; |
|||
if (stream.flags() & stream.dec) |
|||
div = 10; |
|||
if (stream.flags() & stream.hex) |
|||
div = 16; |
|||
while (rhs > 0){ |
|||
out = "0123456789abcdef"[size_t(rhs % div)] + out; |
|||
rhs /= div; |
|||
} |
|||
} |
|||
stream << out; |
|||
return stream; |
|||
} |
@ -0,0 +1,606 @@ |
|||
/*
|
|||
uint256_t.h |
|||
An unsigned 256 bit integer library for C++ |
|||
By Jason Lee @ calccrypto@yahoo.com |
|||
with much help from Auston Sterling |
|||
|
|||
From http://calccrypto.wikidot.com/programming:uint256-t
|
|||
Licenced http://creativecommons.org/licenses/by-sa/3.0/
|
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <cstdlib> |
|||
#include <iostream> |
|||
#include <stdint.h> |
|||
|
|||
#include "uint128_t.h" |
|||
|
|||
class uint256_t{ |
|||
private: |
|||
uint128_t UPPER, LOWER; |
|||
|
|||
public: |
|||
// Constructors
|
|||
uint256_t(){ |
|||
UPPER = 0; |
|||
LOWER = 0; |
|||
} |
|||
|
|||
template <typename T> |
|||
uint256_t(T rhs){ |
|||
UPPER = 0; |
|||
LOWER = (uint128_t) rhs; |
|||
} |
|||
|
|||
template <typename S, typename T> |
|||
uint256_t(const S upper_rhs, const T lower_rhs){ |
|||
UPPER = (uint128_t) upper_rhs; |
|||
LOWER = (uint128_t) lower_rhs; |
|||
} |
|||
|
|||
uint256_t(const uint256_t & rhs){ |
|||
UPPER = rhs.UPPER; |
|||
LOWER = rhs.LOWER; |
|||
} |
|||
|
|||
// RHS input args only
|
|||
|
|||
// Assignment Operator
|
|||
template <typename T> uint256_t operator=(T rhs){ |
|||
UPPER = 0; |
|||
LOWER = (uint128_t) rhs; |
|||
return *this; |
|||
} |
|||
|
|||
uint256_t operator=(uint256_t rhs){ |
|||
UPPER = rhs.UPPER; |
|||
LOWER = rhs.LOWER; |
|||
return *this; |
|||
} |
|||
|
|||
// Typecast Operators
|
|||
operator bool(){ |
|||
return (bool) (UPPER | LOWER); |
|||
} |
|||
|
|||
operator char(){ |
|||
return (char) LOWER; |
|||
} |
|||
|
|||
operator int(){ |
|||
return (int) LOWER; |
|||
} |
|||
|
|||
operator uint8_t(){ |
|||
return (uint8_t) LOWER; |
|||
} |
|||
|
|||
operator uint16_t(){ |
|||
return (uint16_t) LOWER; |
|||
} |
|||
|
|||
operator uint32_t(){ |
|||
return (uint32_t) LOWER; |
|||
} |
|||
|
|||
operator uint64_t(){ |
|||
return (uint64_t) LOWER; |
|||
} |
|||
|
|||
operator uint128_t(){ |
|||
return LOWER; |
|||
} |
|||
|
|||
// Bitwise Operators
|
|||
template <typename T> uint256_t operator&(T rhs){ |
|||
return uint256_t(0, LOWER & (uint128_t) rhs); |
|||
} |
|||
|
|||
uint256_t operator&(uint256_t rhs){ |
|||
return uint256_t(UPPER & rhs.UPPER, LOWER & rhs.LOWER); |
|||
} |
|||
|
|||
template <typename T> uint256_t operator|(T rhs){ |
|||
return uint256_t(UPPER, LOWER | uint128_t(rhs)); |
|||
} |
|||
|
|||
uint256_t operator|(uint256_t rhs){ |
|||
return uint256_t(UPPER | rhs.UPPER, LOWER | rhs.LOWER); |
|||
} |
|||
|
|||
template <typename T> uint256_t operator^(T rhs){ |
|||
return uint256_t(UPPER, LOWER ^ (uint128_t) rhs); |
|||
} |
|||
|
|||
uint256_t operator^(uint256_t rhs){ |
|||
return uint256_t(UPPER ^ rhs.UPPER, LOWER ^ rhs.LOWER); |
|||
} |
|||
|
|||
template <typename T> uint256_t operator&=(T rhs){ |
|||
UPPER = 0; |
|||
LOWER &= rhs; |
|||
return *this; |
|||
} |
|||
|
|||
uint256_t operator&=(uint256_t rhs){ |
|||
UPPER &= rhs.UPPER; |
|||
LOWER &= rhs.LOWER; |
|||
return *this; |
|||
} |
|||
|
|||
template <typename T> uint256_t operator|=(T rhs){ |
|||
LOWER |= (uint128_t) rhs; |
|||
return *this; |
|||
} |
|||
|
|||
uint256_t operator|=(uint256_t rhs){ |
|||
UPPER |= rhs.UPPER; |
|||
LOWER |= rhs.LOWER; |
|||
return *this; |
|||
} |
|||
|
|||
template <typename T> uint256_t operator^=(T rhs){ |
|||
LOWER ^= (uint128_t) rhs; |
|||
return *this; |
|||
} |
|||
|
|||
uint256_t operator^=(const uint256_t rhs){ |
|||
UPPER ^= rhs.UPPER; |
|||
LOWER ^= rhs.LOWER; |
|||
return *this; |
|||
} |
|||
|
|||
uint256_t operator~(){ |
|||
return uint256_t(~UPPER, ~LOWER); |
|||
} |
|||
|
|||
// Bit Shift Operators
|
|||
uint256_t operator<<(int shift){ |
|||
if (shift >= 256) |
|||
return uint256_t(0, 0); |
|||
else if (shift == 128) |
|||
return uint256_t(LOWER, 0); |
|||
else if (shift == 0) |
|||
return *this; |
|||
else if (shift < 128) |
|||
return uint256_t((UPPER << shift) + (LOWER >> (128 - shift)), LOWER << shift); |
|||
else if ((256 > shift) && (shift > 128)) |
|||
return uint256_t(LOWER << (shift - 128), 0); |
|||
else |
|||
return uint256_t(0); |
|||
} |
|||
|
|||
template <typename T> |
|||
uint256_t operator>>(const T shift){ |
|||
if (shift >= 256) |
|||
return uint256_t(0, 0); |
|||
else if (shift == 128) |
|||
return uint256_t(0, UPPER); |
|||
else if (shift == 0) |
|||
return *this; |
|||
else if (shift < 128) |
|||
return uint256_t(UPPER >> shift, (UPPER << (128 - shift)) + (LOWER >> shift)); |
|||
else if ((256 > shift) && (shift > 128)) |
|||
return uint256_t(0, (UPPER >> (shift - 128))); |
|||
else |
|||
return uint256_t(0); |
|||
} |
|||
|
|||
uint256_t operator<<=(const int shift){ |
|||
*this = *this << shift; |
|||
return *this; |
|||
} |
|||
|
|||
uint256_t operator>>=(int shift){ |
|||
*this = *this >> shift; |
|||
return *this; |
|||
} |
|||
|
|||
// Logical Operators
|
|||
bool operator!(){ |
|||
return !(bool) (UPPER | LOWER); |
|||
} |
|||
|
|||
template <typename T> bool operator&&(T rhs){ |
|||
return (bool) *this && rhs; |
|||
} |
|||
|
|||
template <typename T> bool operator&&(uint256_t rhs){ |
|||
return (bool) *this && (bool) rhs; |
|||
} |
|||
|
|||
template <typename T> bool operator||(T rhs){ |
|||
return ((bool) *this) || rhs; |
|||
|
|||
} |
|||
|
|||
template <typename T> bool operator||(uint256_t rhs){ |
|||
return ((bool) *this) || (bool) rhs; |
|||
} |
|||
|
|||
// Comparison Operators
|
|||
template <typename T> bool operator==(T rhs){ |
|||
return (!UPPER && (LOWER == uint128_t(rhs))); |
|||
} |
|||
|
|||
bool operator==(uint256_t rhs){ |
|||
return ((UPPER == rhs.UPPER) && (LOWER == rhs.LOWER)); |
|||
} |
|||
|
|||
template <typename T> bool operator!=(T rhs){ |
|||
return (UPPER | (LOWER != (uint128_t) rhs)); |
|||
} |
|||
|
|||
bool operator==(uint128_t rhs){ |
|||
return (!UPPER && (LOWER == rhs)); |
|||
} |
|||
|
|||
bool operator!=(uint256_t rhs){ |
|||
return ((UPPER != rhs.UPPER) | (LOWER != rhs.LOWER)); |
|||
} |
|||
|
|||
template <typename T> bool operator>(T rhs){ |
|||
if (UPPER) |
|||
return true; |
|||
return (LOWER > (uint128_t) rhs); |
|||
} |
|||
|
|||
bool operator>(uint256_t rhs){ |
|||
if (UPPER == rhs.UPPER) |
|||
return (LOWER > rhs.LOWER); |
|||
if (UPPER > rhs.UPPER) |
|||
return true; |
|||
return false; |
|||
} |
|||
|
|||
template <typename T> bool operator<(T rhs){ |
|||
if (!UPPER) |
|||
return (LOWER < (uint128_t) rhs); |
|||
return false; |
|||
} |
|||
|
|||
bool operator<(uint256_t rhs){ |
|||
if (UPPER == rhs.UPPER) |
|||
return (LOWER < rhs.LOWER); |
|||
if (UPPER < rhs.UPPER) |
|||
return true; |
|||
return false; |
|||
} |
|||
|
|||
template <typename T> bool operator>=(T rhs){ |
|||
return ((*this > rhs) | (*this == rhs)); |
|||
} |
|||
|
|||
bool operator>=(uint256_t rhs){ |
|||
return ((*this > rhs) | (*this == rhs)); |
|||
} |
|||
|
|||
template <typename T> bool operator<=(T rhs){ |
|||
return ((*this < rhs) | (*this == rhs)); |
|||
} |
|||
|
|||
bool operator<=(uint256_t rhs){ |
|||
return ((*this < rhs) | (*this == rhs)); |
|||
} |
|||
|
|||
// Arithmetic Operators
|
|||
template <typename T> uint256_t operator+(T rhs){ |
|||
return uint256_t(UPPER + ((LOWER + (uint128_t) rhs) < LOWER), LOWER + (uint128_t) rhs); |
|||
} |
|||
|
|||
uint256_t operator+(uint256_t rhs){ |
|||
return uint256_t(rhs.UPPER + UPPER + ((LOWER + rhs.LOWER) < LOWER), LOWER + rhs.LOWER); |
|||
} |
|||
|
|||
template <typename T> uint256_t operator+=(T rhs){ |
|||
UPPER = UPPER + ((LOWER + rhs) < LOWER); |
|||
LOWER = LOWER + rhs; |
|||
return *this; |
|||
} |
|||
|
|||
uint256_t operator+=(uint256_t rhs){ |
|||
UPPER = rhs.UPPER + UPPER + ((LOWER + rhs.LOWER) < LOWER); |
|||
LOWER = LOWER + rhs.LOWER; |
|||
return *this; |
|||
} |
|||
|
|||
template <typename T> uint256_t operator-(T rhs){ |
|||
return uint256_t(UPPER - ((LOWER - rhs) > LOWER), LOWER - rhs); |
|||
} |
|||
|
|||
uint256_t operator-(uint256_t rhs){ |
|||
return uint256_t(UPPER - rhs.UPPER - ((LOWER - rhs.LOWER) > LOWER), LOWER - rhs.LOWER);; |
|||
} |
|||
|
|||
template <typename T> uint256_t operator-=(T rhs){ |
|||
*this = *this - rhs; |
|||
return *this; |
|||
} |
|||
|
|||
uint256_t operator-=(uint256_t rhs){ |
|||
*this = *this - rhs; |
|||
return *this; |
|||
} |
|||
|
|||
template <typename T> uint256_t operator*(T rhs){ |
|||
return *this * uint256_t(rhs); |
|||
} |
|||
|
|||
uint256_t operator*(uint256_t rhs){ |
|||
// split values into 4 64-bit parts
|
|||
uint128_t top[4] = {UPPER >> 64, UPPER % uint128_t(1, 0), LOWER >> 64, LOWER % uint128_t(1, 0)}; |
|||
uint128_t bottom[4] = {rhs.upper() >> 64, rhs.upper() % uint128_t(1, 0), rhs.lower() >> 64, rhs.lower() % uint128_t(1, 0)}; |
|||
uint128_t products[4][4]; |
|||
|
|||
for(int y = 3; y > -1; y--) |
|||
for(int x = 3; x > -1; x--){ |
|||
products[3 - x][y] = top[x] * bottom[y]; |
|||
} |
|||
|
|||
// initial row
|
|||
uint128_t fourth64 = products[0][3] % uint128_t(1, 0); |
|||
uint128_t third64 = products[0][2] % uint128_t(1, 0) + (products[0][3] >> 64); |
|||
uint128_t second64 = products[0][1] % uint128_t(1, 0) + (products[0][2] >> 64); |
|||
uint128_t first64 = products[0][0] % uint128_t(1, 0) + (products[0][1] >> 64); |
|||
|
|||
// second row
|
|||
third64 += products[1][3] % uint128_t(1, 0); |
|||
second64 += (products[1][2] % uint128_t(1, 0)) + (products[1][3] >> 64); |
|||
first64 += (products[1][1] % uint128_t(1, 0)) + (products[1][2] >> 64); |
|||
|
|||
// third row
|
|||
second64 += products[2][3] % uint128_t(1, 0); |
|||
first64 += (products[2][2] % uint128_t(1, 0)) + (products[2][3] >> 64); |
|||
|
|||
// fourth row
|
|||
first64 += products[3][3] % uint128_t(1, 0); |
|||
|
|||
// combines the values, taking care of carry over
|
|||
return uint256_t(first64 << 64, 0) + uint256_t(third64 >> 64, third64 << 64) + uint256_t(second64, 0) + uint256_t(fourth64); |
|||
} |
|||
|
|||
template <typename T> uint256_t operator*=(T rhs){ |
|||
*this = *this * uint256_t(rhs); |
|||
return *this; |
|||
} |
|||
|
|||
uint256_t operator*=(uint256_t rhs){ |
|||
*this = *this * rhs; |
|||
return *this; |
|||
} |
|||
|
|||
template <typename T> uint256_t operator/(T rhs){ |
|||
return *this / uint256_t(rhs); |
|||
} |
|||
|
|||
uint256_t operator/(uint256_t rhs){ |
|||
// Save some calculations //////////////////////
|
|||
if (rhs == 0){ |
|||
std::cout << "Error: division or modulus by zero" << std::endl; |
|||
exit(1); |
|||
} |
|||
if (rhs == 1) |
|||
return *this; |
|||
if (*this == rhs) |
|||
return uint256_t(1); |
|||
if ((*this == 0) | (*this < rhs)) |
|||
return uint256_t(0); |
|||
// Checks for divisors that are powers of two
|
|||
uint16_t s = 0; |
|||
uint256_t copyd(rhs); |
|||
while ((copyd.LOWER & 1) == 0){ |
|||
copyd >>= 1; |
|||
s++; |
|||
} |
|||
if (copyd == 1) |
|||
return *this >> s; |
|||
////////////////////////////////////////////////
|
|||
uint256_t copyn(*this), quotient = 0; |
|||
while (copyn >= rhs){ |
|||
uint256_t copyd(rhs), temp(1); |
|||
// shift the divosr to match the highest bit
|
|||
while ((copyn >> 1) > copyd){ |
|||
copyd <<= 1; |
|||
temp <<= 1; |
|||
} |
|||
copyn -= copyd; |
|||
quotient += temp; |
|||
} |
|||
return quotient; |
|||
} |
|||
|
|||
template <typename T> uint256_t operator/=(T rhs){ |
|||
*this = *this / uint256_t(rhs); |
|||
return *this; |
|||
} |
|||
|
|||
uint256_t operator/=(uint256_t rhs){ |
|||
*this = *this / rhs; |
|||
return *this; |
|||
} |
|||
|
|||
template <typename T> uint256_t operator%(T rhs){ |
|||
return *this % uint256_t(rhs); |
|||
} |
|||
|
|||
uint256_t operator%(uint256_t rhs){ |
|||
return *this - (rhs * (*this / rhs)); |
|||
} |
|||
|
|||
template <typename T> uint256_t operator%=(T rhs){ |
|||
*this = *this % uint256_t(rhs); |
|||
return *this; |
|||
} |
|||
|
|||
uint256_t operator%=(uint256_t rhs){ |
|||
*this = *this % rhs; |
|||
return *this; |
|||
} |
|||
|
|||
// Increment Operators
|
|||
uint256_t operator++(){ |
|||
*this += 1; |
|||
return *this; |
|||
} |
|||
|
|||
uint256_t operator++(int){ |
|||
uint256_t temp(*this); |
|||
++*this; |
|||
return temp; |
|||
} |
|||
|
|||
// Decrement Operators
|
|||
uint256_t operator--(){ |
|||
*this -= 1; |
|||
return *this; |
|||
} |
|||
|
|||
uint256_t operator--(int){ |
|||
uint256_t temp(*this); |
|||
--*this; |
|||
return temp; |
|||
} |
|||
|
|||
// get private values
|
|||
uint128_t upper(){ |
|||
return UPPER; |
|||
} |
|||
|
|||
uint128_t lower(){ |
|||
return LOWER; |
|||
} |
|||
}; |
|||
// lhs type T as first arguemnt
|
|||
|
|||
// Bitwise Operators
|
|||
template <typename T> T operator&(T lhs, uint256_t rhs){ |
|||
T out = lhs & (T) rhs.lower(); |
|||
return out; |
|||
} |
|||
|
|||
template <typename T> T operator|(T lhs, uint256_t rhs){ |
|||
T out = lhs | (T) rhs.lower(); |
|||
return out; |
|||
} |
|||
|
|||
template <typename T> T operator^(T lhs, uint256_t rhs){ |
|||
T out = lhs ^ (T) rhs.lower(); |
|||
return out; |
|||
} |
|||
|
|||
template <typename T> T operator&=(T & lhs, uint256_t rhs){ |
|||
lhs &= (T) rhs.lower(); |
|||
return lhs; |
|||
} |
|||
|
|||
template <typename T> T operator|=(T & lhs, uint256_t rhs){ |
|||
lhs |= (T) rhs.lower(); |
|||
return lhs; |
|||
} |
|||
|
|||
template <typename T> T operator^=(T & lhs, uint256_t rhs){ |
|||
lhs ^= (T) rhs.lower(); |
|||
return lhs; |
|||
} |
|||
|
|||
// Comparison Operators
|
|||
template <typename T> bool operator==(T lhs, uint256_t rhs){ |
|||
return (!rhs.upper() && (uint128_t) lhs == rhs.lower()); |
|||
} |
|||
|
|||
template <typename T> bool operator!=(T lhs, uint256_t rhs){ |
|||
return (rhs.upper() | ((uint128_t) lhs != rhs.lower())); |
|||
} |
|||
|
|||
template <typename T> bool operator>(T lhs, uint256_t rhs){ |
|||
if (rhs.upper()) |
|||
return false; |
|||
return ((uint128_t) lhs > rhs.lower()); |
|||
} |
|||
|
|||
template <typename T> bool operator<(T lhs, uint256_t rhs){ |
|||
if (rhs.upper()) |
|||
return true; |
|||
return ((uint128_t) lhs < rhs.lower()); |
|||
} |
|||
|
|||
template <typename T> bool operator>=(T lhs, uint256_t rhs){ |
|||
if (rhs.upper()) |
|||
return false; |
|||
return ((uint128_t) lhs >= rhs.lower()); |
|||
} |
|||
|
|||
template <typename T> bool operator<=(T lhs, uint256_t rhs){ |
|||
if (rhs.upper()) |
|||
return true; |
|||
return ((uint128_t) lhs <= rhs.lower()); |
|||
} |
|||
|
|||
// Arithmetic Operators
|
|||
template <typename T> T operator+(T lhs, uint256_t rhs){ |
|||
return (T) (rhs + lhs); |
|||
} |
|||
|
|||
template <typename T> T & operator+=(T & lhs, uint256_t rhs){ |
|||
lhs = (T) (rhs + lhs); |
|||
return lhs; |
|||
} |
|||
|
|||
template <typename T> T operator-(T lhs, uint256_t rhs){ |
|||
return (T) (rhs - lhs); |
|||
} |
|||
|
|||
template <typename T> T & operator-=(T & lhs, uint256_t rhs){ |
|||
lhs = (T) (rhs - lhs); |
|||
return lhs; |
|||
} |
|||
|
|||
template <typename T> T operator*(T lhs, uint256_t rhs){ |
|||
return lhs * rhs.lower(); |
|||
} |
|||
|
|||
template <typename T> T & operator*=(T & lhs, uint256_t rhs){ |
|||
lhs = (T) (rhs.lower() * lhs); |
|||
return lhs; |
|||
} |
|||
|
|||
template <typename T> T operator/(T lhs, uint256_t rhs){ |
|||
return (T) (uint256_t(lhs) / rhs); |
|||
} |
|||
|
|||
template <typename T> T & operator/=(T & lhs, uint256_t rhs){ |
|||
lhs = (T) (uint256_t(lhs) / rhs); |
|||
return lhs; |
|||
} |
|||
|
|||
template <typename T> T operator%(T lhs, uint256_t rhs){ |
|||
return (T) (uint256_t(lhs) % rhs); |
|||
} |
|||
|
|||
template <typename T> T & operator%=(T & lhs, uint256_t rhs){ |
|||
lhs = (T) (uint256_t(lhs) % rhs); |
|||
return lhs; |
|||
} |
|||
|
|||
// IO Operator
|
|||
inline std::ostream & operator<<(std::ostream & stream, uint256_t rhs){ |
|||
std::string out = ""; |
|||
if (rhs == 0) |
|||
out = "0"; |
|||
else { |
|||
int div; |
|||
if (stream.flags() & stream.oct) |
|||
div = 8; |
|||
if (stream.flags() & stream.dec) |
|||
div = 10; |
|||
if (stream.flags() & stream.hex) |
|||
div = 16; |
|||
while (rhs > 0){ |
|||
out = "0123456789abcdef"[size_t(rhs % div)] + out; |
|||
rhs /= div; |
|||
} |
|||
} |
|||
stream << out; |
|||
return stream; |
|||
} |
Loading…
Reference in new issue