A Raiz Quadrada Inversa Rápida do Quake III parece usar um truque de ponto flutuante. Pelo que entendi, a representação de ponto flutuante pode ter algumas implementações diferentes.
Então, é possível implementar a Raiz quadrada inversa rápida em Javascript?
Isso retornaria o mesmo 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
fonte
fonte
Respostas:
O truque depende da reinterpretação dos bits de um número de ponto flutuante como um número inteiro e vice-versa, o que é possível no JavaScript usando o recurso Arrays digitados , para criar um buffer de bytes brutos com várias visualizações numéricas nele.
Aqui está uma conversão literal do código que você forneceu; observe que não é exatamente o mesmo, pois todas as operações aritméticas em JavaScript são ponto flutuante de 64 bits, não 32 bits; portanto, a entrada será necessariamente convertida. Além disso, como o código original, isso depende da plataforma, pois fornecerá resultados sem sentido se a arquitetura do processador usar uma ordem de bytes diferente; se você precisar fazer coisas assim, recomendo que seu aplicativo execute primeiro um caso de teste para determinar se números inteiros e flutuantes têm as representações de bytes que você espera.
Confirmei ao observar um gráfico que isso fornece resultados numéricos razoáveis. No entanto, não é óbvio que isso melhore o desempenho, pois estamos realizando mais operações JavaScript de alto nível. Eu executei benchmarks nos navegadores úteis e descobri que
Q_rsqrt(number)
leva de 50% a 80% do tempo gasto1/sqrt(number)
(Chrome, Firefox e Safari no macOS, em abril de 2018). Aqui está minha configuração completa de teste:fonte
In classic JavaScript, it is not possible to... reinterpreting the bits of a floating-point number as an integer
realmente? Isso foi há anos, então eu não lembro exatamente quais operações eu estava usando, mas uma vez escrevi um analisador de dados em JavaScript que converteria uma sequência de bytes em uma série de números inteiros de N bits (N foi definido no cabeçalho). Isso é bem parecido.