Skip to content

Commit c56c590

Browse files
authored
Merge pull request #147 from visitorckw/optimize-str-base10
Optimize __str_base10()
2 parents 13b828d + 85f67c5 commit c56c590

File tree

3 files changed

+34
-49
lines changed

3 files changed

+34
-49
lines changed

lib/c.c

Lines changed: 32 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,25 @@ char *memcpy(char *dest, char *src, int count)
113113
return dest;
114114
}
115115

116-
/* set 10 digits (32bit) without div */
116+
/*
117+
* set 10 digits (32bit) without div
118+
*
119+
* This function converts a given integer value to its string representation
120+
* in base-10 without using division operations. The method involves calculating
121+
* the approximate quotient and remainder using bitwise operations, which are
122+
* then used to derive each digit of the result.
123+
*
124+
* The logic is based on an efficient method of dividing by constants, as
125+
* detailed in the reference link:
126+
* http://web.archive.org/web/20180517023231/http://www.hackersdelight.org/divcMore.pdf.
127+
* This approach avoids expensive division instructions by using a series of
128+
* bitwise shifts and additions to calculate the quotient and remainder.
129+
*/
117130
void __str_base10(char *pb, int val)
118131
{
119132
int neg = 0;
133+
int q, r, t;
134+
int i = INT_BUF_LEN - 1;
120135

121136
if (val == -2147483648) {
122137
strncpy(pb + INT_BUF_LEN - 11, "-2147483648", 11);
@@ -127,54 +142,24 @@ void __str_base10(char *pb, int val)
127142
val = -val;
128143
}
129144

130-
while (val >= 1000000000) {
131-
val -= 1000000000;
132-
pb[INT_BUF_LEN - 10]++;
133-
}
134-
while (val >= 100000000) {
135-
val -= 100000000;
136-
pb[INT_BUF_LEN - 9]++;
137-
}
138-
while (val >= 10000000) {
139-
val -= 10000000;
140-
pb[INT_BUF_LEN - 8]++;
141-
}
142-
while (val >= 1000000) {
143-
val -= 1000000;
144-
pb[INT_BUF_LEN - 7]++;
145-
}
146-
while (val >= 100000) {
147-
val -= 100000;
148-
pb[INT_BUF_LEN - 6]++;
149-
}
150-
while (val >= 10000) {
151-
val -= 10000;
152-
pb[INT_BUF_LEN - 5]++;
153-
}
154-
while (val >= 1000) {
155-
val -= 1000;
156-
pb[INT_BUF_LEN - 4]++;
157-
}
158-
while (val >= 100) {
159-
val -= 100;
160-
pb[INT_BUF_LEN - 3]++;
161-
}
162-
while (val >= 10) {
163-
val -= 10;
164-
pb[INT_BUF_LEN - 2]++;
165-
}
166-
while (val >= 1) {
167-
val -= 1;
168-
pb[INT_BUF_LEN - 1]++;
169-
}
145+
while (val) {
146+
q = (val >> 1) + (val >> 2);
147+
q += (q >> 4);
148+
q += (q >> 8);
149+
q += (q >> 16);
150+
q = q >> 3;
151+
r = val - (((q << 2) + q) << 1);
152+
t = ((r + 6) >> 4);
153+
q += t;
154+
r = r - (((t << 2) + t) << 1);
170155

171-
if (neg == 1) {
172-
int c = 0;
173-
while (pb[c] == '0')
174-
c++;
175-
if (c > 0)
176-
pb[c - 1] = '-';
156+
pb[i] += r;
157+
val = q;
158+
i--;
177159
}
160+
161+
if (neg == 1)
162+
pb[i] = '-';
178163
}
179164

180165
void __str_base8(char *pb, int val)

tests/snapshots/fib.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

tests/snapshots/hello.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)