Finding and using the time derivative of a bezier curve

Calculating the bezier contour uses the formula:

bezier(t) = A*(1-t)^3 + B*3*(1-t)^2*t + C*3*(1-t)*t^2 + D*t^3

Even when optimized it takes 10 multiplications and 4 additions/subtraction:

let t1 = 1-t;
let x = t1*t1*(A*t1 + B*3*t) + t*t*(C*3*t1 + D*t)

In an attempt to make it even more efficient, an alternative approach is to convert the formula into a time incremental function and loop unroll all the constants. Given the time increment dt, the change to x is:

dx = bezier(t+dt)-bezier(t)

As A,B,C,D and dt are all loop unrollable constants, the equation can be rewritten to the form that requires 3 multiplications and 2 additions.

dx = COEF2*t*t + COEF1*t + COEF0

The rest of this section determines the values of COEF2, COEF1, COEF0.

Step 1: Expand bezier(t+dt)-bezier(t)

A*(1-t-dt)^3 + B*3*(1-t-dt)^2*(t+dt) + C*3*(1-t-dt)*(t+dt)^2 + D*(t+dt)^3 - A*(1-t)^3 - B*3*(1-t)^2*t - C*3*(1-t)*t^2 - D*t^3

Step 2: Expand the powers

A*(1-t-dt)*(1-t-dt)*(1-t-dt) + B*3*(1-t-dt)*(1-t-dt)*(t+dt) + C*3*(1-t-dt)*(t+dt)*(t+dt) + D*(t+dt)*(t+dt)*(t+dt) - A*(1-t)*(1-t)*(1-t) - B*3*(1-t)*(1-t)*t - C*3*(1-t)*t*t - D*t*t*t

Step 3: Solve parentheses (in smaller steps)

A*(1-t-dt)*(1-t-dt)*(1-t-dt) =  A*( t*t*t*(-1) + t*t*(3-3*dt) + t*(-3+6*dt-3*dt*dt) + (1 -3*dt +3*dt*dt -dt*dt*dt) )
B*3*(1-t-dt)*(1-t-dt)*(t+dt) =  B*( t*t*t*(3) + t*t*(-6 +9*dt) + t*(3 -12*dt +9*dt*dt) + (3*dt -6*dt*dt +3*dt*dt*dt) )
C*3*(1-t-dt)*(t+dt)*(t+dt)   =  C*( t*t*t*(-3) + t*t*(+3 -9*dt) + t*(6*dt -9*dt*dt) + (3*dt*dt -3*dt*dt*dt) )
D*(t+dt)*(t+dt)*(t+dt)       =  D*( t*t*t*(1) + t*t*(3*dt) + t*(3*dt*dt) + (dt*dt*dt) )
-A*(1-t)*(1-t)*(1-t)         =  A*( t*t*t*(1) + t*t*(-3) + t*(3) + (-1) )
-B*3*(1-t)*(1-t)*t           =  B*( t*t*t*(-3) + t*t*(6) + t*(-3) )
-C*3*(1-t)*t*t               =  C*( t*t*t*(3) + t*t*(-3) )
-D*t*t*t                     =  D*( t*t*t*(1) )

Step 4: Merge terms

A*( t*t*(-3*dt) + t*(6*dt-3*dt*dt) + (-3*dt +3*dt*dt -dt*dt*dt) )
B*( t*t*(+9*dt) + t*(-12*dt +9*dt*dt) + (3*dt -6*dt*dt +3*dt*dt*dt) )
C*( t*t*(-9*dt) + t*(6*dt -9*dt*dt) + (3*dt*dt -3*dt*dt*dt) )
D*( t*t*(3*dt) + t*(3*dt*dt) + (dt*dt*dt) )

Step 5: Regroup towards t

+t*t*(A*(-3*dt) +B*(9*dt) +C*(-9*dt) +D*(3*dt))
+t*(A*(6*dt-3*dt*dt) +B*(-12*dt +9*dt*dt) +C*(6*dt -9*dt*dt) +D*(3*dt*dt))
+(A*(-3*dt +3*dt*dt -dt*dt*dt) +B*(3*dt -6*dt*dt +3*dt*dt*dt) +C*(3*dt*dt -3*dt*dt*dt) +D*(dt*dt*dt))

Step 6: Resulting coefficients

COEF2 = A*(-3*dt) +B*(9*dt) +C*(-9*dt) +D*(3*dt)
COEF1 = A*(6*dt-3*dt*dt) +B*(-12*dt +9*dt*dt) +C*(6*dt -9*dt*dt) +D*(3*dt*dt)
COEF0 = A*(-3*dt +3*dt*dt -dt*dt*dt) +B*(3*dt -6*dt*dt +3*dt*dt*dt) +C*(3*dt*dt -3*dt*dt*dt) +D*(dt*dt*dt)

Determining coefficients requires 90 multiplications, 24 additions and 10 subtractions.

Sample code for verification:

let A = .3;
let B = .5;
let C = .2;
let D = .7;
let dt = 1/10000;

let COEF2 = A*(-3*dt) +B*(9*dt) +C*(-9*dt) +D*(3*dt);
let COEF1 = A*(6*dt-3*dt*dt) +B*(-12*dt +9*dt*dt) +C*(6*dt -9*dt*dt) +D*(3*dt*dt);
let COEF0 = A*(-3*dt +3*dt*dt -dt*dt*dt) +B*(3*dt -6*dt*dt +3*dt*dt*dt) +C*(3*dt*dt -3*dt*dt*dt) +D*(dt*dt*dt);

for (let t=0,x1=A; t<1; t+=dt) {

        // calculate as absolute
        let x2 = A*(1-t)*(1-t)*(1-t) + B*3*(1-t)*(1-t)*t + C*3*(1-t)*t*t + D*t*t*t;

        // display difference
	if (Math.abs(x1-x2) > 1e-13)
	        console.log(x2-x1);

        // calculate as relative
        x1 += COEF2*t*t + COEF1*t + COEF0;
}