S
Sean Kenwrick
I am writing a byte-code interpreter/emulator for a language that
exclusively uses strings for variables (i.e all variables are pushed onto
the stack as strings). Therefore for arithmetic operations I need to
convert the string to a 32 bit integer, carry out the arithmetic operation,
then convert it back to a string before pushing it back onto the stack.
This can happen millions of times per second so it is essential that I have
optimised (for speed) atol() and ltoa() functions.
Here is my attempt at ltoa()... (The __fastcall keyword is to tell my
compiler to pass arguments through registers and is used instead of inline
because it seems to be just as fast and this function gets called from
various modules ..).
static char * __fastcall myltoa(long n,char * s)
{
register long r, k;
register int flag = 0;
register int next;
next = 0;
if (n == 0) {
s[next++] = '0';
}
else {
if (n < 0) {
s[next++] = '-';
n = -n;
}
if(n < 100) goto label2;
if(n < 100000) goto label1;
k = 1000000000;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
k = 100000000;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
k = 10000000;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
k = 1000000;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
k = 100000;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
label1:
k = 10000;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
k = 1000;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
k = 100;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
label2:
k = 10;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
r=n;
s[next++] = '0' + r;
}
s[next] = '\0';
return(s);
}
The goto's are there because I recognised that the majority of numbers are
less than 100 (mainly return codes from functions) and those that are not
less than 100 tend to be less than 100,000 (this language is not usually
used for mathemetics). This did give me another 15-20% improvement in
speed on a tight loop going some arithmetic..
By the way, I have tried pre-calculating integer values for all strings
pushed onto the stack (by always appending the 4 byte integer value on the
stack at the end of the string, but it actually caused a slowdown since the
I have to do a atol() on every function return value or string concatenation
operation even if the value is not going to be used in an arithmetic or
comparison operation.
Any hints would be welcome...
Sean
exclusively uses strings for variables (i.e all variables are pushed onto
the stack as strings). Therefore for arithmetic operations I need to
convert the string to a 32 bit integer, carry out the arithmetic operation,
then convert it back to a string before pushing it back onto the stack.
This can happen millions of times per second so it is essential that I have
optimised (for speed) atol() and ltoa() functions.
Here is my attempt at ltoa()... (The __fastcall keyword is to tell my
compiler to pass arguments through registers and is used instead of inline
because it seems to be just as fast and this function gets called from
various modules ..).
static char * __fastcall myltoa(long n,char * s)
{
register long r, k;
register int flag = 0;
register int next;
next = 0;
if (n == 0) {
s[next++] = '0';
}
else {
if (n < 0) {
s[next++] = '-';
n = -n;
}
if(n < 100) goto label2;
if(n < 100000) goto label1;
k = 1000000000;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
k = 100000000;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
k = 10000000;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
k = 1000000;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
k = 100000;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
label1:
k = 10000;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
k = 1000;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
k = 100;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
label2:
k = 10;
r = n/k;
if(flag) s[next++] = '0' + r;
else if(r > 0){ s[next++] = '0' + r;flag = 1;}
n -= r * k;
r=n;
s[next++] = '0' + r;
}
s[next] = '\0';
return(s);
}
The goto's are there because I recognised that the majority of numbers are
less than 100 (mainly return codes from functions) and those that are not
less than 100 tend to be less than 100,000 (this language is not usually
used for mathemetics). This did give me another 15-20% improvement in
speed on a tight loop going some arithmetic..
By the way, I have tried pre-calculating integer values for all strings
pushed onto the stack (by always appending the 4 byte integer value on the
stack at the end of the string, but it actually caused a slowdown since the
I have to do a atol() on every function return value or string concatenation
operation even if the value is not going to be used in an arithmetic or
comparison operation.
Any hints would be welcome...
Sean