I want to perform a simple linear interpolation between $A$ and $B$ (which are binary floating-point values) using floating-point math with IEEE-754 round-to-nearest-or-even rounding rules, as accurately as possible. Please note that speed is not a big concern here.
I know of two basic approaches. I'll use the symbols $\oplus, \ominus, \otimes, \oslash$ following Knuth [1], to mean floating-point addition, subtraction, product and division, respectively (actually I don't use division, but I've listed it for completeness).
(1) $\quad f(t) = A\,\oplus\,(B\ominus A)\otimes t$
(2) $\quad f(t) = A\otimes(1\ominus t)\,\oplus \,B\otimes t$
Each method has its pros and cons. Method (1) is clearly monotonic, which is a very interesting property, while it is not obvious at all to me that that holds for method (2), and I suspect it may not be the case. On the other hand, method (2) has the advantage that when $t = 1$ the result is exactly $B$, not an approximation, and that is also a desirable property (and exactly $A$ when $t = 0$, but method (1) does that too). That follows from the properties listed in [2], in particular:
$u\oplus v = v\oplus u$
$u\ominus v = u\oplus -v$
$u\oplus v = 0$ if and only if $v = -u$
$u\oplus 0 = u$
$u\otimes 1 = u$
$u\otimes v = 0$ if and only if $u = 0$ or $v = 0$
In [3] Knuth also discusses this case:
$u' = (u\oplus v)\ominus v$
which implicitly means that $u'$ may or may not be equal to $u$. Replacing $u$ with $B$ and $v$ with $-A$ and using the above rules, it follows that it's not granted that $A\oplus(B\ominus A) = B$, meaning that method (1) does not always produce $B$ when $t = 1$.
So, here come my questions:
- Is method (2) guaranteed to be monotonic?
- If not, is there a better method that is accurate, monotonic and yields $A$ when $t = 0$ and $B$ when $t = 1$?
If not (or you don't know), does method (1) when $t = 1$ always overshoot (that is, $A\oplus(B\ominus A)=A+(B-A)\cdot t$ for some $t \geq 1$)? Always undershoot (ditto for some $t \leq 1$)? Or sometimes overshoot and sometimes undershoot?
I assume that if method (1) always undershoots, I can make a special case when $t = 1$ to obtain the desired property of being exactly equal to $B$ when $t = 1$, but if it always overshoots, then I can't. That's the reason for question 3.
EDIT: I've found that the answer to question 3 is that it sometimes overshoots and sometimes undershoots. For example, in double precision:
-0x1.cae164da859c9p-1 + (0x1.eb4bf7b6b2d6ep-1 - (-0x1.cae164da859c9p-1))
results in 0x1.eb4bf7b6b2d6fp-1, which is 1 ulp greater than the original, while
-0x1.be03888ad585cp-1 + (0x1.0d9940702d541p-1 - (-0x1.be03888ad585cp-1))
results in 0x1.0d9940702d540p-1, which is 1 ulp less than the original. On the other hand, the method that I planned (special casing $t=1$) won't fly, because I've found it can be the case where $t < 1$ and $A\oplus(B\ominus A)\otimes t > B$, for example:
t = 0x1.fffffffffffffp-1
A = 0x1.afb669777cbfdp+2
B = 0x1.bd7b786d2fd28p+1
$A \oplus (B \ominus A)\otimes t =\,$ 0x1.bd7b786d2fd29p+1
which means that if method (1) is to be used, the only strategy that may work is clamping.
Update: As noted by Davis Herring in a comment and later checked by me, special casing t=1 actually works.
References
[1] D.E.Knuth, The Art of Computer Programming, vol. 2: Seminumerical algorithms, third edition, p. 215
[2] Op. cit. pp. 230-231
[3] Op. cit. p.235 eq.(41)
tas volatile fixed it. I've updated the program. – Pedro Gimeno Aug 30 '14 at 20:51fma(t, b, fma(-t, a, a))– njuffa May 21 '16 at 21:45A=0x1.FC5A90p+13, B=0x1.4BB814p+5, t=0x1.8B212Ap-17results in0x1.FC5908p+13, and same A&B with the next t which is0x1.8B212Cp-17gives0x1.FC590Ap+13which is greater than the previous value, but it should be descending because A > B. Perhaps an alternative is to calculate the error in B-A and add that later, something like: fma(t, err(B-A), fma(t, B-A, A)). I'll test. – Pedro Gimeno May 22 '16 at 21:29A=0x1.B1B374p+41, B=-0x1.A6404Ep+43, t=1.0yields-0x1.A64050p+43. Turning around err and B-A doesn't help, more like the contrary. For reference,err(u+v) = fabs(u)>=fabs(v) ? u-(u+v)+v : v-(u+v)+u(Knuth, theorem 4.2.2-C). Here, u=B, v=−A. – Pedro Gimeno May 23 '16 at 22:41a=0x1.fc5a90p+13 b=0x1.4bb814p+5 t=0x1.8b212ap-17 t2=0x1.8b212cp-17 res=0x1.fc590ap+13 res2=0x1.fc590ap+13– njuffa May 25 '16 at 16:08b-ais exact ort*(b-a)is rounded in the correct direction from (the exact) b-a. In particular, note that for any 0<f<1 and (w.l.o.g.) x>00<x*f<xunless x is denormal. – Davis Herring Dec 18 '19 at 15:08lerpthat computes this linear interpolation operation. – Zsbán Ambrus Mar 27 '24 at 13:21