La raíz cuadrada inversa rápida de Quake III parece usar un truco de punto flotante. Según tengo entendido, la representación de punto flotante puede tener algunas implementaciones diferentes.
Entonces, ¿es posible implementar la raíz cuadrada inversa rápida en Javascript?
¿Devolvería el mismo resultado?
float Q_rsqrt(float number) {
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y;
i = 0x5f3759df - ( i >> 1 );
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) );
return y;
}
javascript
Atav32
fuente
fuente
Respuestas:
El truco depende de reinterpretar los bits de un número de coma flotante como un número entero y viceversa, lo cual es posible en JavaScript mediante el uso de Typed Arrays , para crear un búfer de bytes sin formato con múltiples vistas numéricas.
Aquí hay una conversión literal del código que le diste; tenga en cuenta que no es exactamente lo mismo, ya que todas las operaciones aritméticas en JavaScript son de coma flotante de 64 bits, no de 32 bits, por lo que la entrada necesariamente se convertirá. Además, al igual que el código original, esto depende de la plataforma, ya que dará resultados sin sentido si la arquitectura del procesador usa un orden de bytes diferente; si debe hacer cosas como esta, le recomiendo que su aplicación primero ejecute un caso de prueba para determinar que los enteros y flotantes tengan las representaciones de bytes que espera.
He confirmado mirando un gráfico que esto da resultados numéricos razonables. Sin embargo, no es obvio que esto mejorará el rendimiento, ya que estamos haciendo más operaciones de JavaScript de alto nivel. He ejecutado puntos de referencia en los navegadores que tengo a mano y descubrí que
Q_rsqrt(number)
lleva del 50% al 80% del tiempo que toma1/sqrt(number)
(Chrome, Firefox y Safari en macOS, a partir de abril de 2018). Aquí está mi configuración de prueba completa:fuente
In classic JavaScript, it is not possible to... reinterpreting the bits of a floating-point number as an integer
¿De Verdad? Fue hace años, así que no recuerdo exactamente qué operaciones estaba usando, pero una vez escribí un analizador de datos en JavaScript que convertiría una cadena de bytes en una serie de enteros de N bits (se definió N en el encabezado). Eso es muy similar.