So I was recently writing some code for my robotics class, and I wrote this code:

/*
alpha:    repulsion coefficient
gamma:    attraction coefficient
x0x, x0y: position of robot 0
xjx, xjy: position of robot j
dSafe:    safe distance
dFar:     "too far" distance
*/
Vector2 getFollowerAttraction(double alpha, double gamma,
double x0x, double x0y, double xjx, double xjy, double r0, double rj,
double dSafe, double dFar) {
// Create the return struct
Vector2 fa;
// Calculate the distance between the center of robot j to 0
double sx = x0x - xjx;
double sy = x0y - xjy;
double sm = sqrt(sx*sx + sy*sy);
// Subtract the radii of the robots
double d = sm - (r0 + rj);
// Calculate the vector conversion factor
double ka;
if (d < dSafe) {
ka = -alpha / (d*d * sm);
} else if (d < dFar) {
fa.x = 0;
fa.y = 0;
return fa;
} else {
ka = gamma * d*d / sm;
}
// Calculate the vector of the force
fa.x = ka * sx;
fa.y = ka * sy;
return fa;
}

Vector2 getFollowerAttraction() {
Pose &x0 = pose;
Pose &xj = pose[ID];
return getFollowerAttraction(REPULSION_CONSTANT_ALPHA,
ATTRACTION_CONSTANT_GAMMA, x0.x, x0.y, xj.x, xj.y, ROBOT_RADIUS_M,
}

I figured that having the option to override the constants if necessary by calling the first form was a nice thing to have. But I was concerned that adding this ability would cost me performance. Putting 640 bits of arguments on the stack seemed a bit overkill if they weren't needed. So I decided to do a bit of an experiment, and I am very pleased with the results. I wrote a simple C++ file called test.cpp:

const double A = 0;
const double B = 1;
const double C = 2;
const double D = 3;
const double E = 4;
const double F = 5;
const double G = 6;
const double H = 7;
const double I = 8;
const double J = 9;

double add(double a, double b, double c, double d, double e, double f,
double g, double h, double i, double j) {
return a + b + c + d + e + f + g + h + i + j;
}

return add(A, B, C, D, E, F, G, H, I, J);
}

int main() {
}

I tested it:

0 ✓ ntd5@ntd5-mbpro ~
% g++ test.cpp -o test -O2
0 ✓ ntd5@ntd5-mbpro ~
% ./test
45 ✗ ntd5@ntd5-mbpro ~
% g++ test.cpp -S -o test.s -O2

And this was what I got for the assembly (test.s):

.file   "test.cpp"
.text
.p2align 4,,15
.LFB0:
.cfi_startproc
ret
.cfi_endproc
.LFE0:
.p2align 4,,15
.LFB1:
.cfi_startproc
movsd   .LC0(%rip), %xmm0
ret
.cfi_endproc
.LFE1:
.section    .text.startup,"ax",@progbits
.p2align 4,,15
.globl  main
.type   main, @function
main:
.LFB2:
.cfi_startproc
movl    \$45, %eax
ret
.cfi_endproc
.LFE2:
.size   main, .-main
.section    .rodata.cst8,"aM",@progbits,8
.align 8
.LC0:
.long   0
.long   1078362112
.ident  "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4"
.section    .note.GNU-stack,"",@progbits

As you can see below _Z3addv, the constants got applied into the function. One can imagine that you would get similar optimization in my robotics code. Yay!