{"id":16692525,"url":"https://github.com/ckormanyos/soft_double","last_synced_at":"2025-08-02T13:42:05.014Z","repository":{"id":37045618,"uuid":"354003302","full_name":"ckormanyos/soft_double","owner":"ckormanyos","description":"soft_double provides a C++ software implementation of a double-precision floating-point data type","archived":false,"fork":false,"pushed_at":"2025-03-26T20:10:39.000Z","size":807,"stargazers_count":18,"open_issues_count":6,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-10T01:14:52.303Z","etag":null,"topics":["double-precision","double-precision-floating-point","embedded-systems","floating-point-arithmetic","floating-point-emulation"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ckormanyos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING.txt","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":"2021-04-02T11:49:37.000Z","updated_at":"2025-04-09T10:18:12.000Z","dependencies_parsed_at":"2023-01-29T13:33:22.018Z","dependency_job_id":"42244c93-c8bd-4e34-83b5-b8691a68c010","html_url":"https://github.com/ckormanyos/soft_double","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ckormanyos/soft_double","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckormanyos%2Fsoft_double","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckormanyos%2Fsoft_double/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckormanyos%2Fsoft_double/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckormanyos%2Fsoft_double/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ckormanyos","download_url":"https://codeload.github.com/ckormanyos/soft_double/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckormanyos%2Fsoft_double/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263608567,"owners_count":23488039,"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":["double-precision","double-precision-floating-point","embedded-systems","floating-point-arithmetic","floating-point-emulation"],"created_at":"2024-10-12T16:27:26.024Z","updated_at":"2025-07-04T19:38:19.358Z","avatar_url":"https://github.com/ckormanyos.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"soft_double\n==================\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/ckormanyos/soft_double/actions\"\u003e\n        \u003cimg src=\"https://github.com/ckormanyos/soft_double/actions/workflows/soft_double.yml/badge.svg\" alt=\"Build Status\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/ckormanyos/soft_double/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc\"\u003e\n        \u003cimg src=\"https://custom-icon-badges.herokuapp.com/github/issues-raw/ckormanyos/soft_double?logo=github\" alt=\"Issues\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://scan.coverity.com/projects/ckormanyos-soft_double\"\u003e\n        \u003cimg src=\"https://scan.coverity.com/projects/26197/badge.svg\" alt=\"Coverity Scan Build Status\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://sonarcloud.io/summary/new_code?id=ckormanyos_soft_double\"\u003e\n        \u003cimg src=\"https://sonarcloud.io/api/project_badges/measure?project=ckormanyos_soft_double\u0026metric=alert_status\" alt=\"Quality Gate Status\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://codecov.io/gh/ckormanyos/soft_double\"\u003e\n        \u003cimg src=\"https://codecov.io/gh/ckormanyos/soft_double/branch/main/graph/badge.svg?token=V1JNXSUQJQ\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/ckormanyos/soft_double/blob/master/LICENSE_1_0.txt\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/license-BSL%201.0-blue.svg\" alt=\"Boost Software License 1.0\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://img.shields.io/github/commit-activity/y/ckormanyos/soft_double\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/commit-activity/y/ckormanyos/soft_double\" alt=\"GitHub commit activity\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/ckormanyos/soft_double\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/languages/code-size/ckormanyos/soft_double\" alt=\"GitHub code size in bytes\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://godbolt.org/z/dqTG9cPbT\" alt=\"godbolt\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/try%20it%20on-godbolt-green\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nsoft_double is a C++ header-only library that implements\na 64-bit double-precision floating-point data type in software.\nThe data type implemented is called `::math::softfloat::soft_double`\nand it can be used essentially like a regular\nbuilt-in 64-bit floating-point type (such as built-in `double`).\nThis data type type is also aliased to `::math::softfloat::float64_t`.\n\nSome C/C++ environments do not support a built-in 64-bit floating-point type,\nwhich might be commonly known as `double` or `long` `double`,\ndepending on the target system/compiler combination.\nConsider, for instance, the `avr-gcc` tool chain popularly used on\n8-bit embedded systems like Arduino or standalone _bare metal_ AVR.\nPrior to version 10, this compiler does not support 64-bit `double`.\n\nOn such systems, soft_double can be used to provide a software-emulated,\nportable implementation of 64-bit `double`.\n\nsoft_double implements common algebraic operations,\ncomparison operations, simple functions such as\n`fabs`, `frexp`, `sqrt`, some power functions such as\n`log`, `exp`, a few trigonometric functions including\n`sin`, `cos`, and more. There is also full support/specialization\nof `std::numeric_limits\u003csoft_double\u003e` for the `soft_double` type.\n\nThe soft_double implementation is written in header-only C++14\nand is compatible for C++14, 17, 20, 23 and beyond.\n\n## Quick Start\n\nUsing soft_double is straightforward. Simply `#include \u003cmath/softfloat/soft_double.h\u003e` and\nthe `soft_double` type can be used almost like familiar built-in 64-bit `double`.\nFor instance,\n\n```cpp\n#include \u003cmath/softfloat/soft_double.h\u003e\n\n// Use a convenient alias for float64_t.\nusing ::math::softfloat::float64_t;\n\n// Use the type like built-in `double`.\nconst float64_t one_third = float64_t(1U) / 3U;\n```\n\nAn interesting detail in this code sample is the construction\nof `one_third` from the composite initialization\nprovided by `float64_t(1U) / 3U`.\nThis is needed, for example, when the compiler\ndoes not support 64-bit built-in `double` or `long` `double`\nand these are limited to 32-bits (because\nthe 64-bit floating-point type is the actual type\nthat is being emulated). This situation arises,\nas mentioned above, on certain popular versions of\nthe `avr-gcc` and other tool chains.\n\n## Implementation goals\n\n  - Clean header-only C++ design.\n  - Seamless portability to any modern C++14, 17, 20, 23 compiler (and beyond).\n  - Achieve efficiency suitable for _bare-metal_ embedded systems.\n  - Particularly useful if 64-bit native `double` or a similar built-in type is unavailable.\n  - Use refactored versions of trusted algorithms based on those found in [softfloat 3e](https://github.com/ucb-bar/berkeley-softfloat-3).\n\n## Details\n\nThe following more detailed example provides an in-depth examination\ninto effectively using soft_double. This code computes and checks the value of\n\n$$\\sqrt{\\pi}~{\\approx}~1.77245385090551602730{\\ldots}$$\n\nThis example, compiled with successful output result,\nis shown in its entirety in the following\n[short link](https://godbolt.org/z/dqTG9cPbT) to [godbolt](https://godbolt.org).\n\n```cpp\n#include \u003cmath/softfloat/soft_double.h\u003e\n\n#include \u003ccmath\u003e\n#include \u003ciomanip\u003e\n#include \u003ciostream\u003e\n#include \u003csstream\u003e\n\nauto main() -\u003e int\n{\n  using ::math::softfloat::soft_double;\n\n  // Initialize the soft_double value of pi with built-in double.\n  const soft_double my_pi = 3.1415926535897932384626433832795028841972;\n\n  // Compute the soft_double value of sqrt(pi).\n  {\n    std::stringstream strm { };\n\n    strm \u003c\u003c \"sqrt(pi) as soft-double:     \" \u003c\u003c std::fixed\n                                            \u003c\u003c std::setprecision(static_cast\u003cstd::streamsize\u003e(std::numeric_limits\u003csoft_double\u003e::max_digits10))\n                                            \u003c\u003c sqrt(my_pi);\n\n    std::cout \u003c\u003c strm.str() \u003c\u003c std::endl;\n  }\n\n  {\n    std::stringstream strm { };\n\n    // Compute the built-in double value of sqrt(pi).\n    strm \u003c\u003c \"sqrt(pi) as built-in double: \" \u003c\u003c std::fixed\n                                            \u003c\u003c std::setprecision(static_cast\u003cstd::streamsize\u003e(std::numeric_limits\u003cdouble\u003e::max_digits10))\n                                            \u003c\u003c std::sqrt(3.1415926535897932384626433832795028841972)\n                                            ;\n\n    std::cout \u003c\u003c strm.str() \u003c\u003c std::endl;\n  }\n}\n```\n\nWhen working with soft_double, performing library verification,\nor prototyping project-specific software algorithms\n(intended) to use the `soft_double` type, a built-in 64-bit `double`\ncan be helpful if available.\nThe examples, testing and verification of numerical correctness\nin the soft_double project do, in fact, actually use 64-bit built-in `double`.\n\n## Bare Metal Microcontroller\n\nsoft_double can readily be used _on the metal_ to emulate a 64-bit floating point type.\nThis can be provide the ability to do 64-bit floating-point calculations on\ntarget system/compiler combinations lacking a built-in 64-bit floating-point type.\n\nAn example tested on various microcontrollers system\ncan be found in the file\n[`example010_hypergeometric_2f1.cpp`](./examples/example010_hypergeometric_2f1.cpp).\nThis benchmark has also been tested on the 8-bit MICROCHIP ATmega328P controller\nwith `avr-gcc` versions 5 and 7 (both lacking built-in 64-bit `double`).\n\nWhen working with even the most tiny microcontroller systems,\nI/O streaming can optionally be disabled with the compiler switch:\n\n```cpp\n#define SOFT_DOUBLE_DISABLE_IOSTREAM\n```\n\n## Examples\n\nVarious interesting and algorithmically challenging\n[examples](./examples) have been implemented.\nIt is hoped that the examples provide inspiration and guidance on\nhow to use soft_double.\n\n  - ![`example001_roots_sqrt.cpp`](./examples/example001_roots_sqrt.cpp) computes a square root.\n  - ![`example004_bessel_recur.cpp`](./examples/example004_bessel_recur.cpp) implements cylindrical Bessel functions of integral order via downward recursion with a Neumann sum.\n  - ![`example005_polylog_series.cpp`](./examples/example005_polylog_series.cpp) performs a small-argument polylogarithm series calculation.\n  - ![`example007_catalan_series.cpp`](./examples/example007_catalan_series.cpp) computes $\\sim 15$ decimal digits of Catalan's constant using an accelerated series.\n  - ![`example010_hypergeometric_2f1.cpp`](./examples/example010_hypergeometric_2f1.cpp) calculates $\\sim 15$ decimal digits of a hypergeometric function value using a classic iterative rational approximation scheme.\n  - ![`example011_trig_trapezoid_integral.cpp`](./examples/example011_trig_trapezoid_integral.cpp) uses trapezoid integration with an integral representation involving locally-written trigonometric sine and cosine functions to compute several cylindrical Bessel function values.\n  - ![`example012_exercise_constexpr.cpp`](./examples/example012_exercise_constexpr.cpp) verifies that C++20 `constexpr`-ness works properly for both rudimentary assignment-operation as well as an elementary square root function.\n\n## C++20 `constexpr` support\n\nWhen using C++20, `soft_double` supports compile-time\n`constexpr` construction and evaluation of results\nof binary arithmetic, comparison operators\nand various elementary functions.\n\nThe following code, for instance, shows a compile-time instantiation\nof `soft_double` with subsequent `constexpr` evaluation\nof a square root function and its comparison of its result\nwith the known control value.\n\nSee this example fully worked out at the following\n[short link](https://godbolt.org/z/ec1GG1sxd) to [godbolt](https://godbolt.org).\nThe generated assembly includes nothing other than the call to `main()`\nand its subsequent `return` of the value zero\n(i.e., `main()`'s successful return-value in this example).\n\n```cpp\n#include \u003cmath/softfloat/soft_double.h\u003e\n\n#include \u003ccmath\u003e\n\n// Use a C++20 (or higher) compiler for this example.\n\nint main()\n{\n  // Use a convenient alias for float64_t.\n  using ::math::softfloat::float64_t;\n\n  // Use a cached value for pi.\n  constexpr float64_t my_pi { float64_t::my_value_pi() };\n\n  // Compute soft_double sqrt(pi).\n  constexpr float64_t s { sqrt(my_pi) };\n\n  constexpr bool\n    result_is_ok\n    {\n      (s.crepresentation() == static_cast\u003ctypename float64_t::representation_type\u003e(UINT64_C(0x3FFC5BF891B4EF6A)))\n    };\n\n  // constexpr verification.\n  // This is a compile-time comparison.\n  static_assert(result_is_ok, \"Error: example001_roots_sqrt not OK!\");\n\n  return (result_is_ok ? 0 : -1);\n}\n```\n\n`constexpr`-ness of `soft_double` has been checked on GCC, clang\n(with `-std=c++20` and beyond) and VC 14.2 and higher (with `/std:c++latest`),\nalso for various embedded compilers such as `avr-gcc` 11 and up,\n`arm-non-eabi-gcc` 11 and up, and more.\nIn addition, less modern compiler versions have been sporadically\n(not exhaustively) checked for `constexpr` usage of `soft_double`.\nIf you have an older compiler, you might have to check the compiler's\nability to obtain the entire benefit of `constexpr` with `soft_double`.\n\nIn [issue 110](https://github.com/ckormanyos/soft_double/issues/110),\nthe topic of `constexpr`-ness regarding construction from built-in `float`,\n`double` and `long` `double` was briefly addressed. At the moment,\nconstruction from built-in floating-point types adheres to C++20 `constexpr`-ness\nor higher. Perhaps in the future, an alternate programing could bring this feature\nto earlier language standards.\n\nThe macro sequence below can be used to test for the feature\nof `constexpr`-ness regarding construction from built-in\nfloating-point types.\n\n```cpp\n#include \u003cmath/softfloat/soft_double.h\u003e\n\n#if ((defined SOFT_DOUBLE_CONSTEXPR_BUILTIN_FLOATS) \u0026\u0026 (SOFT_DOUBLE_CONSTEXPR_BUILTIN_FLOATS == 1))\n#endif\n```\n\nIt is not mandatory to actually use this feature-test if the\nlanguage standard being used is known to be sufficiently high\nfor compatibility. The following code, for instance, uses\n`constexpr` construction from built-in `double`,\nas shown also in this\n[short link](https://godbolt.org/z/sovzoWTMc) to [godbolt](https://godbolt.org).\n\n```cpp\n#include \u003cmath/softfloat/soft_double.h\u003e\n\nauto main() -\u003e int\n{\n  using ::math::softfloat::float64_t;\n\n  constexpr auto gravitational_constant = float64_t { 6.674e-11 };\n  constexpr auto near_pi_constant       = float64_t { 3.14 };\n  constexpr auto one_quarter_constant   = float64_t { 0.25 };\n\n  static_assert(gravitational_constant \u003c 1, \"Error: Initialization constexpr-double does not properly work\");\n  static_assert(gravitational_constant != near_pi_constant, \"Error: Initialization constexpr-double does not properly work\");\n  static_assert(static_cast\u003cint\u003e(INT8_C(4)) * one_quarter_constant == 1, \"Error: Initialization constexpr-double does not properly work\");\n  static_assert(static_cast\u003cint\u003e(INT8_C(12)) * one_quarter_constant \u003c near_pi_constant, \"Error: Initialization constexpr-double does not properly work\");\n  static_assert(static_cast\u003cint\u003e(INT8_C(13)) * one_quarter_constant \u003e near_pi_constant, \"Error: Initialization constexpr-double does not properly work\");\n}\n```\n\n## Building, testing and CI\n\n### Build Status\n[![Build Status](https://github.com/ckormanyos/soft_double/actions/workflows/soft_double.yml/badge.svg)](https://github.com/ckormanyos/soft_double/actions)\n\nThe recent status of building and executing the tests and examples\nin Continuous Integration (CI) is always shown in the Build Status banner.\n\nSimply using the [`soft_double.h` header](./math/softfloat/soft_double.h)\ncan be accomplished by identifying the header within\nits directory, including the header path and header in the normal C++ way.\n\nBuilding and running the tests and examples can be accomplished\nusing the Microsoft VisualStudio solution workspace provided\nin `soft_double.sln` located in the project's root directory.\nIt is also possible, if desired, to build and execute\nthe tests and examples using various different OS/compiler\ncombinations.\n\nTesting is a big issue and a growing test suite\nis in continued progress providing for tested,\nefficient functionality on the PC and workstation.\nThe GitHub code is delivered with an affiliated MSVC project.\nIt uses easy-to-understand subroutines called from\n[`main()`](https://github.com/ckormanyos/soft_double/blob/fa628ee77c002c1073256056f7dcdb57d45e758c/test/test.cpp#L13)\nthat exercise various test cases.\n\nFurthermore,\nthe [`example010_hypergeometric_2f1.cpp`](./examples/example010_hypergeometric_2f1.cpp)\nbenchmark is built-for the 8-bit MICROCHIP ATmega328P controller\nand it is also built-for and executed-on the simulated\n32-bit ARM(R) Cortex(R)-M4F in QEMU in CI.\n\nCI runs on push and pull request using GitHub Actions.\nVarious compilers, operating systems, and various\nC++ standards are included in CI.\n\n## Origins and Licensing\n\nThe origins of `soft_double` in modern C++ can be traced to traditional\n[berkeley-softfloat-3](https://github.com/ucb-bar/berkeley-softfloat-3).\nConsistency with the\n[original licensing](./COPYING.txt)\nthereof has been retained.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fckormanyos%2Fsoft_double","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fckormanyos%2Fsoft_double","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fckormanyos%2Fsoft_double/lists"}