Created
September 29, 2024 17:15
-
-
Save Ssenseii/122fa372d830a0de3394d9082f8d3c34 to your computer and use it in GitHub Desktop.
Quake's Fast Inverse Square Root Implementation in Elixir.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| defmodule FastInverseSquareRoot do | |
| @magic_number 0x5f3759df | |
| # Quake Fast Inverse Square Root | |
| # steps | |
| # integer into a 32 bit integer. | |
| # the magic number - (the integer shifted to the right) | |
| # turn the int32integer to a float | |
| # return the newton formula: y * (1.5 - 0.5 * x * y * y); for a very close approximation | |
| def float_to_binary(f) when is_float(f) do | |
| <<int::32>> = <<f::float-32>> | |
| int | |
| end | |
| def int_to_float(int) do | |
| <<f::float-32>> = <<int::32>> | |
| f | |
| end | |
| def apply(x) when is_float(x) do | |
| half_x = x * 0.5 | |
| i = float_to_binary(x) | |
| i = @magic_number - Bitwise.bsr(i, 1) | |
| y = int_to_float(i) | |
| # Newton's approximation | |
| y = y * (1.5 - half_x * y * y) | |
| y | |
| end | |
| def benchmark do | |
| normal_inverse_square_root_time = measure_time(fn -> 1.0 / :math.sqrt(0.04598) end) | |
| fast_inverse_square_root_time = measure_time(fn -> FastInverseSquareRoot.apply(0.04598) end) | |
| IO.puts("Normal inverse square root time: #{normal_inverse_square_root_time} milliseconds") | |
| IO.puts("Fast inverse square root time: #{fast_inverse_square_root_time} milliseconds") | |
| IO.puts("Difference: #{normal_inverse_square_root_time - fast_inverse_square_root_time} milliseconds") | |
| end | |
| defp measure_time(fun) do | |
| start_time = :os.system_time(:nanosecond) | |
| fun.() | |
| end_time = :os.system_time(:nanosecond) | |
| (end_time - start_time) | |
| end | |
| end | |
| IO.puts(FastInverseSquareRoot.apply(0.12548)); | |
| IO.puts(FastInverseSquareRoot.benchmark()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment