replaced 64-bit multiplication in difficulty.cpp with a portable version

This commit is contained in:
Riccardo Spagni 2015-01-27 14:04:23 +02:00
parent 9b3673a54c
commit 709bbc52c4
No known key found for this signature in database
GPG key ID: 55432DF31CCD4FCD

View file

@ -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