Thanks for benchmarking. It was not intended to be a racer...
There are probably too many sequence points and too few common
subexpressions to give the compiler enough freedom to optimise.
There are other cases where this "computed enumeration" method can save
you some headaches. (e.g. 2D range-compare) It is relatively easy to
build and test, even if the conditions get very complex. The cases where
you know beforehand that you won't get it right the first time.
Gave me an idea:
int median3c(int a, int b, int c)
{
e_type elist[7] = {a,c,a,b,b,a,c};
return elist[(a > b) + ((b > c) << 1) + ((c > a) << 2)];
}
I am benching it now.
I guess that the 7 assignments filling the array will be expensive but
a benchmark may prove revealing.
The array idea was worse.
typedef int e_type;
e_type median3(e_type a, e_type b, e_type c)
{
return (a < b) ? ((b < c) ? b : ((a < c) ? c : a)) : ((a < c) ?
a : ((b < c) ? c : b));
}
e_type median3a(e_type a, e_type b, e_type c)
{
if (a < b) {
if (b < c)
return b; /* a b c */
if (c < a)
return a; /* c a b */
return c; /* a c b */
} else {
if (a < c)
return a; /* b a c */
if (c < b)
return b; /* c b a */
return c; /* b c a */
}
}
e_type median3b(e_type a, e_type b, e_type c)
{
switch ((a > b) + ((b > c) << 1) + ((c > a) << 2)) {
case 0:
return a;
case 1:
return c;
case 2:
return a;
case 3:
return b;
case 4:
return b;
case 5:
return a;
case 6:
default:
return c;
}
}
int median3c(int a, int b, int c)
{
e_type elist[7] = {a, c, a, b, b, a, c};
return elist[(a > b) + ((b > c) << 1) + ((c > a) << 2)];
}
#ifdef UNIT_TEST
#include <stdio.h>
int main(void)
{
e_type i,
j,
k,
m,
m2,
m3,
m4;
for (i = 0; i < 3000; i++)
for (j = 0; j < 3000; j++)
for (k = 0; k < 3000; k++) {
m = median3(i, j, k);
m2 = median3a(i, j, k);
m3 = median3b(i, j, k);
m4 = median3c(i, j, k);
#ifdef SHOW_RESULTS
printf("median of %d %d %d is %d\n", i, j, k, m3);
#endif
if (m4 != m)
printf("Disagreement (4) of %d verses %d\n", m3,
m);
if (m3 != m)
printf("Disagreement (3) of %d verses %d\n", m3,
m);
if (m2 != m)
printf("Disagreement (2) of %d verses %d\n", m2,
m);
}
return 0;
}
#endif
/*
Profile results were:
Function Name,Exclusive Samples,Exclusive Samples %,
"median3c","51,810",38.73,
"median3b","36,892",27.58,
"main","22,829",17.07,
"median3a","11,904",8.90,
"median3","10,320",7.72,
*/