{"id":16692515,"url":"https://github.com/ckormanyos/wide-decimal","last_synced_at":"2025-05-12T04:30:29.630Z","repository":{"id":36998987,"uuid":"309114203","full_name":"ckormanyos/wide-decimal","owner":"ckormanyos","description":"Wide-Decimal implements a generic C++ template for large decimal float types from about 10 up to 10 million digits. ","archived":false,"fork":false,"pushed_at":"2025-03-25T14:04:55.000Z","size":1918,"stargazers_count":51,"open_issues_count":11,"forks_count":8,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-03-31T23:51:29.408Z","etag":null,"topics":["arbitrary-precision","bigdecimal","bigfloat","embedded-systems","high-performance","multiple-precision","multiprecision"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsl-1.0","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":"LICENSE_1_0.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":"2020-11-01T14:30:48.000Z","updated_at":"2025-03-25T14:04:58.000Z","dependencies_parsed_at":"2024-01-19T19:40:43.879Z","dependency_job_id":"dc2b1d44-6756-46df-acae-129492c68827","html_url":"https://github.com/ckormanyos/wide-decimal","commit_stats":{"total_commits":944,"total_committers":6,"mean_commits":"157.33333333333334","dds":0.08792372881355937,"last_synced_commit":"d19f49277bab554644183cf33eae098c88914609"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckormanyos%2Fwide-decimal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckormanyos%2Fwide-decimal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckormanyos%2Fwide-decimal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckormanyos%2Fwide-decimal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ckormanyos","download_url":"https://codeload.github.com/ckormanyos/wide-decimal/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253675041,"owners_count":21945886,"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":["arbitrary-precision","bigdecimal","bigfloat","embedded-systems","high-performance","multiple-precision","multiprecision"],"created_at":"2024-10-12T16:27:23.509Z","updated_at":"2025-05-12T04:30:28.732Z","avatar_url":"https://github.com/ckormanyos.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"Wide-decimal\n==================\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/ckormanyos/wide-decimal/actions\"\u003e\n        \u003cimg src=\"https://github.com/ckormanyos/wide-decimal/actions/workflows/wide_decimal.yml/badge.svg\" alt=\"Build Status\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/ckormanyos/wide-decimal/issues\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/issues-raw/ckormanyos/wide-decimal\" alt=\"Open Issues\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/ckormanyos/wide-decimal/actions?query=workflow%3ACodeQL\"\u003e\n        \u003cimg src=\"https://github.com/ckormanyos/wide-decimal/actions/workflows/CodeQL.yml/badge.svg\" alt=\"CodeQL\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://scan.coverity.com/projects/ckormanyos-wide-decimal\"\u003e\n        \u003cimg src=\"https://scan.coverity.com/projects/24792/badge.svg\" alt=\"Coverity Scan\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://sonarcloud.io/summary/new_code?id=ckormanyos_wide-decimal\"\u003e\n        \u003cimg src=\"https://sonarcloud.io/api/project_badges/measure?project=ckormanyos_wide-decimal\u0026metric=alert_status\" alt=\"Quality Gate Status\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://www.codacy.com/gh/ckormanyos/wide-decimal/dashboard?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=ckormanyos/wide-decimal\u0026amp;utm_campaign=Badge_Grade\"\u003e\n        \u003cimg src=\"https://app.codacy.com/project/badge/Grade/3f3d6624f20e4b53b95de69202cfe297\"/\u003e\u003c/a\u003e\n    \u003ca href=\"https://codecov.io/gh/ckormanyos/wide-decimal\"\u003e\n        \u003cimg src=\"https://codecov.io/gh/ckormanyos/wide-decimal/branch/main/graph/badge.svg?token=9SEP7RLNSO\" alt=\"code coverage\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/ckormanyos/wide-decimal/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/wide-decimal\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/commit-activity/y/ckormanyos/wide-decimal\" alt=\"GitHub commit activity\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/ckormanyos/wide-decimal\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/languages/code-size/ckormanyos/wide-decimal\" alt=\"GitHub code size in bytes\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nWide-decimal implements a generic C++ template for extended width\ndecimal float types.\n\nThis C++ template header-only library implements drop-in big decimal float types,\nsuch as `dec51_t`, `dec101_t`, `dec1001_t`, `dec10001_t`, `dec1000001_t`, etc.,\nthat can be used essentially like regular built-in floating-point types.\nWide-decimal supports decimal float types having digit counts ranging\nroughly from about ${\\sim}~10 {\\ldots} 10^{7}$.\n\nWide-decimal implements both elementary algebraic operations as well as\na few common `\u003ccmath\u003e`-like functions such as `fabs`, `sqrt` and `log`.\nIt also includes full support for `std::numeric_limits`.\n\nWide-decimal is written in header-only C++14, and compatible through C++14, 17, 20, 23 and beyond.\n\n## Implementation goals\n\n  - Instances of the `decwide_t` type should behave as closely as possible to the behavior of built-in floating-point types.\n  - Relatively wide precision range from about ${\\sim}~10 {\\ldots} 10^{7}$ decimal digits.\n  - Moderately good efficiency over the entire wide precision range.\n  - Clean header-only C++14 design.\n  - Seamless portability to any modern C++14, 17, 20, 23 compiler and beyond.\n  - Scalability with small memory footprint and efficiency suitable for both PC/workstation systems as well as _bare-metal_ embedded systems.\n\n## Quick start\n\nEasy application follows via a traditional C-style typedef or C++14 alias.\nThe defined type can be used very much like a built-in floating-point type.\n\nThe following sample, for instance, defines and uses a decimal type\ncalled `dec101_t` having $101$ decimal digits of precision.\nIn this example, the subroutine `do_something()` initializes the variable `d`\nof type `dec101_t` with $\\frac{1}{3}$. The $101$ digit value of `d`\nis subsequently printed to the console. The console precision is set with\n`std::setprecision` in combination with `dec101_t`'s specialization\nof `std::numeric_limits`.\n\nIn particular,\n\n```cpp\n#include \u003ciomanip\u003e\n#include \u003ciostream\u003e\n\n#include \u003cmath/wide_decimal/decwide_t.h\u003e\n\nvoid do_something()\n{\n  using dec101_t = ::math::wide_decimal::decwide_t\u003cINT32_C(101), std::uint32_t, void\u003e;\n\n  dec101_t d = dec101_t(1) / 3;\n\n  // 0.33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333\n  std::cout \u003c\u003c std::setprecision(std::numeric_limits\u003cdec101_t\u003e::digits) \u003c\u003c d \u003c\u003c std::endl;\n}\n```\n\nThe local data type `dec101_t` is defined with a C++14 alias.\nThe first template parameter `INT32_C(101)` sets the decimal digit\ncount while the second optional template parameter `std::uint32_t`\nsets the internal _limb_ _type_. If the second template parameter is left blank,\nthe default limb type is thirty-two bits in width and unsigned.\n\nThe template signature of the `decwide_t` class is shown below.\n\n```cpp\n// Forward declaration of the decwide_t template class.\ntemplate\u003cconst std::int32_t ParamDigitsBaseTen,\n         typename LimbType          = std::uint32_t,\n         typename AllocatorType     = std::allocator\u003cvoid\u003e,\n         typename InternalFloatType = double,\n         typename ExponentType      = std::int64_t,\n         typename FftFloatType      = double\u003e\nclass decwide_t;\n```\n\n`decwide_t` also has a third (and a few more) optional template paramter(s).\nThe third template parameter `AllocatorType`\ncan be used to set the allocator type for internal storage of the\nwide decimal type. The default allocator type is\n`std::allocator\u003climb_type\u003e` which helps to reduce\nstack consumption, especially when using higher digit counts.\nIf low digit counts are used, the allocator type can\nbe explicitly set to `void`\nand stack allocation is used with an `array`-like\ninternal representation.\n\n## Examples\n\nVarious interesting [examples](./examples), some of which are\nquite algorithmically challenging, have been implemented.\nIt is hoped that the examples provide inspiration and guidance on\nhow to use wide-decimal.\n\nThe examples include the following.\n\n  - ![`example000_multiply_nines.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example000_multiply_nines.cpp) verifies schoolbook multiplication using a `decwide-t` type having 8-bit limbs in a small digit range.\n  - ![`example000a_multiply_pi_squared.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example000a_multiply_pi_squared.cpp) performs a hard-coded multiplication check resulting in $\\pi^2$.\n  - ![`example001_roots_sqrt.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example001_roots_sqrt.cpp) computes a square root.\n  - ![`example001a_roots_seventh.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example001a_roots_seventh.cpp) computes a seventh root.\n  - ![`example001b_roots_almost_integer.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example001b_roots_almost_integer.cpp) uses roots and algebraic operations to compute $5,001$ decimal digits of a fascinating [Pisot number](https://mathworld.wolfram.com/PisotNumber.html) that is [almost integer](https://mathworld.wolfram.com/AlmostInteger.html).\n  - ![`example001c_roots_sqrt_limb08.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example001c_roots_sqrt_limb08.cpp) computes a square root with a wide decimal representation having 8-bit limbs.\n  - ![`example001d_pow2_from_list.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example001d_pow2_from_list.cpp) verifies a list of values $2^n$ with $-128 {\\le} n {\\le} 127$.\n  - ![`example002_pi.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example002_pi.cpp) calculates $1,000,001$ decimal digits of $\\pi$ using a Gauss AGM iteration.\n  - ![`example002a_pi_small_limb.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example002a_pi_small_limb.cpp) calculates $1,000,001$ decimal digits of $\\pi$ using a 16-bit internal limb type.\n  - ![`example002b_pi_100k.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example002b_pi_100k.cpp) calculates $100,001$ decimal digits of $\\pi$.\n  - ![`example002c_pi_quintic.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example002c_pi_quintic.cpp) calculates $1,000,001$ decimal digits of $\\pi$ using a Borwein quintic iteration.\n  - ![`example002d_pi_limb08.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example002d_pi_limb08.cpp) calculates yet again $1,000,001$ decimal digits of $\\pi$ using an 8-bit internal limb type and `float` internal floating-point type.\n  - ![`example001e_algebra_and_constexpr.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example001e_algebra_and_constexpr.cpp) (TBD) verifies some basic C++20 `constexpr` algebraic operations.\n  - ![`example003_zeta.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example003_zeta.cpp) computes a Riemann zeta function value.\n  - ![`example004_bessel_recur.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example004_bessel_recur.cpp) implements cylindrical Bessel functions of integral order via downward recursion with a Neumann sum.\n  - ![`example005_polylog_series.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example005_polylog_series.cpp) performs a small-argument polylogarithm series calculation.\n  - ![`example006_logarithm.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example006_logarithm.cpp) calculates the value of a logarithm (internally using a Gauss AGM method).\n  - ![`example007_catalan_series.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example007_catalan_series.cpp) computes $1,001$ decimal digits of Catalan's constant using an accelerated series.\n  - ![`example008_bernoulli_tgamma.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example008_bernoulli_tgamma.cpp) implements `tgamma(x)` using Stirling's asymptotic expansion of the logarithm of the Gamma function with Bernoulli numbers and subsequently calculates $1,001$ decimal digits of $\\Gamma(n/2)$ for small integer $n$.\n  - ![`example009_boost_math_standalone.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example009_boost_math_standalone.cpp) checks basic compatibility of standalone `decwide_t` with `Boost.Math` by testing a cube root value obtained from `boost::math::cbrt`.\n  - ![`example009a_boost_math_standalone.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example009a_boost_math_standalone.cpp) also checks standalone `decwide_t` with significantly more of `Boost.Math` by testing a $1,001$ digit generalized Legendre function value (using `boost::math::tgamma` and more to do so).\n  - ![`example009b_boost_math_standalone.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example009b_boost_math_standalone.cpp) checks yet again standalone `decwide_t` with `Boost.Math`'s available `boost::math::tgamma` function for small-ish decimal floats having ${\\lesssim}~100$ decimal digits.\n  - ![`example010_hypergeometric_2f1.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example010_hypergeometric_2f1.cpp) calculates a $1,001$ decimal digit hypergeometric function value using an iterative rational approximation scheme.\n  - ![`example010a_hypergeometric_1f1.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example010a_hypergeometric_1f1.cpp) calculates another $1,001$ decimal digit hypergeometric function in a similar fashion.\n  - ![`example011_trig_trapezoid_integral.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/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_rational_floor_ceil.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example012_rational_floor_ceil.cpp) verifies the proper representation of a wide selection of small-valued, pure integral rational quotients.\n  - ![`example013_embeddable_sqrt.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example013_embeddable_sqrt.cpp) and ![`example013a_embeddable_agm.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/examples/example013a_embeddable_agm.cpp) exercise calculations that also run on tiny bare-metal embedded systems. These two straightforward embedded-ready examples feature a ${\\sim}100$ digit square root calculation and a ${\\sim}50$ digit AGM iteration for $\\pi$, respectively.\n\n## Testing, CI and Quality Checks\n\n### Testing\n\nTesting is definitely a big issue. A growing, supported\ntest suite improves confidence in the library.\nIt provides for tested, efficient functionality on the PC and workstation.\nThe GitHub code is, as mentioned above, delivered with an affiliated MSVC\nproject or a variety of other build/make options that use easy-to-understand\nsubroutines called from `main()`. These exercise the various\nexamples and the full suite of test cases.\n\nIf an issue is reported, reproduced and verified, an attempt\nis made to correct it without breaking any other\ncode. Upon successful correction, specific test cases\nexercising the reported issue are usually added as part\nof the issue resolution process.\n\n### CI and Quality checks\n\nCI runs on both push-to-branch as well as pull request using GitHub Actions.\nVarious compilers, operating systems, and C++ standards\nranging from C++14, 17, 20, 23 are included in CI.\n\nIn CI, we use both elevated GCC/clang compiler warnings\nas well as MSVC level 4 warnings active on the correspondoing platforms.\nFor additional in-depth syntax checking, clang-tidy is used both in CI\nas well as in offline checks to improve static code quality.\n\nBoth GCC's run-time\n[sanitizers](https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html)\nas well as [_valgrind_](https://valgrind.org) (see also [1] and [2] in the References below)\nare used in CI in order to help assure dynamic quality.\n\nAdditional quality checks are performed on pull-request\nand merge to master using modern third party open-source services.\nThese include\n[CodeQL](https://github.com/ckormanyos/wide-decimal/actions?query=workflow%3ACodeQL),\n[Synopsis Coverity](https://scan.coverity.com/projects/ckormanyos-wide-decimal),\nand [CodeSonar](https://sonarcloud.io/summary/new_code?id=ckormanyos_wide-decimal).\nAt the moment, the Coverity check is run with manual report submission.\nAutomation of this is, however, planned.\n\nCode coverage uses GCC/gcov/lcov and has a\nquality-gate with comparison/baseline-check provided by\n[Codecov](https://app.codecov.io/gh/ckormanyos/wide-decimal).\n\nQuality badges are displayed at the top of this repository's\nreadme page.\n\n### Build status\n[![Build Status](https://github.com/ckormanyos/wide-decimal/actions/workflows/wide_decimal.yml/badge.svg)](https://github.com/ckormanyos/wide-decimal/actions)\n\n## Additional details\n\nWide-decimal has been tested with numerous compilers for target systems ranging from 8 to 64 bits.\nThe library is specifically designed for modest efficiency (not the world's fastest)\nover the entire range of small to large digit counts.\nHow efficient is the code? Based on a very general\ncomparison, a million digit AGM calculation of $\\pi$\nis about five times slower than an equivalent calculation\nperformed with a big float data type based on\n[GMP](https://gmplib.org/).\n\nPortability of the code is another key point of focus. Special care\nhas been taken to test in certain high-performance embedded real-time\nprogramming environments.\n\nWhen working with even the most tiny microcontroller systems,\nvarious _heavy-wieght_ features such as I/O streaming,\ndynamic memory allocation, construction from character string\nand caching constant values such as $\\pi$ and $\\log(2)$\ncan optionally be disabled with the compiler switches:\n\n```cpp\n#define WIDE_DECIMAL_DISABLE_IOSTREAM\n#define WIDE_DECIMAL_DISABLE_DYNAMIC_MEMORY_ALLOCATION\n#define WIDE_DECIMAL_DISABLE_CONSTRUCT_FROM_STRING\n#define WIDE_DECIMAL_DISABLE_CACHED_CONSTANTS\n#define WIDE_DECIMAL_DISABLE_USE_STD_FUNCTION\n#define WIDE_DECIMAL_NAMESPACE\n```\n\nEach one of these compiler switches has an intuitive name\nintended to represent its meaning.\n\nNote: Activating the option `WIDE_DECIMAL_DISABLE_DYNAMIC_MEMORY_ALLOCATION`\nsimultaneously disallows using `decwide_t` in a multithreaded application.\nSo if PC-based or other kinds of multithreading are used, then dynamic memory\nallocation is needed and can not be disabled. In other words,\n\n```cpp\n// Activate/Deactivate the disable of dynamic memory.\n// For most multithreaded PC work, comment out or remove\n// this line entirely (i.e., thereby enable dynamic memory).\n\n#define WIDE_DECIMAL_DISABLE_DYNAMIC_MEMORY_ALLOCATION\n```\n\nLet's consider also the macro `WIDE_DECIMAL_NAMESPACE` in greater detail.\n\n```cpp\n#define WIDE_DECIMAL_NAMESPACE something_unique\n```\n\nThis is an advanced macro intended to be used in strict, exacting applications for which\nusing the unqualified, global namespace `math` (i.e., `namespace` `::math`) is undesired or inacceptable.\nWe recall that all parts of the wide-decimal implementation,\nsuch as the `decwide_t` class and its associated implementation\ndetails reside within `namespace` `::math::wide_decimal`\n\nConsider defining the macro `WIDE_DECIMAL_NAMESPACE` to be a self-chosen,\nunique namespace name, for instance something like\n\n```sh\n-DWIDE_DECIMAL_NAMESPACE=something_unique\n```\n\nThis places all parts of the wide-decimal's `uintwide_t` template class implementation\nand its associated details within the prepended outer namespace\n`something_unique` - as in\n\n```cpp\nnamespace something_unique::math::wide_decimal\n{\n  template\u003cconst std::int32_t ParamDigitsBaseTen,\n           typename LimbType          = std::uint32_t,\n           typename AllocatorType     = std::allocator\u003cvoid\u003e,\n           typename InternalFloatType = double,\n           typename ExponentType      = std::int64_t,\n           typename FftFloatType      = double\u003e\n  class decwide_t;\n\n  // And also all its related types and functions.\n}\n```\n\nWhen utilizing the `WIDE_DECIMAL_NAMESPACE` option,\nit is easy to vary the actual name or nesting depth of the desired prepended\nouter namespace if/as needed for your particular project.\n\nBy default the macro `WIDE_DECIMAL_NAMESPACE` is not defined.\nIn this default state, `namespace` `::math::wide_decimal` is used\nand the `decwide_t` class and its associated implementation\ndetails reside therein.\n\n## Examples\n\n### Basic square root\n\nThe example below performs a basic square root calculation,\ngiven by approximately\n\n$$\\sqrt{\\frac{123456}{100}} \\approx 35.1363060095963986639333846404180557597515{\\ldots}$$\n\n```cpp\n#include \u003ccstdint\u003e\n#include \u003ciomanip\u003e\n#include \u003ciostream\u003e\n\n#include \u003cmath/wide_decimal/decwide_t.h\u003e\n\nauto main() -\u003e int\n{\n  using local_limb_type = std::uint16_t;\n\n  using dec101_t = ::math::wide_decimal::decwide_t\u003cINT32_C(101), local_limb_type, void\u003e;\n\n  const dec101_t s = sqrt(dec101_t(123456U) / 100);\n\n  // N[Sqrt[123456/100], 101]\n  const dec101_t control\n  {\n    \"35.136306009596398663933384640418055759751518287169314528165976164717710895452890928635031219132220978\"\n  };\n\n  const dec101_t closeness = fabs(1 - (s / control));\n\n  const auto result_is_ok = (closeness \u003c (std::numeric_limits\u003cdec101_t\u003e::epsilon() * 10));\n\n  std::cout \u003c\u003c \"result_is_ok: \" \u003c\u003c std::boolalpha \u003c\u003c result_is_ok \u003c\u003c std::endl;\n}\n```\n\n### 1,000,001 digits of pi\n\nIn the following code, we compute $1,000,001$ (one million and one)\ndecimal digits of the fundamental constant $\\pi$.\nThe truncated (non-rounded) expected result is\n$3.14159265{\\ldots}79458151$\nIn this particular example, all _heavyweight_ components are deactivated and\nthis particular calculation is, in fact, suitable for a bare-metal mega-digit pi calculation.\n\nIn this example, note how a specialized custom allocator called\n`util::n_slot_array_allocator` is utilized for exact, efficient memory management\nof a certain number of temporary storages of mega-digit numbers\n(tuned to $18$ in this particular example).\n\n```cpp\n#include \u003ciomanip\u003e\n#include \u003ciostream\u003e\n\n#define WIDE_DECIMAL_DISABLE_IOSTREAM\n#define WIDE_DECIMAL_DISABLE_DYNAMIC_MEMORY_ALLOCATION\n#define WIDE_DECIMAL_DISABLE_CONSTRUCT_FROM_STRING\n#define WIDE_DECIMAL_DISABLE_CACHED_CONSTANTS\n\n#include \u003cmath/wide_decimal/decwide_t.h\u003e\n#include \u003cutil/memory/util_n_slot_array_allocator.h\u003e\n\nauto main() -\u003e int\n{\n  using local_limb_type = std::uint32_t;\n\n  constexpr std::int32_t wide_decimal_digits10 = INT32_C(1000001);\n\n  constexpr std::int32_t local_elem_number =\n    ::math::wide_decimal::detail::decwide_t_helper\u003cwide_decimal_digits10, local_limb_type\u003e::elem_number;\n\n  constexpr std::int32_t local_elem_digits10 =\n    ::math::wide_decimal::detail::decwide_t_helper\u003cwide_decimal_digits10, local_limb_type\u003e::elem_digits10;\n\n  using local_allocator_type = util::n_slot_array_allocator\u003cvoid, local_elem_number, 18U\u003e;\n\n  using local_wide_decimal_type =\n    ::math::wide_decimal::decwide_t\u003cwide_decimal_digits10, local_limb_type, local_allocator_type, double\u003e;\n\n  const auto start = std::clock();\n\n  const local_wide_decimal_type my_pi =\n    ::math::wide_decimal::pi\u003cwide_decimal_digits10, local_limb_type, local_allocator_type, double\u003e(nullptr);\n\n  const auto stop = std::clock();\n\n  std::cout \u003c\u003c \"Time example002_pi(): \"\n            \u003c\u003c static_cast\u003cfloat\u003e(stop - start) / static_cast\u003cfloat\u003e(CLOCKS_PER_SEC)\n            \u003c\u003c std::endl;\n\n  const auto head_is_ok = std::equal(my_pi.crepresentation().cbegin(),\n                                     my_pi.crepresentation().cbegin() + ::math::constants::const_pi_control_head_32.size(),\n                                     ::math::constants::const_pi_control_head_32.begin());\n\n  using const_iterator_type = typename local_wide_decimal_type::array_type::const_iterator;\n\n  const_iterator_type\n    fi\n    (\n        my_pi.crepresentation().cbegin()\n      + static_cast\u003cstd::uint32_t\u003e\n        (\n            static_cast\u003cstd::uint32_t\u003e(1UL + ((wide_decimal_digits10 - 1UL) / local_elem_digits10))\n          - static_cast\u003cstd::uint32_t\u003e(::math::constants::const_pi_control_tail_32_1000001.size())\n        )\n    );\n\n  const auto tail_is_ok = std::equal(fi,\n                                     fi + ::math::constants::const_pi_control_tail_32_1000001.size(),\n                                          ::math::constants::const_pi_control_tail_32_1000001.begin());\n\n  const auto result_is_ok = (head_is_ok \u0026\u0026 tail_is_ok);\n\n  std::cout \u003c\u003c \"result_is_ok: \" \u003c\u003c std::boolalpha \u003c\u003c result_is_ok \u003c\u003c std::endl;\n}\n```\n\nThe million digit run is comparatively slow and requires approximately\nten seconds on a modern PC. Considering, however, the design goals\nof header-only and capable of running on bare-metal, this is\na very nice calculational result.\n\n### 1,000,001 digits of pi on a bare metal microcontroller\n\nThe wide-decimal float back end is used to compute\n$1,000,001$ decimal digits of the mathematical constant $\\pi$\non selected bare-metal OS-less microcontroller systems in\n[pi-crunch-metal](https://github.com/ckormanyos/pi-crunch-metal)\n\n## Further details\n\n### Mixing wide-decimal with wide-integer\n\n[Wide-decimal](https://github.com/ckormanyos/wide-decimal)\ncan be used simultaneously with\n[wide-integer](https://github.com/ckormanyos/wide-integer).\nAlthough this was not primarily foreseen in the designs\nof these libraries, harmonized mixing can be done in the same project,\nand even in the same file.\nThis can, however, lead to a conflicting multiple definition\nof the container class `util::dynamic_array\u003c\u003e`, as has been shown in\n[issue 166](https://github.com/ckormanyos/wide-decimal/issues/166).\n\nIn order to use the\n[`uintwide_t.h`](https://github.com/ckormanyos/wide-integer/tree/master/math/wide_integer)\nheader together with the\n[`decwide_t.h`](https://github.com/ckormanyos/wide-integer/tree/master/math/wide_integer)\nheader in the same translation unit, use the\ndefinition shown below.\n\n```cpp\n#define WIDE_INTEGER_DISABLE_IMPLEMENT_UTIL_DYNAMIC_ARRAY\n```\n\nEnsure that this definition appears _above_ the line that `#include`s\nthe `uintwide_t.h` header.\nDo this for all files including both big-number headers.\nAlternatively, this preprocessor\nswitch can be defined on the command line of the compiler call(s)\nfor the project.\n\nThe rational for this is as follows. The helper-container template class\n`util::dynamic_array\u003c\u003e` is used in both the\n[`decwide_t_detail.h`](https://github.com/ckormanyos/wide-decimal/tree/main/math/wide_decimal)\nheader (secondarily included in `decwide_t.h`) as well as the\n[`uintwide_t.h`](https://github.com/ckormanyos/wide-integer/tree/master/math/wide_integer)\nheader.\nDefining `WIDE_INTEGER_DISABLE_IMPLEMENT_UTIL_DYNAMIC_ARRAY`\nupstream of the inclusion of the `uintwide_t.h` header\ndisables that file's definition\nof `util::dynamic_array\u003c\u003e`, and ensures that\nonly one definition is visivble in the file\ncontaining both big-number headers.\n\nA use-case that uses both\n[wide-decimal](https://github.com/ckormanyos/wide-decimal)\nas well as\n[wide-integer](https://github.com/ckormanyos/wide-integer)\nsimultaneously has been implemented in a test file.\nThis file is called\n[`test_mixed_wide_decimal_wide_integer_b2n.cpp`](https://github.com/ckormanyos/wide-decimal/blob/main/test/test_mixed_wide_decimal_wide_integer_b2n.cpp).\nIt is included in the\n[test folder](https://github.com/ckormanyos/wide-decimal/tree/main/test)\nand also included in continuous integration.\nThis test file involves computations and comparisons of Bernoulli numbers.\n\n### (TBD) C++20 `constexpr` support\n\n(TBD) See also [issue 291](https://github.com/ckormanyos/wide-decimal/issues/291).\nWhen using C++20 `decwide_t` supports compile-time\n`constexpr` construction and evaluation of results\nof binary arithmetic, comparison operators\nand various elementary functions.\n\n### Alternatives and limitations\n\nAlternative libraries for big float types include,\namong others, most notably\n[GMP](https://gmplib.org/)\nand\n[`Boost.Multiprecision`](https://www.boost.org/doc/libs/1_83_0/libs/multiprecision/doc/html/index.html).\n\nAt the moment, wide-decimal has a rather large number of\nso-called _guard_ _digits_. In addition, wide-decimal\ndoes not make use of rounding when performing multiplication\nor other common algebraic operations. The combined\nresult is that exact calculations such as those potentially\nneeded in some areas requiring pure, exact decimal calculations\nmay not work well with this library. In this sense, wide-decimal suffers\nfrom the same rounding limitations as the\n[`cpp_dec_float`](https://www.boost.org/doc/libs/1_83_0/libs/multiprecision/doc/html/boost_multiprecision/tut/floats/cpp_dec_float.html)\nclass known from\n[`Boost.Multiprecision`](https://www.boost.org/doc/libs/1_83_0/libs/multiprecision/doc/html/index.html).\n\n## References\n\nA original publications on [_valgrind_](https://valgrind.org)\nand its relation to memory errors can be found in [1] and [2].\n\n[1] Nicholas Nethercote and Julian Seward,\n_Valgrind:_ _A_ _Framework_ _for_ _Heavyweight_ _Dynamic_ _Binary_ _Instrumentation_,\nProceedings of ACM SIGPLAN 2007 Conference on Programming Language Design and Implementation (PLDI 2007),\nSan Diego, California, USA, June 2007.\n\n[2] Nicholas Nethercote and Julian Seward,\n_How_ _to_ _Shadow_ _Every_ _Byte_ _of_ _Memory_ _Used_ _by_ _a_ _Program_.\nProceedings of the Third International ACM SIGPLAN/SIGOPS Conference on Virtual Execution Environments (VEE 2007),\nSan Diego, California, USA, June 2007.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fckormanyos%2Fwide-decimal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fckormanyos%2Fwide-decimal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fckormanyos%2Fwide-decimal/lists"}