Skip to content

Commit 2f1f453

Browse files
HowardHinnantintelliot
authored andcommitted
Optimize uint128_t division by 10 within Number.cpp
* Optimization includes computing remainder from division. * Used only within Number::operator*=.
1 parent 6eaaa7b commit 2f1f453

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

src/ripple/basics/impl/IOUAmount.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ IOUAmount::normalize()
5353

5454
if (*stNumberSwitchover)
5555
{
56-
Number v{mantissa_, exponent_};
56+
const Number v{mantissa_, exponent_};
5757
mantissa_ = v.mantissa();
5858
exponent_ = v.exponent();
5959
if (exponent_ > maxExponent)

src/ripple/basics/impl/Number.cpp

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
//==============================================================================
1919

2020
#include <ripple/basics/Number.h>
21+
#include <boost/predef.h>
2122
#include <algorithm>
2223
#include <cassert>
2324
#include <numeric>
@@ -335,6 +336,34 @@ Number::operator+=(Number const& y)
335336
return *this;
336337
}
337338

339+
// Optimization equivalent to:
340+
// auto r = static_cast<unsigned>(u % 10);
341+
// u /= 10;
342+
// return r;
343+
// Derived from Hacker's Delight Second Edition Chapter 10
344+
// by Henry S. Warren, Jr.
345+
static inline unsigned
346+
divu10(uint128_t& u)
347+
{
348+
// q = u * 0.75
349+
auto q = (u >> 1) + (u >> 2);
350+
// iterate towards q = u * 0.8
351+
q += q >> 4;
352+
q += q >> 8;
353+
q += q >> 16;
354+
q += q >> 32;
355+
q += q >> 64;
356+
// q /= 8 approximately == u / 10
357+
q >>= 3;
358+
// r = u - q * 10 approximately == u % 10
359+
auto r = static_cast<unsigned>(u - ((q << 3) + (q << 1)));
360+
// correction c is 1 if r >= 10 else 0
361+
auto c = (r + 6) >> 4;
362+
u = q + c;
363+
r -= c * 10;
364+
return r;
365+
}
366+
338367
Number&
339368
Number::operator*=(Number const& y)
340369
{
@@ -370,8 +399,10 @@ Number::operator*=(Number const& y)
370399
g.set_negative();
371400
while (zm > maxMantissa)
372401
{
373-
g.push(static_cast<unsigned>(zm % 10));
374-
zm /= 10;
402+
// The following is optimization for:
403+
// g.push(static_cast<unsigned>(zm % 10));
404+
// zm /= 10;
405+
g.push(divu10(zm));
375406
++ze;
376407
}
377408
xm = static_cast<rep>(zm);

0 commit comments

Comments
 (0)