Page MenuHomePhabricator

Add lerp function to cmath (P0811R3)
Needs RevisionPublic

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

Details

Summary

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

Event Timeline

zoecarver created this revision.Sat, Apr 6, 5:39 PM
cpplearner added a subscriber: cpplearner.EditedSun, Apr 14, 10:21 PM

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."

mclow.lists requested changes to this revision.Mon, Apr 15, 4:33 AM

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)));

This revision now requires changes to proceed.Mon, Apr 15, 4:33 AM

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.

@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?