{"action":"created","issue":{"url":"https://api.github.com/repos/kripken/emscripten/issues/4251","repository_url":"https://api.github.com/repos/kripken/emscripten","labels_url":"https://api.github.com/repos/kripken/emscripten/issues/4251/labels{/name}","comments_url":"https://api.github.com/repos/kripken/emscripten/issues/4251/comments","events_url":"https://api.github.com/repos/kripken/emscripten/issues/4251/events","html_url":"https://github.com/kripken/emscripten/issues/4251","id":148851616,"number":4251,"title":"Single precision floating point issues","user":{"login":"sagamusix","id":875883,"avatar_url":"https://avatars.githubusercontent.com/u/875883?v=3","gravatar_id":"","url":"https://api.github.com/users/sagamusix","html_url":"https://github.com/sagamusix","followers_url":"https://api.github.com/users/sagamusix/followers","following_url":"https://api.github.com/users/sagamusix/following{/other_user}","gists_url":"https://api.github.com/users/sagamusix/gists{/gist_id}","starred_url":"https://api.github.com/users/sagamusix/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sagamusix/subscriptions","organizations_url":"https://api.github.com/users/sagamusix/orgs","repos_url":"https://api.github.com/users/sagamusix/repos","events_url":"https://api.github.com/users/sagamusix/events{/privacy}","received_events_url":"https://api.github.com/users/sagamusix/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":11,"created_at":"2016-04-16T13:15:13Z","updated_at":"2016-05-16T17:19:43Z","closed_at":null,"body":"The calculations done by the following program show huge discrepancies compared to compiling them natively in GCC, Clang or MSVC:\r\n```\r\n#include <iostream>\r\n#include <cstdint>\r\n#include <cmath>\r\n\r\nuint32_t TransposeToFrequency(int32_t transpose, int32_t finetune)\r\n{\r\n\treturn static_cast<uint32_t>(std::floor(std::pow(2.0f, (transpose * 128.0f + finetune) * (1.0f / (12.0f * 128.0f))) * 8363.0f + 0.5f));\r\n}\r\n\r\nint main(int, char**)\r\n{\r\n\tuint32_t transposeToFrequency[] = // expected values as calculated by MSVC on x86\r\n\t{\r\n\t\t      5,       5,       5,       5,\r\n\t\t     31,      32,      33,      34,\r\n\t\t    196,     202,     207,     214,\r\n\t\t   1243,    1280,    1317,    1356,\r\n\t\t   7894,    8125,    8363,    8608,\r\n\t\t  50121,   51590,   53102,   54658,\r\n\t\t 318251,  327576,  337175,  347055,\r\n\t\t2020767, 2079980, 2140928, 2203663,\r\n\t};\r\n\r\n\tsize_t freqIndex = 0;\r\n\tfor(int32_t transpose = -128; transpose < 128; transpose += 32)\r\n    {\r\n\t\tfor(int32_t finetune = -128; finetune < 128; finetune += 64, freqIndex++)\r\n        {\r\n\t\t\tif(transposeToFrequency[freqIndex] != TransposeToFrequency(transpose, finetune))\r\n            {\r\n                std::cout << transpose << \"/\" << finetune << \" should be \" << transposeToFrequency[freqIndex] << \" but is \" << TransposeToFrequency(transpose, finetune) << std::endl;\r\n            }\r\n        }\r\n    }\r\n\r\n\treturn 0;\r\n}\r\n```\r\nOutput:\r\n```\r\nem++ --version\r\nemcc (Emscripten gcc/clang-like replacement) 1.36.0 (commit 07b87426f898d6e9c677db291d9088c839197291)\r\n\r\nem++ -std=c++11 -fPIC -O2 -s DISABLE_EXCEPTION_CATCHING=0 test.cpp\r\nnodejs a.out.js\r\n-96/-64 should be 32 but is 31\r\n-64/-128 should be 196 but is 193\r\n-64/0 should be 207 but is 210\r\n-64/64 should be 214 but is 210\r\n-32/-64 should be 1280 but is 1298\r\n-32/0 should be 1317 but is 1298\r\n0/-128 should be 7894 but is 8008\r\n0/-64 should be 8125 but is 8008\r\n0/64 should be 8608 but is 8733\r\n32/-128 should be 50121 but is 49403\r\n32/0 should be 53102 but is 53874\r\n32/64 should be 54658 but is 53874\r\n64/-64 should be 327576 but is 332341\r\n64/0 should be 337175 but is 332341\r\n96/-128 should be 2020767 but is 2050160\r\n96/-64 should be 2079980 but is 2050160\r\n96/64 should be 2203663 but is 2235715\r\n```\r\nThat's an error of about 1.5%, which is quite high.\r\nChanging the calculations to use double precision leads to a more acceptable result:\r\n```\r\nnodejs a.out.js\r\n96/64 should be 2203663 but is 2203662\r\n```"},"comment":{"url":"https://api.github.com/repos/kripken/emscripten/issues/comments/219486317","html_url":"https://github.com/kripken/emscripten/issues/4251#issuecomment-219486317","issue_url":"https://api.github.com/repos/kripken/emscripten/issues/4251","id":219486317,"user":{"login":"kripken","id":173661,"avatar_url":"https://avatars.githubusercontent.com/u/173661?v=3","gravatar_id":"","url":"https://api.github.com/users/kripken","html_url":"https://github.com/kripken","followers_url":"https://api.github.com/users/kripken/followers","following_url":"https://api.github.com/users/kripken/following{/other_user}","gists_url":"https://api.github.com/users/kripken/gists{/gist_id}","starred_url":"https://api.github.com/users/kripken/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kripken/subscriptions","organizations_url":"https://api.github.com/users/kripken/orgs","repos_url":"https://api.github.com/users/kripken/repos","events_url":"https://api.github.com/users/kripken/events{/privacy}","received_events_url":"https://api.github.com/users/kripken/received_events","type":"User","site_admin":false},"created_at":"2016-05-16T17:19:43Z","updated_at":"2016-05-16T17:19:43Z","body":"Probably in `-O1` LLVM thinks it can do better than the generic pow method, as it knows it's a power of 2.\r\n\r\nWhat goes wrong in those compiled methods is that they are sensitive to float precision, I believe. Perhaps they could be rewritten, but it wouldn't be easy ;)\r\n\r\nOverall, the solution is just to use `PRECISE_F32` to get the proper precision. I wish we could have it on by default, but browser limitations prevent it. However, it will be on in WebAssembly, so things will improve here."}}