Корень быстрого обратного квадрата из Quake III, похоже, использует трюк с плавающей точкой. Как я понимаю, представление с плавающей точкой может иметь несколько разных реализаций.
Так можно ли реализовать быстрый корень квадратного обратного в Javascript?
Вернет ли он тот же результат?
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
источник
источник
Ответы:
Хитрость заключается в том , чтобы заново интерпретировать биты числа с плавающей запятой как целое число и обратно, что возможно в JavaScript с помощью средства Typed Arrays для создания необработанного байтового буфера с несколькими числовыми представлениями.
Вот буквальное преобразование кода, который вы дали; обратите внимание, что это не совсем то же самое, поскольку все арифметические операции в JavaScript являются 64-разрядными с плавающей точкой, а не 32-разрядными, поэтому входные данные обязательно будут преобразованы. Также, как и в исходном коде, это зависит от платформы в том смысле, что оно даст бессмысленные результаты, если в архитектуре процессора используется другой порядок байтов; если вы должны сделать что-то подобное, я рекомендую вашему приложению сначала выполнить тестовый пример, чтобы определить, что целые числа и числа с плавающей запятой имеют ожидаемые вами байтовые представления.
Посмотрев на график, я подтвердил, что это дает разумные числовые результаты. Однако не очевидно, что это вообще улучшит производительность, так как мы выполняем более высокоуровневые операции JavaScript. Я провел тесты в браузерах, которые мне пригодились, и обнаружил, что это
Q_rsqrt(number)
занимает от 50% до 80% времени1/sqrt(number)
(Chrome, Firefox и Safari на macOS, по состоянию на апрель 2018 года). Вот моя полная тестовая настройка:источник
In classic JavaScript, it is not possible to... reinterpreting the bits of a floating-point number as an integer
действительно? Это было много лет назад, поэтому я не помню точно, какие операции я использовал, но однажды я написал в JavaScript анализатор данных, который преобразует строку байтов в последовательность N-битных (в заголовке было определено N). Это очень похоже.