Adds the `lerp` function as specified in P0811R3.

I don't think the special conditions are necessary, but if they are, I can add them (from the sample implementation).

Differential D60371

Add lerp function to cmath (P0811R3)

Authored by **zoecarver** on Apr 6 2019, 5:39 PM.

Details

- Reviewers
mclow.lists howard.hinnant

Adds the `lerp` function as specified in P0811R3.

I don't think the special conditions are necessary, but if they are, I can add them (from the sample implementation).

Diff Detail

Comment Actions

As mentioned in https://math.stackexchange.com/questions/907327/accurate-floating-point-linear-interpolation, given

double a = 4000; double b = a; double t = 0x1.b2f3db7800a39p-2;

`((1 - t) * a + t * b) != a`. This does not conform to the requirement "If isfinite(t) && a == b, then r == a."

Comment Actions

This is too simplistic.

I have a better implementation of this; but I need more tests for the denormalized cases.

Mine also fails for edge cases like this: `assert(std::isinf(std::lerp(T( 0), T( 1), inf)));`

Comment Actions

The paper suggests an implementation like this:

constexpr Float lerp(Float a, Float b, Float t) { // Exact, monotonic, bounded, determinate, and (for a=b=0) consistent: if(a<=0 && b>=0 || a>=0 && b<=0) return t*b + (1-t)*a; if(t==1) return b; // exact // Exact at t=0, monotonic except near t=1, // bounded, determinate, and consistent: const Float x = a + t*(b-a); return t>1 == b>a ? max(b,x) : min(b,x); // monotonic near t=1 }

I've tested this, and it works "pretty well", but not (I think) well enough.

Comment Actions

@cpplearner that link is very helpful. In the first answer, there is a suggested function which might work well (though I haven't had time to test it yet). It is similar to the suggested implementation. There is one case which this function does not work for, but we could add a case for that. In pseudocode:

if (t < 0.5) a + (b - a) * t else b - (b - a) * (1 - t)

Additionally, the link has a lot of good exceptions which we could add to our tests. How does this compare to what you have @mclow.lists? I am going to add some tests to this patch in the meantime, mind sharing what you have so far?