Skip to content

Commit

Permalink
Optimize __str_base10() using bitwise operations
Browse files Browse the repository at this point in the history
Replace the loop-based method for converting integers to base-10 with a
more efficient approach using bitwise operations. The new method
simulates division and modulus operations by 10 without using
multiplication, division, or modulus instructions, leading to improved
performance.

This optimization reduces the number of branches compared to the
original loop-based approach, resulting in fewer conditional checks and
a more streamlined execution path.

Experimental results demonstrate significant performance improvements
with the new method. Timing data, collected by calling __str_base10()
100,000,000 times in a loop across various ranges, shows the following
reductions in execution time:

| Range           | Old    | New    |
|-----------------|--------|--------|
| [0, 10)         | 0.473s | 0.293s |
| [0, 100)        | 0.619s | 0.434s |
| [0, 1000)       | 0.818s | 0.646s |
| [0, 10000)      | 1.715s | 0.902s |
| [0, 100000)     | 2.166s | 1.169s |
| [0, 1000000)    | 2.239s | 1.453s |
| [0, 10000000)   | 2.359s | 1.773s |
| [0, 100000000)  | 2.463s | 2.122s |

Link: http://web.archive.org/web/20180517023231/http://www.hackersdelight.org/divcMore.pdf
  • Loading branch information
visitorckw committed Aug 9, 2024
1 parent 13b828d commit bc25eff
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 41 deletions.
55 changes: 16 additions & 39 deletions lib/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ char *memcpy(char *dest, char *src, int count)
void __str_base10(char *pb, int val)
{
int neg = 0;
int q, r, t;
int i = INT_BUF_LEN - 1;

if (val == -2147483648) {
strncpy(pb + INT_BUF_LEN - 11, "-2147483648", 11);
Expand All @@ -127,45 +129,20 @@ void __str_base10(char *pb, int val)
val = -val;
}

while (val >= 1000000000) {
val -= 1000000000;
pb[INT_BUF_LEN - 10]++;
}
while (val >= 100000000) {
val -= 100000000;
pb[INT_BUF_LEN - 9]++;
}
while (val >= 10000000) {
val -= 10000000;
pb[INT_BUF_LEN - 8]++;
}
while (val >= 1000000) {
val -= 1000000;
pb[INT_BUF_LEN - 7]++;
}
while (val >= 100000) {
val -= 100000;
pb[INT_BUF_LEN - 6]++;
}
while (val >= 10000) {
val -= 10000;
pb[INT_BUF_LEN - 5]++;
}
while (val >= 1000) {
val -= 1000;
pb[INT_BUF_LEN - 4]++;
}
while (val >= 100) {
val -= 100;
pb[INT_BUF_LEN - 3]++;
}
while (val >= 10) {
val -= 10;
pb[INT_BUF_LEN - 2]++;
}
while (val >= 1) {
val -= 1;
pb[INT_BUF_LEN - 1]++;
while (val) {
q = (val >> 1) + (val >> 2);
q += (q >> 4);
q += (q >> 8);
q += (q >> 16);
q = q >> 3;
r = val - (((q << 2) + q) << 1);
t = ((r + 6) >> 4);
q += t;
r = r - (((t << 2) + t) << 1);

pb[i] += r;
val = q;
i--;
}

if (neg == 1) {
Expand Down
2 changes: 1 addition & 1 deletion tests/snapshots/fib.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/snapshots/hello.json

Large diffs are not rendered by default.

0 comments on commit bc25eff

Please sign in to comment.