Quiero realizar una interpolación lineal simple entre $A$ y $B$ (que son valores binarios de punto flotante) utilizando matemáticas de punto flotante con reglas de redondeo IEEE-754 al más cercano o al más cercano par, con la mayor precisión posible. Tenga en cuenta que la velocidad no es una gran preocupación aquí.
Conozco dos enfoques básicos. Usaré los símbolos $\oplus, \ominus, \otimes, \oslash$ siguiendo a Knuth [1], para significar suma, resta, producto y división de punto flotante, respectivamente (en realidad no uso la división, pero la he enumerado por completitud).
(1) $\quad f(t) = A\,\oplus\,(B\ominus A)\otimes t$
(2) $\quad f(t) = A\otimes(1\ominus t)\,\oplus \,B\otimes t$
Cada método tiene sus pros y sus contras. El método (1) es claramente monótono, lo cual es una propiedad muy interesante, mientras que no me resulta obvio en absoluto que eso sea cierto para el método (2), y sospecho que puede que no sea el caso. Por otro lado, el método (2) tiene la ventaja de que cuando $t = 1$ el resultado es exactamente $B$, no una aproximación, y esa es también una propiedad deseable (y exactamente $A$ cuando $t = 0$, pero el método (1) también hace eso). Eso se sigue de las propiedades enumeradas en [2], en particular:
$u\oplus v = v\oplus u$
$u\ominus v = u\oplus -v$
$u\oplus v = 0$ si y solo si $v = -u$
$u\oplus 0 = u$
$u\otimes 1 = u$
$u\otimes v = 0$ si y solo si $u = 0$ o $v = 0$
En [3] Knuth también discute este caso:
$u' = (u\oplus v)\ominus v$
lo que implica que $u'$ puede o no ser igual a $u$. Reemplazando $u$ con $B$ y $v$ con $-A$ y usando las reglas anteriores, se sigue que no está garantizado que $A\oplus(B\ominus A) = B$, lo que significa que el método (1) no siempre produce $B$ cuando $t = 1$.
Entonces, aquí vienen mis preguntas:
- ¿Está garantizado que el método (2) es monótono?
- Si no, ¿hay un método mejor que sea preciso, monótono y produzca $A$ cuando $t = 0$ y $B$ cuando $t = 1$?
Si no (o no lo sabe), ¿el método (1) cuando $t = 1$ siempre se excede (es decir, $A\oplus(B\ominus A)=A+(B-A)\cdot t$ para algún $t \geq 1$)? ¿Siempre se queda corto (idem para algún $t \leq 1$)? ¿O a veces se excede y a veces no llega?
Supongo que si el método (1) siempre se queda corto, puedo hacer un caso especial cuando $t = 1$ para obtener la propiedad deseada de ser exactamente igual a $B$ cuando $t = 1$, pero si siempre se excede, entonces no puedo. Esa es la razón de la pregunta 3.
EDITAR: He encontrado que la respuesta a la pregunta 3 es que a veces se excede y a veces no llega. Por ejemplo, en doble precisión:
-0x1.cae164da859c9p-1 + (0x1.eb4bf7b6b2d6ep-1 - (-0x1.cae164da859c9p-1))
da como resultado 0x1.eb4bf7b6b2d6fp-1
, que es 1 ulp mayor que el original, mientras que
-0x1.be03888ad585cp-1 + (0x1.0d9940702d541p-1 - (-0x1.be03888ad585cp-1))
da como resultado 0x1.0d9940702d540p-1
, que es 1 ulp menor que el original. Por otro lado, el método que planeé (caso especial de $t=1$) no funcionará, porque he encontrado que puede ser el caso donde $t < 1$ y $A\oplus(B\ominus A)\otimes t > B$, por ejemplo:
~~
t = 0x1.fffffffffffffp-1
A = 0x1.afb669777cbfdp+2
B = 0x1.bd7b786d2fd28p+1
$A \oplus (B \ominus A)\otimes t =\,$ 0x1.bd7b786d2fd29p+1
~~
lo que significa que si se va a utilizar el método (1), la única estrategia que puede funcionar es recortar.
Actualización: Como señaló Davis Herring en un comentario y verificado posteriormente por mí, hacer un caso especial de t=1 funciona en realidad.
Referencias
[1] D.E.Knuth, The Art of Computer Programming, vol. 2: Seminumerical algorithms, tercera edición, pág. 215
[2] Ibíd. pp. 230-231
[3] Ibíd. p.235 ec.(41)