{"id":16406193,"url":"https://github.com/itchyny/fastinvsqrt","last_synced_at":"2025-02-23T21:21:31.684Z","repository":{"id":47142099,"uuid":"62886547","full_name":"itchyny/fastinvsqrt","owner":"itchyny","description":"Fast inverse square root in programming languages","archived":false,"fork":false,"pushed_at":"2024-04-08T23:14:13.000Z","size":111,"stargazers_count":56,"open_issues_count":0,"forks_count":8,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-05T15:35:52.558Z","etag":null,"topics":["algorithm","fastinvsqrt","language","pointer-casting","programming-language"],"latest_commit_sha":null,"homepage":"","language":"Makefile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/itchyny.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-07-08T12:19:28.000Z","updated_at":"2024-12-10T19:32:37.000Z","dependencies_parsed_at":"2024-06-18T23:59:29.015Z","dependency_job_id":"ac0fe2c7-c00c-4fa0-bc1c-669ef0c095b1","html_url":"https://github.com/itchyny/fastinvsqrt","commit_stats":{"total_commits":176,"total_committers":7,"mean_commits":"25.142857142857142","dds":"0.15909090909090906","last_synced_commit":"730c7a492b3e1a5c79ea5b3c2faf26b2a7a1dd03"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itchyny%2Ffastinvsqrt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itchyny%2Ffastinvsqrt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itchyny%2Ffastinvsqrt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itchyny%2Ffastinvsqrt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/itchyny","download_url":"https://codeload.github.com/itchyny/fastinvsqrt/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240380360,"owners_count":19792281,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithm","fastinvsqrt","language","pointer-casting","programming-language"],"created_at":"2024-10-11T06:08:55.634Z","updated_at":"2025-02-23T21:21:31.410Z","avatar_url":"https://github.com/itchyny.png","language":"Makefile","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fast inverse square root in programming languages\n[![CI Status](https://github.com/itchyny/fastinvsqrt/workflows/CI/badge.svg)](https://github.com/itchyny/fastinvsqrt/actions)\n[![Number of languages](https://img.shields.io/badge/languages-37-blue)](https://api.github.com/repos/itchyny/fastinvsqrt/languages)\n\nThis is a repository for my challenge of *writing Fast inverse square root algorithm in many languages*.\n\nWriting one algorithm in many languages is fun.\nI wrote some codes in languages I have never experienced.\nI learned the differences and similarities between the languages, how languages are influenced by others.\n\nThis challenge is just a passing point on my way.\nNow I want to continue learning some languages I've never thought of writing before this challenge.\nFor example, I have never experienced Rust, OCaml and Erlang but now I think I should continue learning these languages.\n\n## Why did I choose this algorithm?\nHere is an implementation in C.\n```c\nfloat fastInvSqrt(float x) {\n  int i = *(int*)\u0026x;\n  i = 0x5f3759df - (i \u003e\u003e 1);\n  float y = *(float*)\u0026i;\n  return y * (1.5F - 0.5F * x * y * y);\n}\n```\nThe pointer casting magic is the most important part of this algorithm.\nI do not explain why the code works here, please refer to the other references [link](https://www.google.com/search?q=fast%20inverse%20square%20root).\n\nFirst of all, the algorithm to choose should not be too easy and should not be too difficult.\nIf the problem was easy, I could write the codes after some glance on the language tutorials.\nOn the other hand, I could give up the challenge if it was too difficult.\n\nSecondary, pointer casting is not such an easy task in some languages.\nSome languages do not allow us to touch the pointer addresses of the variables.\nFor scripting languages, I have to look through the document whether I can get the byte pattern of floating point numbers.\n\nThirdly, I like the algorithm.\nThe algorithm is largely based on how the floating point number is represented on our computers.\nWhen I came across this algorithm, I got very surprised that it effectively uses the casting pointers between different types of number.\n\n## Some examples in languages\nAll the codes are included in the repository but I want to introduce some interesting implementations here.\n\n### Groovy\nGroovy is like an un-fancy Java.\n```groovy\nScanner scanner = new Scanner(System.in)\nwhile (scanner.hasNext()) {\n  try {\n    println fastInvSqrt(Float.parseFloat(scanner.nextLine()))\n  } catch (NumberFormatException e) {}\n}\n\ndef fastInvSqrt(float x) {\n  int i = Float.floatToRawIntBits(x)\n  float y = Float.intBitsToFloat(0x5f3759df - (i \u003e\u003e 1))\n  y * (1.5F - 0.5F * x * y * y)\n}\n```\n\n### Clojure\nClojure is also a JVM language so the `Float/floatToRawIntBits` function routes in the function of Java.\n```clojure\n(defn fast-inv-sqrt [x]\n  (let [i (Float/floatToRawIntBits x)\n        y (Float/intBitsToFloat (- 0x5f3759df (bit-shift-right i 1)))]\n    (* y (- 1.5 (* 0.5 x y y)))))\n\n(doseq [line (line-seq (java.io.BufferedReader. *in*))]\n  (try (println (fast-inv-sqrt (read-string line)))\n      (catch java.lang.RuntimeException e ())))\n```\n\n### Crystal\nThis language looks like Ruby, but is one of the compiled languages.\nThe code of pointer casting looks pretty.\n```crystal\ndef fastinvsqrt(x : Float32) : Float32\n  i = pointerof(x).as(Int32*).value\n  i = 0x5f3759df - (i \u003e\u003e 1)\n  y = pointerof(i).as(Float32*).value\n  y * (1.5 - 0.5 * x * y * y)\nend\n\nwhile line = gets\n  puts fastinvsqrt(line.to_f32)\nend\n```\n\n### Rust\nThere are `f32::to_bits`, `f32::from_bits` to convert the number types keeping the bits.\n```rust\nuse std::io::BufRead;\n\nfn fast_inv_sqrt(x: f32) -\u003e f32 {\n    let i = x.to_bits();\n    let j = 0x5f3759df - (i \u003e\u003e 1);\n    let y = f32::from_bits(j);\n    y * (1.5 - 0.5 * x * y * y)\n}\n\nfn main() {\n    let stdin = std::io::stdin();\n    for line in stdin.lock().lines().filter_map(|x| x.ok()) {\n        if let Ok(x) = line.parse() {\n            println!(\"{}\", fast_inv_sqrt(x));\n        }\n    }\n}\n```\n\n### Perl\nThe pack and unpack is useful in this challenge for scripting languages (PHP, Ruby, Python etc).\nSomehow this code runs very fast as compiled languages.\n```perl\nuse strict;\nuse warnings;\nuse feature qw(say);\n\nwhile (\u003c\u003e) {\n  say fastInvSqrt($_);\n}\n\nsub fastInvSqrt {\n  my ($x) = @_;\n  my $i = unpack(\"l\", pack(\"f\", $x));\n  $i = 0x5f3759df - ($i \u003e\u003e 1);\n  my $y = unpack(\"f\", pack(\"l\", $i));\n  $y * (1.5 - 0.5 * $x * $y * $y);\n}\n```\n\n### JavaScript\nI thought it is impossible to implement in this language.\nThere's no difference between float and integer, 32-bit and 64-bit.\nHowever, JavaScript has TypedArray, which we can read and write the numbers in specific bit widths.\n```javascript\nrequire('readline').createInterface({\n    input: process.stdin,\n}).on('line', (line) =\u003e {\n    console.log(fastInvSqrt(parseFloat(line)));\n});\n\nfunction fastInvSqrt(x) {\n    const i = floatToUInt32(x);\n    const j = 0x5f3759df - (i \u003e\u003e 1);\n    const y = uint32ToFloat(j);\n    return y * (1.5 - 0.5 * x * y * y);\n}\n\nfunction floatToUInt32(x) {\n    const buf = Float32Array.of(x).buffer;\n    return new Uint32Array(buf)[0];\n}\n\nfunction uint32ToFloat(i) {\n    const buf = Uint32Array.of(i).buffer;\n    return new Float32Array(buf)[0];\n}\n```\n\n### J\nJust difficult to write, difficult to read.\n```j\nfastInvSqrt =: 3 : 0\n  i =. _2 ic 1 fc y\n  i =. (dfh'5f3759df') - _1 (33 b.) i\n  z =. _1 fc 2 ic i\n  z * (1.5 - 0.5 * y * z * z)\n)\n\necho \u0026 fastInvSqrt \u0026 (0 \u0026 \".) \u0026 (-. \u0026 CRLF) ;. 2 \u0026. stdin ''\nexit ''\n```\n\n### F# #\nF# is a .NET language so looking through the MSDN document gave me the way to convert to/from the byte arrays.\n```fsharp\nlet fastinvsqrt(x: float32): float32 =\n    let i = System.BitConverter.ToInt32(System.BitConverter.GetBytes(x), 0)\n    let j = 0x5f3759df - (i \u003e\u003e\u003e 1)\n    let y = System.BitConverter.ToSingle(System.BitConverter.GetBytes(j), 0)\n    y * (1.5F - 0.5F * x * y * y)\n\nseq { while true do yield stdin.ReadLine() }\n    |\u003e Seq.takeWhile ((\u003c\u003e) null)\n    |\u003e Seq.iter (fun x -\u003e try float32 x |\u003e fastinvsqrt |\u003e printfn \"%f\"\n                          with :? System.FormatException -\u003e ())\n```\n\n### Haskell\nHaskell is a functional programming language with advanced features of type system mainly for the research of this field.\nBut it also provides an interface to read and write pointers.\n```haskell\nimport Control.Monad ((\u003c=\u003c))\nimport Data.Bits (shiftR)\nimport Data.Traversable (mapM)\nimport Data.Word (Word32)\nimport Foreign.Marshal.Alloc (alloca)\nimport Foreign.Ptr (castPtr)\nimport Foreign.Storable (peek, poke)\nimport Prelude hiding (mapM)\nimport Text.Read (readMaybe)\n\nmain :: IO ()\nmain = mapM_ (mapM (print \u003c=\u003c fastInvSqrt) . readMaybe) . lines =\u003c\u003c getContents\n\nfastInvSqrt :: Float -\u003e IO Float\nfastInvSqrt x =\n  alloca $ \\ptr -\u003e do\n    poke ptr x\n    i \u003c- peek (castPtr ptr)\n    poke (castPtr ptr) $ 0x5f3759df - (i :: Word32) `shiftR` 1\n    y \u003c- peek ptr\n    return $ y * (1.5 - 0.5 * x * y * y)\n```\n\n### Erlang\nHow cool the binary pattern match is.\nI have never experienced this language but I think I want to learn more.\nThe test results show that the performance of this code is bad.\nIf you have any idea of improving the performance, please let me know from the issue tracker.\n```erlang\n-module(fastinvsqrt).\n-export([main/0, fast_inv_sqrt/1]).\n\nmain() -\u003e\n  case io:get_line(\"\") of\n    eof -\u003e ok;\n    {error, _} -\u003e ok;\n    Line -\u003e catch io:format(\"~f~n\", [fast_inv_sqrt(parse_float(Line))]), main()\n  end.\n\nfast_inv_sqrt(X) -\u003e\n  \u003c\u003cI:32/integer\u003e\u003e = \u003c\u003cX:32/float\u003e\u003e,\n  J = 16#5f3759df - (I bsr 1),\n  \u003c\u003cY:32/float\u003e\u003e = \u003c\u003cJ:32/integer\u003e\u003e,\n  Y * (1.5 - 0.5 * X * Y * Y).\n\nparse_float(Str) -\u003e\n  case string:to_float(Str) of\n    {error, _} -\u003e\n      case string:to_integer(Str) of\n        {error, _} -\u003e error;\n        {Int, _} -\u003e float(Int)\n      end;\n    {Float, _} -\u003e Float\n  end.\n```\n\n## Author\nitchyny (https://github.com/itchyny)\n\nSome codes were written by other people. Thank you so much.\n- The credit of the Smalltalk version goes to sumim [#2](https://github.com/itchyny/fastinvsqrt/pull/2).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitchyny%2Ffastinvsqrt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fitchyny%2Ffastinvsqrt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitchyny%2Ffastinvsqrt/lists"}