diff options
author | Riccardo Spagni <ric@spagni.net> | 2015-01-27 14:04:23 +0200 |
---|---|---|
committer | Riccardo Spagni <ric@spagni.net> | 2015-01-27 14:06:33 +0200 |
commit | 497a514bd328400c8572041c1217ab2adac5e2c8 (patch) | |
tree | b7d147962e0f65bbe97c8ae9169a7151366df8e7 /src/cryptonote_core/difficulty.cpp | |
parent | Merge pull request #220 (diff) | |
download | monero-497a514bd328400c8572041c1217ab2adac5e2c8.tar.xz |
replaced 64-bit multiplication in difficulty.cpp with a portable version
Diffstat (limited to 'src/cryptonote_core/difficulty.cpp')
-rw-r--r-- | src/cryptonote_core/difficulty.cpp | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/src/cryptonote_core/difficulty.cpp b/src/cryptonote_core/difficulty.cpp index 106520440..6486d8124 100644 --- a/src/cryptonote_core/difficulty.cpp +++ b/src/cryptonote_core/difficulty.cpp @@ -56,10 +56,40 @@ namespace cryptonote { #else static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) { - typedef unsigned __int128 uint128_t; - uint128_t res = (uint128_t) a * (uint128_t) b; - low = (uint64_t) res; - high = (uint64_t) (res >> 64); + // __int128 isn't part of the standard, so the previous function wasn't portable. mul128() in Windows is fine, + // but this portable function should be used elsewhere. Credit for this function goes to latexi95. + + uint64_t aLow = a & 0xFFFFFFFF; + uint64_t aHigh = a >> 32; + uint64_t bLow = b & 0xFFFFFFFF; + uint64_t bHigh = b >> 32; + + uint64_t res = aLow * bLow; + uint64_t lowRes1 = res & 0xFFFFFFFF; + uint64_t carry = res >> 32; + + res = aHigh * bLow + carry; + uint64_t highResHigh1 = res >> 32; + uint64_t highResLow1 = res & 0xFFFFFFFF; + + res = aLow * bHigh; + uint64_t lowRes2 = res & 0xFFFFFFFF; + carry = res >> 32; + + res = aHigh * bHigh + carry; + uint64_t highResHigh2 = res >> 32; + uint64_t highResLow2 = res & 0xFFFFFFFF; + + //Addition + + uint64_t r = highResLow1 + lowRes2; + carry = r >> 32; + low = (r << 32) | lowRes1; + r = highResHigh1 + highResLow2 + carry; + uint64_t d3 = r & 0xFFFFFFFF; + carry = r >> 32; + r = highResHigh2 + carry; + high = d3 | (r << 32); } #endif |