-
Notifications
You must be signed in to change notification settings - Fork 39
/
abs.c
114 lines (104 loc) · 2.13 KB
/
abs.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/* ex: set ts=2 et: */
/*
*
* ~/c$ gcc -O3 -lm -o abs abs.c
* ~/c$ ./abs
* 500000000 iterations:
* function seconds speedup
* stdlib abs 2.009 0%
* naive_abs 1.758 14%
* sneaky_abs 1.883 7%
* ~/c$
*
* good old naive C plus great optimization by GCC 4.1.1
* proves to be the fastest
*
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/time.h>
int naive_abs(int i)
{
if (i < 0)
i = -i;
return i;
}
int mask_abs(int a) {
int mask = (a >> (sizeof(int) * CHAR_BIT - 1));
return (a + mask) ^ mask;
}
int sun_abs(int i)
{
__asm__(
"movl %0, %%eax\n\t"
"cdq\n\t"
"xorl %%edx, %%eax\n\t"
"subl %%edx, %%eax\n\t"
: "=m"(i)
: "m"(i)
: "%eax","%edx"
);
return i;
}
int foo_abs(int i)
{
__asm__(
"movl %0, %%eax\n\t"
"xorl $0xFFFFFFFF, %%eax\n\t"
"incl %%eax\n\t"
: "=m"(i)
: "m"(i)
: "%eax"
);
return i;
}
void test(int (*f)(int))
{
assert(0 == f(0));
assert(0 == f(-0));
assert(1 == f(1));
printf("f(-1) -> 0x%08x, -1 == 0x%08x\n",
f(-1), -1);
assert(1 == f(-1));
assert(5 == f(-5));
assert(5 == f(5));
assert(0x7fffffff == f(-0x7fffffff));
}
#define N_TIMES 1 << 26
//#define N_TIMES 1000
static void speed(const char *name, int (*f)(int))
{
static double orig = 0;
struct timeval tv[2];
double d[2], secs;
int i;
printf("%30s ", name);
/* test for correctness ... */
test(f);
/* test speed */
i = -N_TIMES;
gettimeofday(tv, NULL);
do
f(i);
while (i++);
gettimeofday(tv + 1, NULL);
d[0] = (tv[0].tv_sec * 1000000) + tv[0].tv_usec;
d[1] = (tv[1].tv_sec * 1000000) + tv[1].tv_usec;
secs = (d[1] - d[0]) / 1000000;
if (0 == orig)
orig = secs;
printf("%7.3f %4.0f%%\n", secs, ((orig / secs) * 100) - 100);
}
int main(void)
{
printf("%u iterations:\n", N_TIMES);
printf("%30s %5s %s\n", "function", "seconds", "speedup");
speed("foo_abs", foo_abs);
//speed("sun_abs", sun_abs);
speed("mask_abs", mask_abs);
speed("stdlib abs", abs);
speed("naive_abs", naive_abs);
return 0;
}