├── .clang-tidy ├── .gcov └── make │ ├── make_gcov_01_generic.gmk │ ├── make_gcov_02_files.gmk │ └── make_gcov_03_flags.gmk ├── .github ├── toolchains │ └── gcc.cmake └── workflows │ ├── CodeQL.yml │ ├── wide_decimal.yml │ ├── wide_decimal_codecov.yml │ └── wide_decimal_sonar.yml ├── .gitignore ├── .props └── Directory.Build.props ├── .tidy └── make │ ├── make_tidy_01_generic.gmk │ ├── make_tidy_02_files.gmk │ └── make_tidy_03_flags.gmk ├── CMakeLists.txt ├── LICENSE_1_0.txt ├── README.md ├── boost └── math │ └── bindings │ └── decwide_t.hpp ├── codecov.yml ├── examples ├── CMakeLists.txt ├── example000_multiply_nines.cpp ├── example000a_multiply_pi_squared.cpp ├── example001_roots_sqrt.cpp ├── example001a_roots_seventh.cpp ├── example001b_roots_almost_integer.cpp ├── example001c_roots_sqrt_limb08.cpp ├── example001d_pow2_from_list.cpp ├── example001e_algebra_and_constexpr.cpp ├── example002_pi.cpp ├── example002a_pi_small_limb.cpp ├── example002b_pi_100k.cpp ├── example002c_pi_quintic.cpp ├── example002d_pi_limb08.cpp ├── example003_zeta.cpp ├── example004_bessel_recur.cpp ├── example005_polylog_series.cpp ├── example006_logarithm.cpp ├── example007_catalan_series.cpp ├── example008_bernoulli_tgamma.cpp ├── example009_boost_math_standalone.cpp ├── example009a_boost_math_standalone.cpp ├── example009b_boost_math_standalone.cpp ├── example010_hypergeometric_2f1.cpp ├── example010a_hypergeometric_1f1.cpp ├── example011_trig_trapezoid_integral.cpp ├── example012_rational_floor_ceil.cpp ├── example013_embeddable_sqrt.cpp ├── example013a_embeddable_agm.cpp └── example_decwide_t.h ├── math ├── constants │ └── constants_pi_control_for_decwide_t.h └── wide_decimal │ ├── decwide_t.h │ ├── decwide_t_detail.h │ ├── decwide_t_detail_fft.h │ ├── decwide_t_detail_namespace.h │ └── decwide_t_detail_ops.h ├── mcal_lcd ├── mcal_lcd_base.h ├── mcal_lcd_console.h └── mcal_lcd_generic_st7066.h ├── sonar-project.properties ├── target ├── build │ └── test_examples_emulator.gdb └── micros │ └── stm32f429 │ └── make │ ├── single │ └── crt.cpp │ └── stm32f429.ld ├── test ├── CMakeLists.txt ├── coverity.c ├── independent_algebra_test_decwide_t.h ├── independent_algebra_test_decwide_t_base.h ├── independent_algebra_test_decwide_t_boost_cpp.h ├── independent_algebra_test_decwide_t_constants.h ├── independent_algebra_test_decwide_t_wide_decimal.h ├── parallel_for.h ├── stopwatch.h ├── test.cpp ├── test_decwide_t_algebra.cpp ├── test_decwide_t_algebra.h ├── test_decwide_t_algebra_edge.cpp ├── test_decwide_t_examples.cpp ├── test_decwide_t_examples.h ├── test_high_precision_exp.cpp ├── test_high_precision_log.cpp └── test_mixed_wide_decimal_wide_integer_b2n.cpp ├── util ├── memory │ └── util_n_slot_array_allocator.h ├── stdcpp │ └── stdcpp_patch.cpp └── utility │ ├── util_baselexical_cast.h │ ├── util_dynamic_array.h │ ├── util_noncopyable.h │ └── util_pseudorandom_time_point_seed.h ├── wide_decimal.sln ├── wide_decimal.vcxproj ├── wide_decimal.vcxproj.filters ├── wide_decimal_vs2022.sln ├── wide_decimal_vs2022.vcxproj └── wide_decimal_vs2022.vcxproj.filters /.gcov/make/make_gcov_01_generic.gmk: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # Copyright Christopher Kormanyos 2022 - 2024. 3 | # Distributed under the Boost Software License, 4 | # Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | # or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | # ------------------------------------------------------------------------------ 7 | 8 | PATH_MAKE = $(CURDIR) 9 | PATH_PRJ = $(PATH_MAKE)/../.. 10 | PATH_SRC = $(PATH_PRJ) 11 | PATH_BIN = $(PATH_MAKE)/bin 12 | PATH_ERR = $(PATH_MAKE)/err 13 | PATH_OBJ = $(PATH_MAKE)/obj 14 | 15 | CAT = cat 16 | GNUECHO = echo 17 | LS = ls 18 | MKDIR = mkdir 19 | GCOV = gcov 20 | LCOV = lcov 21 | GENHTML = genhtml 22 | RM = rm 23 | SED = sed 24 | 25 | include make_gcov_02_files.gmk 26 | include make_gcov_03_flags.gmk 27 | 28 | FILES_ALL = $(FILES_PRJ) 29 | FILES_O = $(addprefix $(PATH_OBJ)/, $(notdir $(addsuffix .o, $(FILES_ALL)))) 30 | FILES_GCOV = $(addprefix $(PATH_OBJ)/, $(notdir $(addsuffix .gcov, $(FILES_ALL)))) 31 | 32 | # ------------------------------------------------------------------------------ 33 | # VPATH definition: VPATH is required for make to find the source files. 34 | # ------------------------------------------------------------------------------ 35 | VPATH := $(sort $(dir $(FILES_ALL))) 36 | 37 | 38 | # ------------------------------------------------------------------------------ 39 | # Executable file: 40 | # ------------------------------------------------------------------------------ 41 | 42 | .PHONY: $(PATH_BIN)/wide_decimal.exe 43 | $(PATH_BIN)/wide_decimal.exe: $(FILES_O) 44 | # Link coverage-instrumented executable 45 | @$(GNUECHO) +++ link object files to $(PATH_BIN)/wide_decimal.exe 46 | @$(CC) -x none $(CXXFLAGS) $(FILES_O) -o $(PATH_BIN)/wide_decimal.exe 47 | @$(GNUECHO) 48 | 49 | 50 | # ------------------------------------------------------------------------------ 51 | # Main dependency: 52 | # Compile all files and link them. 53 | # Run gcov and get results. 54 | # (See also https://github.com/codecov/example-cpp11-cmake) 55 | # ------------------------------------------------------------------------------ 56 | 57 | .PHONY: gcov 58 | gcov: $(PATH_BIN)/wide_decimal.exe 59 | # Obtain results 60 | @$(GNUECHO) +++ execute $(PATH_BIN)/wide_decimal.exe 61 | @$(PATH_BIN)/wide_decimal.exe 62 | @$(GNUECHO) 63 | @$(GNUECHO) +++ running gcov 64 | @$(GCOV) $(GCOV_FLAGS) $(addsuffix .cpp,$(FILES_PRJ)) 65 | @$(GNUECHO) 66 | @$(GNUECHO) +++ running lcov 67 | @$(LCOV) $(LCOV_BRANCH) -c --directory obj --output-file coverage_unfiltered.info 68 | @$(LCOV) $(LCOV_BRANCH) --ignore-errors unused --remove coverage_unfiltered.info $(LCOV_REMOVES) --output-file coverage.info 69 | @$(GNUECHO) 70 | @$(GNUECHO) +++ running genhtml 71 | @$(GENHTML) coverage.info $(LCOV_BRANCH) --demangle-cpp --output-directory $(PATH_BIN)/report 72 | @$(GNUECHO) 73 | 74 | # ------------------------------------------------------------------------------ 75 | # Clean temporary files. 76 | # ------------------------------------------------------------------------------ 77 | 78 | .PHONY: clean 79 | clean: 80 | # creating output directories 81 | @$(GNUECHO) +++ cleaning output directories 82 | @-$(RM) -rf $(PATH_BIN)* || uname -r 83 | @-$(RM) -rf $(PATH_ERR)* || uname -r 84 | @-$(RM) -rf $(PATH_OBJ)* || uname -r 85 | @-$(RM) -f *.gcov || uname -r 86 | @-$(RM) -f coverage* || uname -r 87 | @$(GNUECHO) 88 | 89 | 90 | # ------------------------------------------------------------------------------ 91 | # Prepare the gcov build. 92 | # ------------------------------------------------------------------------------ 93 | 94 | .PHONY: prepare 95 | prepare: clean 96 | @$(GNUECHO) +++ creating output directories 97 | @-$(MKDIR) -p $(PATH_BIN) 98 | @-$(MKDIR) -p $(PATH_ERR) 99 | @-$(MKDIR) -p $(PATH_OBJ) 100 | @$(GNUECHO) 101 | @$(GNUECHO) +++ print gcov version 102 | @$(GCOV) --version 103 | @$(GNUECHO) 104 | @$(GNUECHO) +++ print include paths 105 | @$(GNUECHO) $(C_INCLUDES) 106 | @$(GNUECHO) 107 | 108 | # ------------------------------------------------------------------------------ 109 | # pattern rule for compilation of cpp-files 110 | # ------------------------------------------------------------------------------ 111 | $(PATH_OBJ)/%.o : %.cpp 112 | @-$(GNUECHO) +++ compiling: $(notdir $<) to $(notdir $(PATH_OBJ)/$(basename $(@F)).o) 113 | @-$(CC) $(CXXFLAGS) -x c++ -c $(C_INCLUDES) $(C_DEFINES) $< -o $(PATH_OBJ)/$(basename $(@F)).o 2> $(PATH_ERR)/$(basename $(@F)).err 114 | @-$(SED) -e 's|.h:\([0-9]*\),|.h(\1) :|' -e 's|:\([0-9]*\):|(\1) :|' $(PATH_ERR)/$(basename $(@F)).err 115 | -------------------------------------------------------------------------------- /.gcov/make/make_gcov_02_files.gmk: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # Copyright Christopher Kormanyos 2022. 3 | # Distributed under the Boost Software License, 4 | # Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | # or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | # ------------------------------------------------------------------------------ 7 | 8 | FILES_PRJ = $(PATH_SRC)/test/test \ 9 | $(PATH_SRC)/test/test_decwide_t_algebra \ 10 | $(PATH_SRC)/test/test_decwide_t_algebra_edge \ 11 | $(PATH_SRC)/test/test_decwide_t_examples \ 12 | $(PATH_SRC)/examples/example000a_multiply_pi_squared \ 13 | $(PATH_SRC)/examples/example000_multiply_nines \ 14 | $(PATH_SRC)/examples/example001_roots_sqrt \ 15 | $(PATH_SRC)/examples/example001a_roots_seventh \ 16 | $(PATH_SRC)/examples/example001b_roots_almost_integer \ 17 | $(PATH_SRC)/examples/example001c_roots_sqrt_limb08 \ 18 | $(PATH_SRC)/examples/example001d_pow2_from_list \ 19 | $(PATH_SRC)/examples/example001e_algebra_and_constexpr \ 20 | $(PATH_SRC)/examples/example002b_pi_100k \ 21 | $(PATH_SRC)/examples/example003_zeta \ 22 | $(PATH_SRC)/examples/example004_bessel_recur \ 23 | $(PATH_SRC)/examples/example005_polylog_series \ 24 | $(PATH_SRC)/examples/example009_boost_math_standalone \ 25 | $(PATH_SRC)/examples/example009a_boost_math_standalone \ 26 | $(PATH_SRC)/examples/example009b_boost_math_standalone \ 27 | $(PATH_SRC)/examples/example010_hypergeometric_2f1 \ 28 | $(PATH_SRC)/examples/example010a_hypergeometric_1f1 \ 29 | $(PATH_SRC)/examples/example011_trig_trapezoid_integral \ 30 | $(PATH_SRC)/examples/example012_rational_floor_ceil \ 31 | $(PATH_SRC)/examples/example013_embeddable_sqrt \ 32 | $(PATH_SRC)/examples/example013a_embeddable_agm 33 | -------------------------------------------------------------------------------- /.gcov/make/make_gcov_03_flags.gmk: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # Copyright Christopher Kormanyos 2022 - 2025. 3 | # Distributed under the Boost Software License, 4 | # Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | # or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | # ------------------------------------------------------------------------------ 7 | 8 | BOOST_ROOT_FOR_GCOV = /mnt/c/boost/boost_1_82_0 9 | CC = g++ 10 | STD = c++20 11 | ALL_COV = 0 12 | 13 | ifneq ($(MY_BOOST_ROOT),) 14 | BOOST_ROOT_FOR_GCOV := $(MY_BOOST_ROOT) 15 | endif 16 | 17 | ifneq ($(MY_CC),) 18 | CC := $(MY_CC) 19 | endif 20 | 21 | ifneq ($(MY_STD),) 22 | STD := $(MY_STD) 23 | endif 24 | 25 | ifneq ($(MY_STD),) 26 | STD := $(MY_STD) 27 | endif 28 | 29 | ifneq ($(MY_ALL_COV),) 30 | ALL_COV := $(MY_ALL_COV) 31 | endif 32 | 33 | CXXFLAGS = -march=native \ 34 | -mtune=native \ 35 | -O2 \ 36 | -Wall \ 37 | -Wextra \ 38 | -Wconversion \ 39 | -Wsign-conversion \ 40 | -std=$(STD) \ 41 | -pthread \ 42 | -lpthread \ 43 | -fno-inline-functions \ 44 | -fprofile-arcs \ 45 | -ftest-coverage 46 | 47 | C_DEFINES = WIDE_DECIMAL_HAS_COVERAGE 48 | 49 | C_INCLUDES = $(PATH_SRC) \ 50 | $(BOOST_ROOT_FOR_GCOV) 51 | 52 | C_DEFINES :=$(addprefix -D,$(C_DEFINES)) 53 | C_INCLUDES :=$(addprefix -I,$(C_INCLUDES)) 54 | 55 | GCOV_FLAGS = --object-directory obj \ 56 | --demangled-names 57 | 58 | 59 | # ------------------------------------------------------------------------------ 60 | # All gcov flags: The GCOV_FLAGS below are equivalent to -abcfu 61 | # ------------------------------------------------------------------------------ 62 | 63 | ifneq ($(ALL_COV),0) 64 | GCOV_FLAGS := $(GCOV_FLAGS) \ 65 | --all-blocks \ 66 | --branch-counts \ 67 | --branch-probabilities \ 68 | --function-summaries \ 69 | --unconditional-branches 70 | endif 71 | 72 | LCOV_BRANCH = 73 | 74 | ifneq ($(ALL_COV),0) 75 | LCOV_BRANCH := --rc lcov_branch_coverage=1 76 | endif 77 | 78 | LCOV_REMOVES = '/usr/*' \ 79 | '*boost/*' \ 80 | '*mcal_lcd/*' \ 81 | '*util/*' 82 | -------------------------------------------------------------------------------- /.github/toolchains/gcc.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_CXX_FLAGS_INIT "-Wall -Wextra -Wconversion -Wsign-conversion -Wshadow -Wno-psabi -Werror") 2 | -------------------------------------------------------------------------------- /.github/workflows/CodeQL.yml: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # Copyright Christopher Kormanyos 2022 - 2025. 3 | # Distributed under the Boost Software License, 4 | # Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | # or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | # ------------------------------------------------------------------------------ 7 | 8 | name: CodeQL 9 | on: 10 | push: 11 | branches: 12 | - '**' 13 | pull_request: 14 | types: [opened, synchronize, reopened] 15 | jobs: 16 | analyze: 17 | name: Analyze 18 | runs-on: ubuntu-latest 19 | permissions: 20 | actions: read 21 | contents: read 22 | security-events: write 23 | strategy: 24 | fail-fast: false 25 | matrix: 26 | language: [ cpp ] 27 | 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@v4 31 | 32 | - name: clone-submods-bootstrap-headers-boost-develop 33 | run: | 34 | git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root 35 | cd ../boost-root 36 | git submodule update --init tools 37 | git submodule update --init libs/config 38 | git submodule update --init libs/math 39 | git submodule update --init libs/multiprecision 40 | ./bootstrap.sh 41 | ./b2 headers 42 | 43 | - name: Configure (cpp) 44 | if: ${{ matrix.language == 'cpp' }} 45 | run: echo configure_command_empty 46 | 47 | - name: Initialize CodeQL 48 | uses: github/codeql-action/init@v3 49 | with: 50 | languages: ${{ matrix.language }} 51 | queries: +security-and-quality 52 | 53 | - name: Build cpp 54 | if: ${{ matrix.language == 'cpp' }} 55 | run: | 56 | echo 'build application on the command line' 57 | g++ -fno-exceptions -fno-rtti -finline-functions -m64 -O3 -Werror -Wall -Wextra -Wconversion -Wsign-conversion -Wshadow -Wunused-parameter -Wuninitialized -Wunreachable-code -Winit-self -Wzero-as-null-pointer-constant -std=c++20 -I. -I../boost-root -pthread -lpthread test/test.cpp test/test_decwide_t_algebra.cpp test/test_decwide_t_algebra_edge.cpp test/test_decwide_t_examples.cpp examples/example000a_multiply_pi_squared.cpp examples/example000_multiply_nines.cpp examples/example001_roots_sqrt.cpp examples/example001a_roots_seventh.cpp examples/example001b_roots_almost_integer.cpp examples/example001c_roots_sqrt_limb08.cpp examples/example001d_pow2_from_list.cpp examples/example001e_algebra_and_constexpr.cpp examples/example002_pi.cpp examples/example002a_pi_small_limb.cpp examples/example002b_pi_100k.cpp examples/example002c_pi_quintic.cpp examples/example002d_pi_limb08.cpp examples/example003_zeta.cpp examples/example004_bessel_recur.cpp examples/example005_polylog_series.cpp examples/example006_logarithm.cpp examples/example007_catalan_series.cpp examples/example008_bernoulli_tgamma.cpp examples/example009_boost_math_standalone.cpp examples/example009a_boost_math_standalone.cpp examples/example009b_boost_math_standalone.cpp examples/example010_hypergeometric_2f1.cpp examples/example010a_hypergeometric_1f1.cpp examples/example011_trig_trapezoid_integral.cpp examples/example012_rational_floor_ceil.cpp examples/example013_embeddable_sqrt.cpp examples/example013a_embeddable_agm.cpp -o wide_decimal.exe 58 | - name: Perform CodeQL Analysis 59 | uses: github/codeql-action/analyze@v3 60 | with: 61 | category: "/language:${{ matrix.language }}" 62 | -------------------------------------------------------------------------------- /.github/workflows/wide_decimal_codecov.yml: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # Copyright Christopher Kormanyos 2022 - 2025. 3 | # Distributed under the Boost Software License, 4 | # Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | # or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | # ------------------------------------------------------------------------------ 7 | 8 | name: wide_decimal_codecov 9 | on: 10 | push: 11 | branches: 12 | - main 13 | pull_request: 14 | types: [opened, synchronize, reopened] 15 | jobs: 16 | gnumake-gcc-gcov-native: 17 | runs-on: ubuntu-latest 18 | defaults: 19 | run: 20 | shell: bash 21 | strategy: 22 | fail-fast: false 23 | matrix: 24 | standard: [ c++20 ] 25 | compiler: [ g++ ] 26 | steps: 27 | - uses: actions/checkout@v4 28 | with: 29 | fetch-depth: '0' 30 | - name: update-tools 31 | run: sudo apt install lcov 32 | - name: clone-submods-bootstrap-headers-boost-develop 33 | run: | 34 | git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root 35 | cd ../boost-root 36 | git submodule update --init tools 37 | git submodule update --init libs/config 38 | git submodule update --init libs/math 39 | git submodule update --init libs/multiprecision 40 | ./bootstrap.sh 41 | ./b2 headers 42 | - name: gnumake-gcc-gcov-native 43 | run: | 44 | grep BOOST_VERSION ../boost-root/boost/version.hpp 45 | cd .gcov/make 46 | echo "build and run gcov/lcov/genhtml" 47 | echo "make prepare -f make_gcov_01_generic.gmk MY_ALL_COV=0 MY_BOOST_ROOT=../../../boost-root MY_CC=${{ matrix.compiler }} MY_STD=${{ matrix.standard }}" 48 | echo 49 | make prepare -f make_gcov_01_generic.gmk MY_ALL_COV=0 MY_BOOST_ROOT=../../../boost-root MY_CC=${{ matrix.compiler }} MY_STD=${{ matrix.standard }} 50 | echo 51 | echo "make gcov -f make_gcov_01_generic.gmk --jobs=12 MY_ALL_COV=0 MY_BOOST_ROOT=../../../boost-root MY_CC=${{ matrix.compiler }} MY_STD=${{ matrix.standard }}" 52 | echo 53 | make gcov -f make_gcov_01_generic.gmk --jobs=12 MY_ALL_COV=0 MY_BOOST_ROOT=../../../boost-root MY_CC=${{ matrix.compiler }} MY_STD=${{ matrix.standard }} 54 | echo 55 | echo "return to wide-decimal root directory" 56 | cd ../.. 57 | - name: upload-codecov 58 | uses: codecov/codecov-action@v4 59 | with: 60 | plugin: gcov 61 | file: ${{ runner.workspace }}/wide-decimal/.gcov/make/coverage.info 62 | token: ${{ secrets.CODECOV_TOKEN }} 63 | fail_ci_if_error: true 64 | verbose: false 65 | -------------------------------------------------------------------------------- /.github/workflows/wide_decimal_sonar.yml: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # Copyright Christopher Kormanyos 2022 - 2025. 3 | # Distributed under the Boost Software License, 4 | # Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | # or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | # ------------------------------------------------------------------------------ 7 | 8 | name: wide_decimal_sonar 9 | on: 10 | push: 11 | branches: 12 | - main 13 | pull_request: 14 | types: [opened, synchronize, reopened] 15 | jobs: 16 | build: 17 | name: sonar-gcc-native 18 | runs-on: ubuntu-latest 19 | env: 20 | SONAR_SCANNER_VERSION: 5.0.1.3006 21 | SONAR_SERVER_URL: "https://sonarcloud.io" 22 | BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed 23 | steps: 24 | - uses: actions/checkout@v4 25 | with: 26 | fetch-depth: 0 27 | - name: clone-submods-bootstrap-headers-boost-develop 28 | run: | 29 | git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root 30 | cd ../boost-root 31 | git submodule update --init tools 32 | git submodule update --init libs/config 33 | git submodule update --init libs/math 34 | git submodule update --init libs/multiprecision 35 | ./bootstrap.sh 36 | ./b2 headers 37 | - name: Set up JDK 17 38 | uses: actions/setup-java@v4 39 | with: 40 | distribution: 'temurin' 41 | java-version: '17' 42 | overwrite-settings: true 43 | - name: Download and set up sonar-scanner 44 | env: 45 | SONAR_SCANNER_DOWNLOAD_URL: https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${{ env.SONAR_SCANNER_VERSION }}-linux.zip 46 | run: | 47 | mkdir -p $HOME/.sonar 48 | curl -sSLo $HOME/.sonar/sonar-scanner.zip ${{ env.SONAR_SCANNER_DOWNLOAD_URL }} 49 | unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/ 50 | echo "$HOME/.sonar/sonar-scanner-${{ env.SONAR_SCANNER_VERSION }}-linux/bin" >> $GITHUB_PATH 51 | - name: Download and set up build-wrapper 52 | env: 53 | BUILD_WRAPPER_DOWNLOAD_URL: ${{ env.SONAR_SERVER_URL }}/static/cpp/build-wrapper-linux-x86.zip 54 | run: | 55 | curl -sSLo $HOME/.sonar/build-wrapper-linux-x86.zip ${{ env.BUILD_WRAPPER_DOWNLOAD_URL }} 56 | unzip -o $HOME/.sonar/build-wrapper-linux-x86.zip -d $HOME/.sonar/ 57 | echo "$HOME/.sonar/build-wrapper-linux-x86" >> $GITHUB_PATH 58 | - name: Run build-wrapper 59 | run: | 60 | java -version 61 | build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} g++ -finline-functions -finline-limit=32 -m64 -O3 -Werror -Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wno-cast-function-type -std=c++20 -DWIDE_DECIMAL_NAMESPACE=ckormanyos -I. -I../boost-root -pthread -lpthread test/test.cpp test/test_decwide_t_algebra.cpp test/test_decwide_t_algebra_edge.cpp test/test_decwide_t_examples.cpp examples/example000a_multiply_pi_squared.cpp examples/example000_multiply_nines.cpp examples/example001_roots_sqrt.cpp examples/example001a_roots_seventh.cpp examples/example001b_roots_almost_integer.cpp examples/example001c_roots_sqrt_limb08.cpp examples/example001d_pow2_from_list.cpp examples/example002_pi.cpp examples/example001e_algebra_and_constexpr.cpp examples/example002a_pi_small_limb.cpp examples/example002b_pi_100k.cpp examples/example002c_pi_quintic.cpp examples/example002d_pi_limb08.cpp examples/example003_zeta.cpp examples/example004_bessel_recur.cpp examples/example005_polylog_series.cpp examples/example006_logarithm.cpp examples/example007_catalan_series.cpp examples/example008_bernoulli_tgamma.cpp examples/example009_boost_math_standalone.cpp examples/example009a_boost_math_standalone.cpp examples/example009b_boost_math_standalone.cpp examples/example010_hypergeometric_2f1.cpp examples/example010a_hypergeometric_1f1.cpp examples/example011_trig_trapezoid_integral.cpp examples/example012_rational_floor_ceil.cpp examples/example013_embeddable_sqrt.cpp examples/example013a_embeddable_agm.cpp -o wide_decimal.exe 62 | - name: Run sonar-scanner 63 | env: 64 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 65 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 66 | run: | 67 | java -version 68 | sonar-scanner --define sonar.host.url="${{ env.SONAR_SERVER_URL }}" --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" 69 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | wide-decimal-release-x64/ 2 | .vs/ 3 | wide-decimal-debug-x64/ 4 | wide_decimal.vcxproj.user 5 | wide-decimal-debug-x86/ 6 | wide-decimal-release-x86/ 7 | wide_decimal_vs2022.vcxproj.user 8 | -------------------------------------------------------------------------------- /.props/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | 5 | 6 | -------------------------------------------------------------------------------- /.tidy/make/make_tidy_01_generic.gmk: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # Copyright Christopher Kormanyos 2022 - 2023. 3 | # Distributed under the Boost Software License, 4 | # Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | # or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | # ------------------------------------------------------------------------------ 7 | 8 | PATH_MAKE = $(CURDIR) 9 | PATH_PRJ = $(PATH_MAKE)/../.. 10 | PATH_SRC = $(PATH_PRJ) 11 | PATH_TMP = $(PATH_MAKE)/tmp 12 | PATH_ERR = $(PATH_MAKE)/err 13 | 14 | CAT = cat 15 | GNUECHO = echo 16 | LS = ls 17 | MKDIR = mkdir 18 | TIDY = clang-tidy 19 | RM = rm 20 | SED = sed 21 | 22 | include make_tidy_02_files.gmk 23 | include make_tidy_03_flags.gmk 24 | 25 | FILES_ALL = $(FILES_PRJ) 26 | FILES_TIDY_TXT = $(addprefix $(PATH_TMP)/, $(notdir $(addsuffix .tidy_txt, $(FILES_ALL)))) 27 | 28 | # ------------------------------------------------------------------------------ 29 | # VPATH definition: VPATH is required for make to find the source files. 30 | # ------------------------------------------------------------------------------ 31 | VPATH := $(sort $(dir $(FILES_ALL))) 32 | 33 | # ------------------------------------------------------------------------------ 34 | # Main dependency: Run clang-tidy on all files and tidy tidy results. 35 | # ------------------------------------------------------------------------------ 36 | 37 | .PHONY: tidy 38 | tidy: $(FILES_TIDY_TXT) 39 | # Summarize tidy results 40 | @$(GNUECHO) +++ summarize clang-tidy results 41 | @$(GNUECHO) +++ concatenate $(PATH_TMP)/*.tidy_txt to $(PATH_TMP)/all.tidy_txt 42 | @$(CAT) $(PATH_TMP)/*.tidy_txt > $(PATH_TMP)/all.tidy_txt 43 | @$(GNUECHO) 44 | @$(GNUECHO) +++ verify existence of $(PATH_TMP)/all.tidy_txt 45 | @$(LS) -la $(PATH_TMP)/all.tidy_txt 46 | @$(GNUECHO) 47 | @$(GNUECHO) +++ print summary of tidy from $(PATH_TMP)/all.tidy_txt: 48 | @-$(SED) -n l $(PATH_TMP)/all.tidy_txt 49 | @$(GNUECHO) 50 | 51 | 52 | # ------------------------------------------------------------------------------ 53 | # Clean temporary files. 54 | # ------------------------------------------------------------------------------ 55 | 56 | .PHONY: prepare 57 | prepare: 58 | # creating output directories 59 | @$(GNUECHO) +++ creating output directories 60 | @-$(MKDIR) -p $(PATH_ERR) 61 | @-$(MKDIR) -p $(PATH_TMP) 62 | @$(GNUECHO) 63 | @$(GNUECHO) +++ cleaning output directories 64 | @-$(RM) -rf $(PATH_ERR)/*.tidy_err 65 | @-$(RM) -rf $(PATH_TMP)/*.tidy_txt 66 | @$(GNUECHO) 67 | @$(GNUECHO) +++ print clang-tidy version 68 | @$(TIDY) --version 69 | @$(GNUECHO) 70 | @$(GNUECHO) +++ print include paths 71 | @$(GNUECHO) $(C_INCLUDES) 72 | @$(GNUECHO) 73 | 74 | # ------------------------------------------------------------------------------ 75 | # pattern rule for clang-tidy analysis of cpp-files 76 | # ------------------------------------------------------------------------------ 77 | $(PATH_TMP)/%.tidy_txt : %.cpp 78 | @-$(GNUECHO) +++ tidying: $< 79 | @-$(TIDY) $(TIDY_FLAGS) $< -- $(CXX_FLAGS) $(C_INCLUDES) $(C_DEFINES) > $(PATH_TMP)/$(basename $(@F)).tidy_txt 2> $(PATH_ERR)/$(basename $(@F)).tidy_err 80 | @-$(GNUECHO) 81 | @-$(GNUECHO) +++ print $(PATH_ERR)/$(basename $(@F)).tidy_err 82 | @-$(SED) -n l $(PATH_ERR)/$(basename $(@F)).tidy_err 83 | @-$(GNUECHO) 84 | -------------------------------------------------------------------------------- /.tidy/make/make_tidy_02_files.gmk: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # Copyright Christopher Kormanyos 2022 - 2023. 3 | # Distributed under the Boost Software License, 4 | # Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | # or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | # ------------------------------------------------------------------------------ 7 | 8 | FILES_PRJ = $(PATH_SRC)/test/test \ 9 | $(PATH_SRC)/test/test_decwide_t_algebra \ 10 | $(PATH_SRC)/test/test_decwide_t_algebra_edge \ 11 | $(PATH_SRC)/test/test_decwide_t_examples \ 12 | $(PATH_SRC)/examples/example000a_multiply_pi_squared \ 13 | $(PATH_SRC)/examples/example000_multiply_nines \ 14 | $(PATH_SRC)/examples/example001_roots_sqrt \ 15 | $(PATH_SRC)/examples/example001a_roots_seventh \ 16 | $(PATH_SRC)/examples/example001b_roots_almost_integer \ 17 | $(PATH_SRC)/examples/example001c_roots_sqrt_limb08 \ 18 | $(PATH_SRC)/examples/example001d_pow2_from_list \ 19 | $(PATH_SRC)/examples/example001e_algebra_and_constexpr \ 20 | $(PATH_SRC)/examples/example002_pi \ 21 | $(PATH_SRC)/examples/example002a_pi_small_limb \ 22 | $(PATH_SRC)/examples/example002b_pi_100k \ 23 | $(PATH_SRC)/examples/example002c_pi_quintic \ 24 | $(PATH_SRC)/examples/example002d_pi_limb08 \ 25 | $(PATH_SRC)/examples/example003_zeta \ 26 | $(PATH_SRC)/examples/example004_bessel_recur \ 27 | $(PATH_SRC)/examples/example005_polylog_series \ 28 | $(PATH_SRC)/examples/example006_logarithm \ 29 | $(PATH_SRC)/examples/example007_catalan_series \ 30 | $(PATH_SRC)/examples/example008_bernoulli_tgamma \ 31 | $(PATH_SRC)/examples/example009_boost_math_standalone \ 32 | $(PATH_SRC)/examples/example009a_boost_math_standalone \ 33 | $(PATH_SRC)/examples/example009b_boost_math_standalone \ 34 | $(PATH_SRC)/examples/example010_hypergeometric_2f1 \ 35 | $(PATH_SRC)/examples/example010a_hypergeometric_1f1 \ 36 | $(PATH_SRC)/examples/example011_trig_trapezoid_integral \ 37 | $(PATH_SRC)/examples/example012_rational_floor_ceil \ 38 | $(PATH_SRC)/examples/example013_embeddable_sqrt \ 39 | $(PATH_SRC)/examples/example013a_embeddable_agm 40 | -------------------------------------------------------------------------------- /.tidy/make/make_tidy_03_flags.gmk: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # Copyright Christopher Kormanyos 2022 - 2025. 3 | # Distributed under the Boost Software License, 4 | # Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | # or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | # ------------------------------------------------------------------------------ 7 | 8 | BOOST_ROOT_FOR_TIDY = /mnt/c/boost/boost_1_87_0 9 | CC = clang++ 10 | STD = c++20 11 | 12 | ifneq ($(MY_BOOST_ROOT),) 13 | BOOST_ROOT_FOR_TIDY := $(MY_BOOST_ROOT) 14 | endif 15 | 16 | ifneq ($(MY_CC),) 17 | CC := $(MY_CC) 18 | endif 19 | 20 | ifneq ($(MY_STD),) 21 | STD := $(MY_STD) 22 | endif 23 | 24 | CXX_FLAGS = $(CC) \ 25 | -march=native \ 26 | -mtune=native \ 27 | -O3 \ 28 | -Wall \ 29 | -Wextra \ 30 | -Wconversion \ 31 | -Wsign-conversion \ 32 | -std=$(STD) 33 | 34 | C_DEFINES = 35 | 36 | C_INCLUDES = $(PATH_SRC) \ 37 | $(BOOST_ROOT_FOR_TIDY) 38 | 39 | C_DEFINES :=$(addprefix -D,$(C_DEFINES)) 40 | C_INCLUDES :=$(addprefix -I,$(C_INCLUDES)) 41 | 42 | 43 | TIDY_CHECKS = "*, \ 44 | -cert-dcl58-cpp, \ 45 | -cppcoreguidelines-rvalue-reference-param-not-moved, \ 46 | -cppcoreguidelines-avoid-do-while, \ 47 | -modernize-type-traits, \ 48 | -modernize-use-constraints, \ 49 | -misc-header-include-cycle, \ 50 | -misc-include-cleaner, \ 51 | -misc-const-correctness, \ 52 | -performance-avoid-endl, \ 53 | -portability-simd-intrinsics, \ 54 | -cppcoreguidelines-avoid-magic-numbers, \ 55 | -readability-avoid-nested-conditional-operator, \ 56 | -readability-identifier-length, \ 57 | -readability-redundant-casting, \ 58 | -readability-redundant-inline-specifier, \ 59 | -altera-struct-pack-align, \ 60 | -altera-unroll-loops, \ 61 | -fuchsia-*, \ 62 | -llvmlibc-*" 63 | 64 | TIDY_FLAGS = --extra-arg-before=--driver-mode=g++ \ 65 | --header-filter=decwide_t \ 66 | -warnings-as-errors=* \ 67 | -checks=$(TIDY_CHECKS) 68 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(wide-decimal) 2 | 3 | cmake_minimum_required(VERSION 3.16.3) 4 | 5 | find_package(Boost) 6 | if (Boost_FOUND) 7 | include(CTest) 8 | 9 | add_subdirectory("examples") 10 | add_subdirectory("test") 11 | endif() 12 | 13 | add_library(WideDecimal INTERFACE) 14 | target_compile_features(WideDecimal INTERFACE cxx_std_14) 15 | 16 | target_include_directories( 17 | WideDecimal SYSTEM INTERFACE 18 | $ 19 | $) 20 | 21 | install(TARGETS WideDecimal EXPORT WideDecimalTargets) 22 | 23 | install( 24 | FILES math/wide_decimal/decwide_t.h math/wide_decimal/decwide_t_detail.h 25 | math/wide_decimal/decwide_t_detail_fft.h math/wide_decimal/decwide_t_detail_namespace.h 26 | math/wide_decimal/decwide_t_detail_ops.h 27 | DESTINATION include/math/wide_decimal/) 28 | 29 | install( 30 | FILES math/constants/constants_pi_control_for_decwide_t.h 31 | DESTINATION include/math/constants/) 32 | 33 | install( 34 | FILES mcal_lcd/mcal_lcd_console.h mcal_lcd/mcal_lcd_base.h mcal_lcd/mcal_lcd_generic_st7066.h 35 | DESTINATION include/mcal_lcd/) 36 | 37 | install( 38 | FILES util/utility/util_baselexical_cast.h util/utility/util_dynamic_array.h 39 | util/utility/util_noncopyable.h 40 | DESTINATION include/util/utility/ 41 | ) 42 | 43 | install( 44 | FILES util/memory/util_n_slot_array_allocator.h 45 | DESTINATION include/util/memory/ 46 | ) 47 | 48 | install( 49 | FILES util/stdcpp/stdcpp_patch.cpp 50 | DESTINATION include/util/stdcpp/ 51 | ) 52 | 53 | install( 54 | FILES boost/math/bindings/decwide_t.hpp 55 | DESTINATION include/boost/math/bindings/ 56 | ) 57 | 58 | install(EXPORT WideDecimalTargets 59 | FILE WideDecimalConfig.cmake 60 | NAMESPACE WideDecimal:: 61 | DESTINATION lib/cmake/wide-decimal) 62 | -------------------------------------------------------------------------------- /LICENSE_1_0.txt: -------------------------------------------------------------------------------- 1 |  2 | Boost Software License - Version 1.0 - August 17th, 2003 3 | 4 | Permission is hereby granted, free of charge, to any person or organization 5 | obtaining a copy of the software and accompanying documentation covered by 6 | this license (the "Software") to use, reproduce, display, distribute, 7 | execute, and transmit the Software, and to prepare derivative works of the 8 | Software, and to permit third-parties to whom the Software is furnished to 9 | do so, all subject to the following: 10 | 11 | The copyright notices in the Software and this entire statement, including 12 | the above license grant, this restriction and the following disclaimer, 13 | must be included in all copies of the Software, in whole or in part, and 14 | all derivative works of the Software, unless such copies or derivative 15 | works are solely in the form of machine-executable object code generated by 16 | a source language processor. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 21 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 22 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 | DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | 4 | coverage: 5 | precision: 1 6 | round: up 7 | range: '50...100' 8 | status: 9 | project: 10 | default: # This can be anything, but it needs to exist as the name 11 | # basic settings 12 | target: 90% 13 | threshold: 3% 14 | if_ci_failed: error #success, failure, error, ignore 15 | only_pulls: false 16 | patch: 17 | default: 18 | target: 75% 19 | threshold: 25% 20 | 21 | parsers: 22 | gcov: 23 | branch_detection: 24 | conditional: no 25 | loop: no 26 | method: no 27 | macro: no 28 | 29 | comment: 30 | layout: 'reach,diff,flags,files,footer' 31 | behavior: default 32 | require_changes: no 33 | -------------------------------------------------------------------------------- /examples/example000_multiply_nines.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2022. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #if defined(WIDE_DECIMAL_NAMESPACE) 15 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example000_multiply_nines() -> bool 16 | #else 17 | auto ::math::wide_decimal::example000_multiply_nines() -> bool 18 | #endif 19 | { 20 | using local_limb_type = std::uint8_t; 21 | 22 | constexpr std::int32_t wide_decimal_digits10 = INT32_C(50); 23 | 24 | #if defined(WIDE_DECIMAL_NAMESPACE) 25 | using wide_decimal_type = 26 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t; 31 | #else 32 | using wide_decimal_type = 33 | ::math::wide_decimal::decwide_t; 38 | #endif 39 | 40 | const wide_decimal_type a 41 | { 42 | ( std::string("9.") 43 | + std::string(wide_decimal_digits10 - 1, '9')).c_str() 44 | }; 45 | 46 | const wide_decimal_type control 47 | { 48 | ( std::string("99.") 49 | + std::string(wide_decimal_digits10 - 3, '9') 50 | + std::string("8")).c_str() 51 | }; 52 | 53 | const wide_decimal_type result = (a * a); 54 | 55 | const wide_decimal_type closeness = fabs(1 - fabs(result / control)); 56 | 57 | const auto result_is_ok = (closeness < (std::numeric_limits::epsilon() * static_cast(UINT8_C(10)))); 58 | 59 | return result_is_ok; 60 | } 61 | 62 | // Enable this if you would like to activate this main() as a standalone example. 63 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE000_MULTIPLY_NINES) 64 | 65 | #include 66 | #include 67 | 68 | auto main() -> int 69 | { 70 | const auto result_is_ok = ::math::wide_decimal::example000_multiply_nines(); 71 | 72 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 73 | } 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /examples/example000a_multiply_pi_squared.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2022. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #if defined(WIDE_DECIMAL_NAMESPACE) 14 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example000a_multiply_pi_squared() -> bool 15 | #else 16 | auto ::math::wide_decimal::example000a_multiply_pi_squared() -> bool 17 | #endif 18 | { 19 | constexpr std::int32_t wide_decimal_digits10 = INT32_C(1001); 20 | 21 | #if defined(WIDE_DECIMAL_NAMESPACE) 22 | using float_type = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t; 23 | #else 24 | using float_type = ::math::wide_decimal::decwide_t; 25 | #endif 26 | 27 | const float_type my_pi 28 | { 29 | "3." 30 | "1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679" 31 | "8214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196" 32 | "4428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273" 33 | "7245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094" 34 | "3305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912" 35 | "9833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132" 36 | "0005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235" 37 | "4201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859" 38 | "5024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303" 39 | "5982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989" 40 | "38" 41 | }; 42 | 43 | const float_type pi_sq = my_pi * my_pi; 44 | 45 | const float_type control 46 | { 47 | "9." 48 | "8696044010893586188344909998761511353136994072407906264133493762200448224192052430017734037185522318" 49 | "2402591377402314407777234812203004672761061767798519766099039985620657563057150604123284032878086935" 50 | "2769342164939666571519044538735261779413820258260581693412515592048309818873270033076266671104358950" 51 | "8715041003257885365952763577528379226833187450864045463541250269737295669583342278581500063652270954" 52 | "7249085975607266926475277900528533645220666980826415896877105732788929174690154551006925443245703644" 53 | "9656172537928607606008145972589229232414240044295981361814413706777778194739658303170856632789570753" 54 | "4079917145231589263721144638282644328528037928503480952338995039685746094853460090177429322057990359" 55 | "1735782046575804193168682300219614689927042061429696346600579984035164213654304998453372173655724046" 56 | "3676848876261512299027059938010299446886181716260980130876530037060158369198676286005079936468322669" 57 | "7315683671755589711987529752963949163155394491954838770687211307898665755909865363656307636308806115" 58 | "01" 59 | }; 60 | 61 | const float_type ratio = pi_sq / control; 62 | 63 | const float_type closeness = fabs(1 - ratio); 64 | 65 | const auto result_is_ok = closeness < (std::numeric_limits::epsilon() * static_cast(UINT8_C(10))); 66 | 67 | return result_is_ok; 68 | } 69 | 70 | // Enable this if you would like to activate this main() as a standalone example. 71 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE000A_MULTIPLY_PI_SQUARED) 72 | 73 | #include 74 | #include 75 | 76 | auto main() -> int 77 | { 78 | const auto result_is_ok = ::math::wide_decimal::example000a_multiply_pi_squared(); 79 | 80 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 81 | } 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /examples/example001_roots_sqrt.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2022. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #if defined(WIDE_DECIMAL_NAMESPACE) 15 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example001_roots_sqrt() -> bool 16 | #else 17 | auto ::math::wide_decimal::example001_roots_sqrt() -> bool 18 | #endif 19 | { 20 | using local_limb_type = std::uint32_t; 21 | 22 | constexpr std::int32_t wide_decimal_digits10 = INT32_C(101); 23 | 24 | #if defined(WIDE_DECIMAL_NAMESPACE) 25 | constexpr std::int32_t local_elem_number = 26 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::detail::decwide_t_helper::elem_number; 27 | #else 28 | constexpr std::int32_t local_elem_number = 29 | ::math::wide_decimal::detail::decwide_t_helper::elem_number; 30 | #endif 31 | 32 | using local_allocator_type = util::n_slot_array_allocator; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 33 | 34 | #if defined(WIDE_DECIMAL_NAMESPACE) 35 | using dec101_t = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t; 40 | #else 41 | using dec101_t = ::math::wide_decimal::decwide_t; 46 | #endif 47 | 48 | const dec101_t s = sqrt(dec101_t(123456U) / 100); 49 | 50 | // N[Sqrt[123456/100], 111] 51 | // 35.1363060095963986639333846404180557597515182871693145281659761647177108954528909286350312191322209780537650946 52 | const dec101_t control 53 | ( 54 | "35.1363060095963986639333846404180557597515182871693145281659761647177108954528909286350312191322209780537650946" 55 | ); 56 | 57 | using std::fabs; 58 | 59 | const dec101_t closeness = fabs(1 - fabs(s / control)); 60 | 61 | const auto result_is_ok = (closeness < (std::numeric_limits::epsilon() * static_cast(UINT8_C(10)))); 62 | 63 | return result_is_ok; 64 | } 65 | 66 | // Enable this if you would like to activate this main() as a standalone example. 67 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE001_ROOTS_SQRT) 68 | 69 | #include 70 | #include 71 | 72 | auto main() -> int 73 | { 74 | const auto result_is_ok = ::math::wide_decimal::example001_roots_sqrt(); 75 | 76 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 77 | } 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /examples/example001a_roots_seventh.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2022. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #if defined(WIDE_DECIMAL_NAMESPACE) 14 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example001a_roots_seventh() -> bool 15 | #else 16 | auto ::math::wide_decimal::example001a_roots_seventh() -> bool 17 | #endif 18 | { 19 | #if defined(WIDE_DECIMAL_NAMESPACE) 20 | using dec101_t = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t(INT32_C(101)), std::uint32_t, void>; 21 | #else 22 | using dec101_t = ::math::wide_decimal::decwide_t(INT32_C(101)), std::uint32_t, void>; 23 | #endif 24 | 25 | const dec101_t r7 = rootn(dec101_t(123456U) / 100, 7); 26 | 27 | // N[(123456/100)^(1/7), 101] 28 | const dec101_t control 29 | { 30 | "2.7646782775741109196428393776807250048855576457486681034865195752391286191642449378095974978251349039" 31 | }; 32 | 33 | const dec101_t closeness = fabs(1 - fabs(r7 / control)); 34 | 35 | const auto result_is_ok = (closeness < (std::numeric_limits::epsilon() * static_cast(UINT8_C(10)))); 36 | 37 | return result_is_ok; 38 | } 39 | 40 | // Enable this if you would like to activate this main() as a standalone example. 41 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE001A_ROOTS_SEVENTH) 42 | 43 | #include 44 | #include 45 | 46 | auto main() -> int 47 | { 48 | const auto result_is_ok = ::math::wide_decimal::example001a_roots_seventh(); 49 | 50 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /examples/example001c_roots_sqrt_limb08.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2022. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #if defined(WIDE_DECIMAL_NAMESPACE) 15 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example001c_roots_sqrt_limb08() -> bool 16 | #else 17 | auto ::math::wide_decimal::example001c_roots_sqrt_limb08() -> bool 18 | #endif 19 | { 20 | using local_limb_type = std::uint8_t; 21 | 22 | constexpr std::int32_t wide_decimal_digits10 = INT32_C(1001); 23 | 24 | #if defined(WIDE_DECIMAL_NAMESPACE) 25 | constexpr std::int32_t local_elem_number = 26 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::detail::decwide_t_helper::elem_number; 27 | #else 28 | constexpr std::int32_t local_elem_number = 29 | ::math::wide_decimal::detail::decwide_t_helper::elem_number; 30 | #endif 31 | 32 | using local_allocator_type = util::n_slot_array_allocator; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 33 | 34 | #if defined(WIDE_DECIMAL_NAMESPACE) 35 | using dec101_t = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t; 40 | #else 41 | using dec101_t = ::math::wide_decimal::decwide_t; 46 | #endif 47 | 48 | const dec101_t s = sqrt(dec101_t(123456U) / 100); 49 | 50 | // N[Sqrt[123456/100], 101] 51 | const dec101_t control 52 | { 53 | "35." 54 | "1363060095963986639333846404180557597515182871693145281659761647177108954528909286350312191322209780" 55 | "5376509458612063848933362936036902894775479901536869612529882911098089704769067860255038125371130309" 56 | "7376476849395654679954112865931807823733220588199157932745047491503972076995050120516343736839242915" 57 | "4369007794430771608198640304436146239417896958061796560916877079311161817597168274846189811523239304" 58 | "2642889928069497444785243273980837009588523459749479302460885283605547111733236159315706029981137688" 59 | "8991852788360379505972332110711893204646089148658294227900893783477868274739342763981945636625577086" 60 | "9672247622850251850193579637713379900799611913793836060987736238490134981026465200443718457075956217" 61 | "6553633317360948823009715346637345353199394836821376443690590142905598515413670933316255259528441000" 62 | "3594505770419599844025682991191472179397790550351313826295588062939873150278838895995158537860944019" 63 | "1539544776173919125406452516595735890842387785268673310183794490210307597283027587373720292917113922" 64 | "51" 65 | }; 66 | 67 | const dec101_t closeness = fabs(1 - fabs(s / control)); 68 | 69 | const auto result_is_ok = (closeness < (std::numeric_limits::epsilon() * static_cast(UINT8_C(10)))); 70 | 71 | return result_is_ok; 72 | } 73 | 74 | // Enable this if you would like to activate this main() as a standalone example. 75 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE001C_ROOTS_SQRT_LIMB08) 76 | 77 | #include 78 | #include 79 | 80 | auto main() -> int 81 | { 82 | const auto result_is_ok = ::math::wide_decimal::example001c_roots_sqrt_limb08(); 83 | 84 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 85 | } 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /examples/example001e_algebra_and_constexpr.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2023. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #if defined(WIDE_DECIMAL_NAMESPACE) 14 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example001e_algebra_and_constexpr() -> bool 15 | #else 16 | auto ::math::wide_decimal::example001e_algebra_and_constexpr() -> bool 17 | #endif 18 | { 19 | using local_limb_type = std::uint32_t; 20 | 21 | constexpr auto wide_decimal_digits10 = static_cast(INT32_C(100)); 22 | 23 | #if defined(WIDE_DECIMAL_NAMESPACE) 24 | using wide_decimal_type = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t; 25 | #else 26 | using wide_decimal_type = ::math::wide_decimal::decwide_t; 27 | #endif 28 | 29 | auto result_is_ok = true; 30 | 31 | const wide_decimal_type local_quarter_a(wide_decimal_type(static_cast(UINT8_C(25))) / static_cast(UINT8_C(100))); 32 | const wide_decimal_type local_quarter_b(static_cast(0.25L)); // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 33 | 34 | const auto result_construct_is_ok = (local_quarter_a == local_quarter_b); 35 | 36 | result_is_ok = (result_construct_is_ok && result_is_ok); 37 | 38 | return result_is_ok; 39 | } 40 | 41 | // Enable this if you would like to activate this main() as a standalone example. 42 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE001E_ALGEBRA_AND_CONSTEXPR) 43 | 44 | #include 45 | #include 46 | 47 | auto main() -> int 48 | { 49 | const auto result_is_ok = ::math::wide_decimal::example001e_algebra_and_constexpr(); 50 | 51 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /examples/example002_pi.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2024. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12)) 9 | #pragma GCC diagnostic push 10 | #pragma GCC diagnostic ignored "-Wstringop-overflow" 11 | #endif 12 | 13 | // Disable heavyweight features via macros for this example. 14 | #define WIDE_DECIMAL_DISABLE_IOSTREAM 15 | #define WIDE_DECIMAL_DISABLE_DYNAMIC_MEMORY_ALLOCATION 16 | #define WIDE_DECIMAL_DISABLE_CONSTRUCT_FROM_STRING 17 | #define WIDE_DECIMAL_DISABLE_CACHED_CONSTANTS 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | namespace example002_pi 34 | { 35 | auto lcd0() -> mcal::lcd::lcd_base& 36 | { 37 | static mcal::lcd::lcd_console lc0; 38 | 39 | return lc0; 40 | } 41 | } // namespace example002_pi 42 | 43 | auto example002_pi_digits10_callback(const std::uint32_t d10) -> void 44 | { 45 | std::array(UINT32_C(10))> p_str = {{ '\0' }}; 46 | 47 | const char* p_end = util::baselexical_cast(d10, p_str.data(), p_str.data() + p_str.size()); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 48 | 49 | const auto len = static_cast(p_end - p_str.data()); 50 | 51 | example002_pi::lcd0().write(p_str.data(), len, 0U); 52 | } 53 | 54 | #if defined(WIDE_DECIMAL_NAMESPACE) 55 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example002_pi() -> bool 56 | #else 57 | auto ::math::wide_decimal::example002_pi() -> bool 58 | #endif 59 | { 60 | using local_limb_type = std::uint32_t; 61 | 62 | constexpr std::int32_t wide_decimal_digits10 = INT32_C(1000001); 63 | 64 | #if defined(WIDE_DECIMAL_NAMESPACE) 65 | constexpr std::int32_t local_elem_number = 66 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::detail::decwide_t_helper::elem_number; 67 | #else 68 | constexpr std::int32_t local_elem_number = 69 | ::math::wide_decimal::detail::decwide_t_helper::elem_number; 70 | #endif 71 | 72 | #if defined(WIDE_DECIMAL_NAMESPACE) 73 | constexpr std::int32_t local_elem_digits10 = 74 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::detail::decwide_t_helper::elem_digits10; 75 | #else 76 | constexpr std::int32_t local_elem_digits10 = 77 | ::math::wide_decimal::detail::decwide_t_helper::elem_digits10; 78 | #endif 79 | 80 | using local_allocator_type = util::n_slot_array_allocator; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 81 | 82 | #if defined(WIDE_DECIMAL_NAMESPACE) 83 | using local_wide_decimal_type = 84 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t; 85 | #else 86 | using local_wide_decimal_type = 87 | ::math::wide_decimal::decwide_t; 88 | #endif 89 | 90 | using stopwatch_type = concurrency::stopwatch; 91 | 92 | stopwatch_type my_stopwatch { }; 93 | 94 | #if defined(WIDE_DECIMAL_NAMESPACE) 95 | const local_wide_decimal_type my_pi = 96 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::pi(example002_pi_digits10_callback); 97 | #else 98 | const local_wide_decimal_type my_pi = 99 | ::math::wide_decimal::pi(example002_pi_digits10_callback); 100 | #endif 101 | 102 | const float execution_time { stopwatch_type::elapsed_time(my_stopwatch) }; 103 | 104 | { 105 | std::stringstream strm { }; 106 | 107 | strm << "Time example002_pi() : " 108 | << std::fixed 109 | << std::setprecision(1) 110 | << execution_time 111 | << "s" 112 | ; 113 | 114 | std::cout << strm.str() << std::endl; 115 | } 116 | 117 | #if defined(WIDE_DECIMAL_NAMESPACE) 118 | const auto head_is_ok = std::equal(my_pi.crepresentation().cbegin(), 119 | my_pi.crepresentation().cbegin() + WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_head_32.size(), 120 | WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_head_32.begin()); 121 | #else 122 | const auto head_is_ok = std::equal(my_pi.crepresentation().cbegin(), 123 | my_pi.crepresentation().cbegin() + ::math::constants::const_pi_control_head_32.size(), 124 | ::math::constants::const_pi_control_head_32.begin()); 125 | #endif 126 | 127 | using const_iterator_type = typename local_wide_decimal_type::representation_type::const_iterator; 128 | 129 | #if defined(WIDE_DECIMAL_NAMESPACE) 130 | const_iterator_type 131 | fi 132 | ( 133 | my_pi.crepresentation().cbegin() 134 | + static_cast 135 | ( 136 | static_cast(1UL + ((wide_decimal_digits10 - 1UL) / local_elem_digits10)) 137 | - static_cast(WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_tail_32_1000001.size()) 138 | ) 139 | ); 140 | #else 141 | const_iterator_type 142 | fi 143 | ( 144 | my_pi.crepresentation().cbegin() 145 | + static_cast 146 | ( 147 | static_cast(1UL + ((wide_decimal_digits10 - 1UL) / local_elem_digits10)) 148 | - static_cast(::math::constants::const_pi_control_tail_32_1000001.size()) 149 | ) 150 | ); 151 | #endif 152 | 153 | #if defined(WIDE_DECIMAL_NAMESPACE) 154 | const auto tail_is_ok = std::equal(fi, 155 | fi + WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_tail_32_1000001.size(), 156 | WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_tail_32_1000001.begin()); 157 | #else 158 | const auto tail_is_ok = std::equal(fi, 159 | fi + ::math::constants::const_pi_control_tail_32_1000001.size(), 160 | ::math::constants::const_pi_control_tail_32_1000001.begin()); 161 | #endif 162 | 163 | const auto result_is_ok = (head_is_ok && tail_is_ok); 164 | 165 | return result_is_ok; 166 | } 167 | 168 | // Enable this if you would like to activate this main() as a standalone example. 169 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE002_PI) 170 | 171 | #include 172 | #include 173 | 174 | auto main() -> int 175 | { 176 | const auto result_is_ok = ::math::wide_decimal::example002_pi(); 177 | 178 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 179 | } 180 | 181 | #endif 182 | 183 | #if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12)) 184 | #pragma GCC diagnostic pop 185 | #endif 186 | -------------------------------------------------------------------------------- /examples/example002a_pi_small_limb.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2024. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12)) 9 | #pragma GCC diagnostic push 10 | #pragma GCC diagnostic ignored "-Wstringop-overflow" 11 | #endif 12 | 13 | // Disable heavyweight features via macros for this example. 14 | #define WIDE_DECIMAL_DISABLE_IOSTREAM 15 | #define WIDE_DECIMAL_DISABLE_DYNAMIC_MEMORY_ALLOCATION 16 | #define WIDE_DECIMAL_DISABLE_CONSTRUCT_FROM_STRING 17 | #define WIDE_DECIMAL_DISABLE_CACHED_CONSTANTS 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace example002a_pi 33 | { 34 | auto lcd0() -> mcal::lcd::lcd_base& 35 | { 36 | static mcal::lcd::lcd_console lc0; 37 | 38 | return lc0; 39 | } 40 | } // namespace example002a_pi 41 | 42 | auto example002a_pi_small_limb_digits10_callback(const std::uint32_t d10) -> void 43 | { 44 | std::array(UINT32_C(10))> p_str = {{ '\0' }}; 45 | 46 | const char* p_end = util::baselexical_cast(d10, p_str.data(), p_str.data() + p_str.size()); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 47 | 48 | const auto len = static_cast(p_end - p_str.data()); 49 | 50 | example002a_pi::lcd0().write(p_str.data(), len, 0U); 51 | } 52 | 53 | #if defined(WIDE_DECIMAL_NAMESPACE) 54 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example002a_pi_small_limb() -> bool 55 | #else 56 | auto ::math::wide_decimal::example002a_pi_small_limb() -> bool 57 | #endif 58 | { 59 | using local_limb_type = std::uint16_t; 60 | 61 | constexpr std::int32_t wide_decimal_digits10 = INT32_C(1000001); 62 | 63 | #if defined(WIDE_DECIMAL_NAMESPACE) 64 | constexpr std::int32_t local_elem_number = 65 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::detail::decwide_t_helper::elem_number; 66 | #else 67 | constexpr std::int32_t local_elem_number = 68 | ::math::wide_decimal::detail::decwide_t_helper::elem_number; 69 | #endif 70 | 71 | #if defined(WIDE_DECIMAL_NAMESPACE) 72 | constexpr std::int32_t local_elem_digits10 = 73 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::detail::decwide_t_helper::elem_digits10; 74 | #else 75 | constexpr std::int32_t local_elem_digits10 = 76 | ::math::wide_decimal::detail::decwide_t_helper::elem_digits10; 77 | #endif 78 | 79 | using local_allocator_type = util::n_slot_array_allocator; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 80 | 81 | #if defined(WIDE_DECIMAL_NAMESPACE) 82 | using local_wide_decimal_type = 83 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t; 84 | #else 85 | using local_wide_decimal_type = 86 | ::math::wide_decimal::decwide_t; 87 | #endif 88 | 89 | using stopwatch_type = concurrency::stopwatch; 90 | 91 | stopwatch_type my_stopwatch { }; 92 | 93 | #if defined(WIDE_DECIMAL_NAMESPACE) 94 | const local_wide_decimal_type my_pi = 95 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::pi(example002a_pi_small_limb_digits10_callback); 96 | #else 97 | const local_wide_decimal_type my_pi = 98 | ::math::wide_decimal::pi(example002a_pi_small_limb_digits10_callback); 99 | #endif 100 | 101 | const float execution_time { stopwatch_type::elapsed_time(my_stopwatch) }; 102 | 103 | { 104 | std::stringstream strm { }; 105 | 106 | strm << "Time example002a_pi_small_limb() : " 107 | << std::fixed 108 | << std::setprecision(1) 109 | << execution_time 110 | << "s" 111 | ; 112 | 113 | std::cout << strm.str() << std::endl; 114 | } 115 | 116 | #if defined(WIDE_DECIMAL_NAMESPACE) 117 | const auto head_is_ok = std::equal(my_pi.crepresentation().cbegin(), 118 | my_pi.crepresentation().cbegin() + WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_head_16.size(), 119 | WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_head_16.begin()); 120 | #else 121 | const auto head_is_ok = std::equal(my_pi.crepresentation().cbegin(), 122 | my_pi.crepresentation().cbegin() + ::math::constants::const_pi_control_head_16.size(), 123 | ::math::constants::const_pi_control_head_16.begin()); 124 | #endif 125 | 126 | using const_iterator_type = typename local_wide_decimal_type::representation_type::const_iterator; 127 | 128 | #if defined(WIDE_DECIMAL_NAMESPACE) 129 | const_iterator_type 130 | fi 131 | ( 132 | my_pi.crepresentation().cbegin() 133 | + static_cast 134 | ( 135 | static_cast(1UL + ((wide_decimal_digits10 - 1UL) / local_elem_digits10)) 136 | - static_cast(WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_tail_16_1000001.size()) 137 | ) 138 | ); 139 | #else 140 | const_iterator_type 141 | fi 142 | ( 143 | my_pi.crepresentation().cbegin() 144 | + static_cast 145 | ( 146 | static_cast(1UL + ((wide_decimal_digits10 - 1UL) / local_elem_digits10)) 147 | - static_cast(::math::constants::const_pi_control_tail_16_1000001.size()) 148 | ) 149 | ); 150 | #endif 151 | 152 | #if defined(WIDE_DECIMAL_NAMESPACE) 153 | const auto tail_is_ok = std::equal(fi, 154 | fi + WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_tail_16_1000001.size(), 155 | WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_tail_16_1000001.begin()); 156 | #else 157 | const auto tail_is_ok = std::equal(fi, 158 | fi + ::math::constants::const_pi_control_tail_16_1000001.size(), 159 | ::math::constants::const_pi_control_tail_16_1000001.begin()); 160 | #endif 161 | 162 | const auto result_is_ok = (head_is_ok && tail_is_ok); 163 | 164 | return result_is_ok; 165 | } 166 | 167 | // Enable this if you would like to activate this main() as a standalone example. 168 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE002A_PI_SMALL_LIMB) 169 | 170 | #include 171 | #include 172 | 173 | auto main() -> int 174 | { 175 | const auto result_is_ok = ::math::wide_decimal::example002a_pi_small_limb(); 176 | 177 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 178 | } 179 | 180 | #endif 181 | 182 | #if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12)) 183 | #pragma GCC diagnostic pop 184 | #endif 185 | -------------------------------------------------------------------------------- /examples/example002b_pi_100k.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2024. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12)) 9 | #pragma GCC diagnostic push 10 | #pragma GCC diagnostic ignored "-Wstringop-overflow" 11 | #endif 12 | 13 | // Disable heavyweight features via macros for this example. 14 | //#define WIDE_DECIMAL_DISABLE_IOSTREAM 15 | #define WIDE_DECIMAL_DISABLE_DYNAMIC_MEMORY_ALLOCATION 16 | #define WIDE_DECIMAL_DISABLE_CONSTRUCT_FROM_STRING 17 | #define WIDE_DECIMAL_DISABLE_CACHED_CONSTANTS 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #if defined(WIDE_DECIMAL_NAMESPACE) 33 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example002b_pi_100k() -> bool 34 | #else 35 | auto ::math::wide_decimal::example002b_pi_100k() -> bool 36 | #endif 37 | { 38 | using local_limb_type = std::uint32_t; 39 | 40 | constexpr std::int32_t wide_decimal_digits10 = INT32_C(100001); 41 | 42 | #if defined(WIDE_DECIMAL_NAMESPACE) 43 | constexpr std::int32_t local_elem_number = 44 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::detail::decwide_t_helper::elem_number; 45 | #else 46 | constexpr std::int32_t local_elem_number = 47 | ::math::wide_decimal::detail::decwide_t_helper::elem_number; 48 | #endif 49 | 50 | #if defined(WIDE_DECIMAL_NAMESPACE) 51 | constexpr std::int32_t local_elem_digits10 = 52 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::detail::decwide_t_helper::elem_digits10; 53 | #else 54 | constexpr std::int32_t local_elem_digits10 = 55 | ::math::wide_decimal::detail::decwide_t_helper::elem_digits10; 56 | #endif 57 | 58 | using local_allocator_type = util::n_slot_array_allocator; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 59 | 60 | #if defined(WIDE_DECIMAL_NAMESPACE) 61 | using local_wide_decimal_type = 62 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t; 63 | #else 64 | using local_wide_decimal_type = 65 | ::math::wide_decimal::decwide_t; 66 | #endif 67 | 68 | using stopwatch_type = concurrency::stopwatch; 69 | 70 | stopwatch_type my_stopwatch { }; 71 | 72 | #if defined(WIDE_DECIMAL_NAMESPACE) 73 | const local_wide_decimal_type my_pi = 74 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::pi(); 75 | #else 76 | const local_wide_decimal_type my_pi = 77 | ::math::wide_decimal::pi(); 78 | #endif 79 | 80 | const float execution_time { stopwatch_type::elapsed_time(my_stopwatch) }; 81 | 82 | { 83 | std::stringstream strm { }; 84 | 85 | strm << "Time example002b_pi_100k() : " 86 | << std::fixed 87 | << std::setprecision(1) 88 | << execution_time 89 | << "s" 90 | ; 91 | 92 | std::cout << strm.str() << std::endl; 93 | } 94 | 95 | #if defined(WIDE_DECIMAL_NAMESPACE) 96 | const auto head_is_ok = std::equal(my_pi.crepresentation().cbegin(), 97 | my_pi.crepresentation().cbegin() + WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_head_32.size(), 98 | WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_head_32.begin()); 99 | #else 100 | const auto head_is_ok = std::equal(my_pi.crepresentation().cbegin(), 101 | my_pi.crepresentation().cbegin() + ::math::constants::const_pi_control_head_32.size(), 102 | ::math::constants::const_pi_control_head_32.begin()); 103 | #endif 104 | 105 | using const_iterator_type = typename local_wide_decimal_type::representation_type::const_iterator; 106 | 107 | #if defined(WIDE_DECIMAL_NAMESPACE) 108 | const_iterator_type 109 | fi 110 | ( 111 | my_pi.crepresentation().cbegin() 112 | + static_cast 113 | ( 114 | static_cast(1UL + ((wide_decimal_digits10 - 1UL) / local_elem_digits10)) 115 | - static_cast(WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_tail_32_100001.size()) 116 | ) 117 | ); 118 | #else 119 | const_iterator_type 120 | fi 121 | ( 122 | my_pi.crepresentation().cbegin() 123 | + static_cast 124 | ( 125 | static_cast(1UL + ((wide_decimal_digits10 - 1UL) / local_elem_digits10)) 126 | - static_cast(::math::constants::const_pi_control_tail_32_100001.size()) 127 | ) 128 | ); 129 | #endif 130 | 131 | #if defined(WIDE_DECIMAL_NAMESPACE) 132 | const auto tail_is_ok = std::equal(fi, 133 | fi + WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_tail_32_100001.size(), 134 | WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_tail_32_100001.begin()); 135 | #else 136 | const auto tail_is_ok = std::equal(fi, 137 | fi + ::math::constants::const_pi_control_tail_32_100001.size(), 138 | ::math::constants::const_pi_control_tail_32_100001.begin()); 139 | #endif 140 | 141 | const auto result_is_ok = (head_is_ok && tail_is_ok); 142 | 143 | return result_is_ok; 144 | } 145 | 146 | // Enable this if you would like to activate this main() as a standalone example. 147 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE002B_PI_100K) 148 | 149 | #include 150 | #include 151 | 152 | auto main() -> int 153 | { 154 | const auto result_is_ok = ::math::wide_decimal::example002b_pi_100k(); 155 | 156 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 157 | } 158 | 159 | #endif 160 | 161 | #if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12)) 162 | #pragma GCC diagnostic pop 163 | #endif 164 | -------------------------------------------------------------------------------- /examples/example002d_pi_limb08.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2024. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12)) 9 | #pragma GCC diagnostic push 10 | #pragma GCC diagnostic ignored "-Wstringop-overflow" 11 | #endif 12 | 13 | // Disable heavyweight features via macros for this example. 14 | #define WIDE_DECIMAL_DISABLE_IOSTREAM 15 | #define WIDE_DECIMAL_DISABLE_DYNAMIC_MEMORY_ALLOCATION 16 | #define WIDE_DECIMAL_DISABLE_CONSTRUCT_FROM_STRING 17 | #define WIDE_DECIMAL_DISABLE_CACHED_CONSTANTS 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace example002d_pi { 33 | 34 | auto lcd0() -> mcal::lcd::lcd_base& 35 | { 36 | static mcal::lcd::lcd_console lc0; 37 | 38 | return lc0; 39 | } 40 | 41 | } // namespace example002d_pi 42 | 43 | auto example002d_pi_limb8_digits10_callback(const std::uint32_t d10) -> void 44 | { 45 | std::array(UINT32_C(10))> p_str = {{ '\0' }}; 46 | 47 | const char* p_end = util::baselexical_cast(d10, p_str.data(), p_str.data() + p_str.size()); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 48 | 49 | const auto len = static_cast(p_end - p_str.data()); 50 | 51 | example002d_pi::lcd0().write(p_str.data(), len, 0U); 52 | } 53 | 54 | #if defined(WIDE_DECIMAL_NAMESPACE) 55 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example002d_pi_limb08() -> bool 56 | #else 57 | auto ::math::wide_decimal::example002d_pi_limb08() -> bool 58 | #endif 59 | { 60 | using local_limb_type = std::uint8_t; 61 | 62 | constexpr std::int32_t wide_decimal_digits10 = INT32_C(1000001); 63 | 64 | #if defined(WIDE_DECIMAL_NAMESPACE) 65 | constexpr std::int32_t local_elem_number = 66 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::detail::decwide_t_helper::elem_number; 67 | #else 68 | constexpr std::int32_t local_elem_number = 69 | ::math::wide_decimal::detail::decwide_t_helper::elem_number; 70 | #endif 71 | 72 | #if defined(WIDE_DECIMAL_NAMESPACE) 73 | constexpr std::int32_t local_elem_digits10 = 74 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::detail::decwide_t_helper::elem_digits10; 75 | #else 76 | constexpr std::int32_t local_elem_digits10 = 77 | ::math::wide_decimal::detail::decwide_t_helper::elem_digits10; 78 | #endif 79 | 80 | using local_allocator_type = util::n_slot_array_allocator; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 81 | 82 | #if defined(WIDE_DECIMAL_NAMESPACE) 83 | using local_wide_decimal_type = 84 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t; 85 | #else 86 | using local_wide_decimal_type = 87 | ::math::wide_decimal::decwide_t; 88 | #endif 89 | 90 | using stopwatch_type = concurrency::stopwatch; 91 | 92 | stopwatch_type my_stopwatch { }; 93 | 94 | #if defined(WIDE_DECIMAL_NAMESPACE) 95 | const local_wide_decimal_type my_pi = 96 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::pi(example002d_pi_limb8_digits10_callback); 97 | #else 98 | const local_wide_decimal_type my_pi = 99 | ::math::wide_decimal::pi(example002d_pi_limb8_digits10_callback); 100 | #endif 101 | 102 | const float execution_time { stopwatch_type::elapsed_time(my_stopwatch) }; 103 | 104 | { 105 | std::stringstream strm { }; 106 | 107 | strm << "Time example002d_pi_limb08() : " 108 | << std::fixed 109 | << std::setprecision(1) 110 | << execution_time 111 | << "s" 112 | ; 113 | 114 | std::cout << strm.str() << std::endl; 115 | } 116 | 117 | #if defined(WIDE_DECIMAL_NAMESPACE) 118 | const auto head_is_ok = std::equal(my_pi.crepresentation().cbegin(), 119 | my_pi.crepresentation().cbegin() + WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_head_08.size(), 120 | WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_head_08.begin()); 121 | #else 122 | const auto head_is_ok = std::equal(my_pi.crepresentation().cbegin(), 123 | my_pi.crepresentation().cbegin() + ::math::constants::const_pi_control_head_08.size(), 124 | ::math::constants::const_pi_control_head_08.begin()); 125 | #endif 126 | 127 | using const_iterator_type = typename local_wide_decimal_type::representation_type::const_iterator; 128 | 129 | #if defined(WIDE_DECIMAL_NAMESPACE) 130 | const_iterator_type 131 | fi 132 | ( 133 | my_pi.crepresentation().cbegin() 134 | + static_cast 135 | ( 136 | static_cast(1UL + ((wide_decimal_digits10 - 1UL) / local_elem_digits10)) 137 | - static_cast(WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_tail_08_1000001.size()) 138 | ) 139 | ); 140 | #else 141 | const_iterator_type 142 | fi 143 | ( 144 | my_pi.crepresentation().cbegin() 145 | + static_cast 146 | ( 147 | static_cast(1UL + ((wide_decimal_digits10 - 1UL) / local_elem_digits10)) 148 | - static_cast(::math::constants::const_pi_control_tail_08_1000001.size()) 149 | ) 150 | ); 151 | #endif 152 | 153 | // When using 8-bit limb size, the two least significant limbs are imprecise. 154 | #if defined(WIDE_DECIMAL_NAMESPACE) 155 | const auto tail_is_ok = std::equal(fi, 156 | fi + (WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_tail_08_1000001.size() - 3U), 157 | WIDE_DECIMAL_NAMESPACE::math::constants::const_pi_control_tail_08_1000001.begin()); 158 | #else 159 | const auto tail_is_ok = std::equal(fi, 160 | fi + (::math::constants::const_pi_control_tail_08_1000001.size() - 3U), 161 | ::math::constants::const_pi_control_tail_08_1000001.begin()); 162 | #endif 163 | 164 | const auto result_is_ok = (head_is_ok && tail_is_ok); 165 | 166 | return result_is_ok; 167 | } 168 | 169 | // Enable this if you would like to activate this main() as a standalone example. 170 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE002D_PI_LIMB08) 171 | 172 | #include 173 | #include 174 | 175 | auto main() -> int 176 | { 177 | const auto result_is_ok = ::math::wide_decimal::example002d_pi_limb08(); 178 | 179 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 180 | } 181 | 182 | #endif 183 | 184 | #if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12)) 185 | #pragma GCC diagnostic pop 186 | #endif 187 | -------------------------------------------------------------------------------- /examples/example003_zeta.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2022. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | namespace local_zeta 16 | { 17 | #if defined(WIDE_DECIMAL_NAMESPACE) 18 | using dec51_t = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t(INT32_C(51)), std::uint32_t, void>; 19 | #else 20 | using dec51_t = ::math::wide_decimal::decwide_t(INT32_C(51)), std::uint32_t, void>; 21 | #endif 22 | 23 | template 24 | auto pi() -> FloatType { using unknown_float_type = FloatType; return unknown_float_type(); } 25 | 26 | // N[Pi, 57] 27 | template<> 28 | auto pi() -> dec51_t { return dec51_t( "3.14159265358979323846264338327950288419716939937510582097"); } 29 | 30 | auto compute_primes_via_square_root(std::deque& primes, // NOLINT(google-runtime-references) 31 | const std::uint_fast16_t maximum_value) -> void 32 | { 33 | // This is a helper function that produces a small table of primes. 34 | // It uses rudimentary (and slow) trial division with denominator 35 | // ranging from 3 up to the square root of the largest expected prime. 36 | 37 | for(auto i = static_cast(UINT16_C(3)); 38 | i <= maximum_value; // NOLINT(altera-id-dependent-backward-branch) 39 | i = static_cast(i + UINT16_C(2))) 40 | { 41 | using std::sqrt; 42 | 43 | const auto maximum_square_root_value = 44 | static_cast 45 | ( 46 | static_cast(sqrt(static_cast(i)) + 0.1F) 47 | ); 48 | 49 | bool is_prime = true; 50 | 51 | for(auto j = static_cast(UINT16_C(3)); 52 | j <= maximum_square_root_value; // NOLINT(altera-id-dependent-backward-branch) 53 | ++j) 54 | { 55 | if(static_cast(i % j) == UINT16_C(0)) 56 | { 57 | is_prime = false; 58 | 59 | break; 60 | } 61 | } 62 | 63 | if(is_prime) 64 | { 65 | primes.push_back(i); 66 | } 67 | } 68 | } 69 | 70 | template 71 | auto zeta16(const std::deque& primes) -> FloatingPointType 72 | { 73 | // This is a dedicated template function that computes 74 | // zeta(16) from an elementary series of prime powers. 75 | 76 | using float_type = FloatingPointType; 77 | 78 | float_type z = float_type(65536U) / 65535U; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 79 | 80 | for(auto i = 1U; i < primes.size(); ++i) 81 | { 82 | float_type p16 = pow(float_type(primes.at(i)), 16); // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 83 | 84 | const float_type term = 1 / (1 - (1 / p16)); 85 | 86 | using std::fabs; 87 | 88 | if(fabs(float_type(1) - term) < std::numeric_limits::epsilon()) 89 | { 90 | break; 91 | } 92 | 93 | z *= term; 94 | } 95 | 96 | return z; 97 | } 98 | } // namespace local_zeta 99 | 100 | #if defined(WIDE_DECIMAL_NAMESPACE) 101 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example003_zeta() -> bool 102 | #else 103 | auto ::math::wide_decimal::example003_zeta() -> bool 104 | #endif 105 | { 106 | std::deque primes(1U, UINT32_C(2)); 107 | 108 | using local_zeta::dec51_t; 109 | 110 | // Get a table of the first 1000 primes. 111 | local_zeta::compute_primes_via_square_root(primes, UINT32_C(7920)); 112 | 113 | // From https://functions.wolfram.com/ZetaFunctionsandPolylogarithms/Zeta/03/02/ 114 | // we find that zeta(16) = (3617 Pi^16)/325641566250 115 | // = 1.000015282259408651871732571487636722023237388990471531... 116 | 117 | // Compute zeta(16). 118 | const auto r16 = local_zeta::zeta16(primes); 119 | 120 | using std::fabs; 121 | 122 | // Check the closeness of the result. 123 | const dec51_t control 124 | { 125 | static_cast(3617U * pow(local_zeta::pi(), 16U)) / 325641566250ULL 126 | }; 127 | 128 | const dec51_t closeness = fabs(1 - (r16 / control)); 129 | 130 | const auto result_is_ok = (closeness < (std::numeric_limits::epsilon() * static_cast(UINT8_C(10)))); 131 | 132 | return result_is_ok; 133 | } 134 | 135 | // Enable this if you would like to activate this main() as a standalone example. 136 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE003_ZETA) 137 | 138 | #include 139 | #include 140 | 141 | auto main() -> int 142 | { 143 | const auto result_is_ok = ::math::wide_decimal::example003_zeta(); 144 | 145 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 146 | } 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /examples/example005_polylog_series.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2022. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | namespace local_polylog 16 | { 17 | template 18 | auto polylog(std::int32_t s, const FloatingPointType& x) -> FloatingPointType; 19 | 20 | template 21 | auto polylog(std::int32_t s, const FloatingPointType& x) -> FloatingPointType 22 | { 23 | using floating_point_type = FloatingPointType; 24 | 25 | const floating_point_type tol = (x * std::numeric_limits::epsilon()) / 10U; 26 | 27 | floating_point_type x_pow_k(x); 28 | floating_point_type sum (x); 29 | 30 | for(auto k = static_cast(UINT32_C(2)); 31 | k < static_cast(UINT32_C(100000)); 32 | ++k) 33 | { 34 | x_pow_k *= x; 35 | 36 | const floating_point_type k_pow_s = pow(floating_point_type(k), s); 37 | const floating_point_type term = x_pow_k / k_pow_s; 38 | 39 | if(term < tol) 40 | { 41 | break; 42 | } 43 | 44 | sum += term; 45 | } 46 | 47 | return sum; 48 | } 49 | } // namespace local_polylog 50 | 51 | #if defined(WIDE_DECIMAL_NAMESPACE) 52 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example005_polylog_series() -> bool 53 | #else 54 | auto ::math::wide_decimal::example005_polylog_series() -> bool 55 | #endif 56 | { 57 | #if defined(WIDE_DECIMAL_NAMESPACE) 58 | using dec101_t = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t(INT32_C(101))>; 59 | #else 60 | using dec101_t = ::math::wide_decimal::decwide_t(INT32_C(101))>; 61 | #endif 62 | 63 | using std::fabs; 64 | 65 | const dec101_t poly = local_polylog::polylog(7U, dec101_t(17U) / 71U); 66 | 67 | // N[PolyLog[7, 17/71], 101] 68 | const dec101_t control 69 | { 70 | "0.23989099751201076665599565769828454152030927256642802570721839696637617308754054721620440634024352282" 71 | }; 72 | 73 | // Check the closeness of the result. 74 | const dec101_t closeness = fabs(1 - (poly / control)); 75 | 76 | const auto result_is_ok = (closeness < (std::numeric_limits::epsilon() * static_cast(UINT8_C(10)))); 77 | 78 | return result_is_ok; 79 | } 80 | 81 | // Enable this if you would like to activate this main() as a standalone example. 82 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE005_POLYLOG_SERIES) 83 | 84 | #include 85 | #include 86 | 87 | auto main() -> int 88 | { 89 | const auto result_is_ok = ::math::wide_decimal::example005_polylog_series(); 90 | 91 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 92 | } 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /examples/example006_logarithm.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2024. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #if defined(WIDE_DECIMAL_NAMESPACE) 18 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example006_logarithm() -> bool 19 | #else 20 | auto ::math::wide_decimal::example006_logarithm() -> bool 21 | #endif 22 | { 23 | // Compute 1,000 values of Log[(123456789/1000000) * (3^n)], 24 | // the result of which is Log[(123456789/1000000)] + (n Log[3]) 25 | 26 | #if defined(WIDE_DECIMAL_NAMESPACE) 27 | using dec1001_t = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t(INT32_C(1001))>; 28 | #else 29 | using dec1001_t = ::math::wide_decimal::decwide_t(INT32_C(1001))>; 30 | #endif 31 | 32 | const dec1001_t control_base 33 | { 34 | "4." 35 | "8158912082037439290859846198570189641070729092477641189851225392867818091922368962401331896527129054" 36 | "2666982451156682861982679524527470166196254928165458284131035443816736211730436451521894844085101906" 37 | "0636084466017164897727191862876944629168307811518342680833354831758201699290992192035440727861285590" 38 | "8000194558288545181435034121332042612342464441366245658708127241516875453381972256430977100477994492" 39 | "1474658096051794033615830363454630975474185840919830130502452555134885705490664737858885196366894765" 40 | "6951094462223789705853191026178076148292450697704283854638855304180978799038854077251637293739120576" 41 | "0521703221737573691529408083457723228782448834154143092019701535755380818666246605093528537268510024" 42 | "5327578738401674847141550739942174920396318884548859759526811168922714652063318571945848520663995099" 43 | "2043823208979562358069992851979820083605474605201139892476772979368945875254998083845420172215964725" 44 | "7405172125930111781652611052213816835641831608143730061196534241354604509454101590453678456875749885" 45 | "9" 46 | }; 47 | 48 | dec1001_t x = dec1001_t(UINT32_C(123456789)) / UINT32_C(1000000); 49 | 50 | const dec1001_t ln3 = log(dec1001_t(static_cast(UINT8_C(3)))); 51 | const auto tol = static_cast(std::numeric_limits::epsilon() * static_cast(UINT8_C(10))); 52 | 53 | bool result_is_ok = true; 54 | 55 | using stopwatch_type = concurrency::stopwatch; 56 | 57 | stopwatch_type my_stopwatch { }; 58 | 59 | for(auto i = static_cast(0U); i < static_cast(UINT32_C(1000)); ++i) 60 | { 61 | const dec1001_t lg = log(x); 62 | 63 | const dec1001_t control = control_base + (ln3 * i); 64 | 65 | const dec1001_t closeness = fabs(1 - (lg / control)); 66 | 67 | result_is_ok &= (closeness < tol); 68 | 69 | x *= 3U; 70 | } 71 | 72 | const float execution_time { stopwatch_type::elapsed_time(my_stopwatch) }; 73 | 74 | { 75 | std::stringstream strm { }; 76 | 77 | strm << "Time example006_logarithm() : " 78 | << std::fixed 79 | << std::setprecision(1) 80 | << execution_time 81 | << "s" 82 | ; 83 | 84 | std::cout << strm.str() << std::endl; 85 | } 86 | 87 | return result_is_ok; 88 | } 89 | 90 | // Enable this if you would like to activate this main() as a standalone example. 91 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE006_LOGARITHM) 92 | 93 | #include 94 | #include 95 | 96 | auto main() -> int 97 | { 98 | const auto result_is_ok = ::math::wide_decimal::example006_logarithm(); 99 | 100 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 101 | } 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /examples/example007_catalan_series.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2022. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace example007_catalan 14 | { 15 | constexpr std::int32_t wide_decimal_digits10 = INT32_C(1001); 16 | 17 | #if defined(WIDE_DECIMAL_NAMESPACE) 18 | using dec1001_t = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t; 19 | #else 20 | using dec1001_t = ::math::wide_decimal::decwide_t; 21 | #endif 22 | 23 | template 24 | auto pi() -> FloatingPointType 25 | { 26 | return static_cast(3.1415926535897932384626433832795029L); // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers,modernize-use-std-numbers) 27 | } 28 | 29 | template<> 30 | auto pi() -> dec1001_t 31 | { 32 | #if defined(WIDE_DECIMAL_NAMESPACE) 33 | return WIDE_DECIMAL_NAMESPACE::math::wide_decimal::pi(); 34 | #else 35 | return ::math::wide_decimal::pi(); 36 | #endif 37 | } 38 | 39 | template 40 | auto catalan() -> FloatingPointType 41 | { 42 | using floating_point_type = FloatingPointType; 43 | 44 | // Adapted from Boost.Math.Constants (see file calculate_constants.hpp). 45 | // See also http://www.mpfr.org/algorithms.pdf 46 | 47 | floating_point_type k_fact (1U); 48 | floating_point_type tk_fact(2U); 49 | floating_point_type sum (static_cast(19U) / 18U); // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 50 | 51 | const floating_point_type lim = std::numeric_limits::epsilon(); 52 | 53 | for(auto k = static_cast(2U); k < UINT32_C(10000000); ++k) 54 | { 55 | const auto tk = static_cast(2U * k); 56 | const auto tk_plus_one = static_cast(tk + 1U); 57 | 58 | const auto tk_plus_one_squared = 59 | static_cast 60 | ( 61 | static_cast(tk_plus_one) * tk_plus_one 62 | ); 63 | 64 | k_fact *= k; 65 | tk_fact *= static_cast(static_cast(tk) * (tk - 1U)); 66 | 67 | floating_point_type term = (k_fact * k_fact) / (tk_fact * tk_plus_one_squared); 68 | 69 | sum += term; 70 | 71 | if(term < lim) 72 | { 73 | break; 74 | } 75 | } 76 | 77 | using example007_catalan::pi; 78 | using std::log; 79 | using std::sqrt; 80 | 81 | return (((pi() * log(2U + sqrt(static_cast(3U)))) + (sum * 3U)) / 8U); // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 82 | } 83 | } // namespace example007_catalan 84 | 85 | #if defined(WIDE_DECIMAL_NAMESPACE) 86 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example007_catalan_series() -> bool 87 | #else 88 | auto ::math::wide_decimal::example007_catalan_series() -> bool 89 | #endif 90 | { 91 | using example007_catalan::dec1001_t; 92 | 93 | const auto c = example007_catalan::catalan(); 94 | 95 | const dec1001_t control 96 | { 97 | "0." 98 | "9159655941772190150546035149323841107741493742816721342664981196217630197762547694793565129261151062" 99 | "4857442261919619957903589880332585905943159473748115840699533202877331946051903872747816408786590902" 100 | "4706484152163000228727640942388259957741508816397470252482011560707644883807873370489900864775113225" 101 | "9971343407485407553230768565335768095835260219382323950800720680355761048235733942319149829836189977" 102 | "0690364041808621794110191753274314997823397610551224779530324875371878665828082360570225594194818097" 103 | "5350971131571261580424272363643985001738287597797653068370092980873887495610893659771940968726844441" 104 | "6680462162433986483891628044828150627302274207388431172218272190472255870531908685735423498539498309" 105 | "9191159673884645086151524996242370437451777372351775440708538464401321748392999947572446199754961975" 106 | "8706400747487070149093767887304586997986064487497464387206238513712392736304998503539223928787979063" 107 | "3644032354784535851927777787270906083031994301332316712476158709792455479119092126201854803963934243" 108 | "5" 109 | }; 110 | 111 | const dec1001_t closeness = fabs(1 - (c / control)); 112 | 113 | const auto result_is_ok = (closeness < (std::numeric_limits::epsilon() * static_cast(UINT8_C(10)))); 114 | 115 | return result_is_ok; 116 | } 117 | 118 | // Enable this if you would like to activate this main() as a standalone example. 119 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE007_CATALAN_SERIES) 120 | 121 | #include 122 | #include 123 | 124 | auto main() -> int 125 | { 126 | const auto result_is_ok = ::math::wide_decimal::example007_catalan_series(); 127 | 128 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 129 | } 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /examples/example009_boost_math_standalone.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2022. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | 10 | #include 11 | 12 | #if !defined(BOOST_VERSION) 13 | #error BOOST_VERSION is not defined. Ensure that is properly included. 14 | #endif 15 | 16 | #if (BOOST_VERSION >= 108000) 17 | #if !defined(BOOST_NO_EXCEPTIONS) 18 | #define BOOST_NO_EXCEPTIONS 19 | #endif 20 | #if !defined(BOOST_NO_RTTI) 21 | #define BOOST_NO_RTTI 22 | #endif 23 | #endif 24 | 25 | #if ((BOOST_VERSION >= 107700) && !defined(BOOST_MATH_STANDALONE)) 26 | #if (defined(_MSC_VER) && (_MSC_VER < 1920)) 27 | #else 28 | #define BOOST_MATH_STANDALONE 29 | #endif 30 | #endif 31 | 32 | #if ((BOOST_VERSION >= 107900) && !defined(BOOST_MP_STANDALONE)) 33 | #define BOOST_MP_STANDALONE 34 | #endif 35 | 36 | #if defined(__GNUC__) 37 | #pragma GCC diagnostic push 38 | #pragma GCC diagnostic ignored "-Wconversion" 39 | #pragma GCC diagnostic push 40 | #pragma GCC diagnostic ignored "-Wsign-conversion" 41 | #pragma GCC diagnostic push 42 | #pragma GCC diagnostic ignored "-Wunused-parameter" 43 | #pragma GCC diagnostic push 44 | #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" 45 | #endif 46 | 47 | #if defined(__clang__) && !defined(__APPLE__) 48 | #pragma GCC diagnostic push 49 | #pragma GCC diagnostic ignored "-Wdeprecated-copy" 50 | #endif 51 | 52 | #if (BOOST_VERSION < 107900) 53 | #include 54 | #include 55 | #endif 56 | 57 | #include 58 | #include 59 | 60 | #include 61 | 62 | namespace example009_boost 63 | { 64 | constexpr std::int32_t wide_decimal_digits10 = INT32_C(1001); 65 | 66 | #if defined(WIDE_DECIMAL_NAMESPACE) 67 | using dec1001_t = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t; 68 | #else 69 | using dec1001_t = ::math::wide_decimal::decwide_t; 70 | #endif 71 | } // namespace example009_boost 72 | 73 | #if defined(WIDE_DECIMAL_NAMESPACE) 74 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example009_boost_math_standalone() -> bool 75 | #else 76 | auto ::math::wide_decimal::example009_boost_math_standalone() -> bool 77 | #endif 78 | { 79 | using example009_boost::dec1001_t; 80 | 81 | #if (BOOST_VERSION < 107900) 82 | using boost_wrapexcept_round_type = ::boost::wrapexcept<::boost::math::rounding_error>; 83 | using boost_wrapexcept_domain_type = ::boost::wrapexcept; 84 | #endif 85 | 86 | auto result_is_ok = false; 87 | 88 | #if (BOOST_VERSION >= 108000) 89 | #else 90 | try 91 | { 92 | #endif 93 | const dec1001_t x = dec1001_t(INT32_C(-123456789)) / 100U; 94 | 95 | using std::cbrt; 96 | using std::fabs; 97 | 98 | // Compare wide-decimal's cube root function with that of Boost.Math. 99 | // Also exercise several different interpretations of the constant pi. 100 | 101 | #if defined(WIDE_DECIMAL_NAMESPACE) 102 | const dec1001_t c = cbrt(x / WIDE_DECIMAL_NAMESPACE::math::wide_decimal::pi, double>()); 103 | #else 104 | const dec1001_t c = cbrt(x / ::math::wide_decimal::pi, double>()); 105 | #endif 106 | 107 | const dec1001_t control = boost::math::cbrt(x / boost::math::constants::pi()); 108 | 109 | const dec1001_t closeness = fabs(1 - (c / control)); 110 | 111 | result_is_ok = (closeness < (std::numeric_limits::epsilon() * static_cast(UINT8_C(10)))); 112 | #if (BOOST_VERSION >= 108000) 113 | #else 114 | } 115 | #if (BOOST_VERSION < 107900) 116 | catch(const boost_wrapexcept_round_type& e) 117 | { 118 | result_is_ok = false; 119 | 120 | std::cout << "Exception: boost_wrapexcept_round_type: " << e.what() << std::endl; 121 | } 122 | catch(const boost_wrapexcept_domain_type& e) 123 | { 124 | result_is_ok = false; 125 | 126 | std::cout << "Exception: boost_wrapexcept_domain_type: " << e.what() << std::endl; 127 | } 128 | #else 129 | // LCOV_EXCL_START 130 | catch(const ::boost::math::rounding_error& e) 131 | { 132 | result_is_ok = false; 133 | 134 | std::cout << "Exception: ::boost::math::rounding_error: " << e.what() << std::endl; 135 | } 136 | catch(const std::domain_error& e) 137 | { 138 | result_is_ok = false; 139 | 140 | std::cout << "Exception: std::domain_error: " << e.what() << std::endl; 141 | } 142 | // LCOV_EXCL_STOP 143 | #endif 144 | #endif 145 | 146 | return result_is_ok; 147 | } 148 | 149 | // Enable this if you would like to activate this main() as a standalone example. 150 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE009_BOOST_MATH_STANDALONE) 151 | 152 | #include 153 | #include 154 | 155 | // TBD: Handle exception catching in example009_boost_math_standalone at a later time. 156 | auto main() -> int // NOLINT(bugprone-exception-escape) 157 | { 158 | const auto result_is_ok = ::math::wide_decimal::example009_boost_math_standalone(); 159 | 160 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 161 | } 162 | 163 | #endif 164 | 165 | #if defined(__clang__) && !defined(__APPLE__) 166 | #pragma GCC diagnostic pop 167 | #endif 168 | 169 | #if defined(__GNUC__) 170 | #pragma GCC diagnostic pop 171 | #pragma GCC diagnostic pop 172 | #pragma GCC diagnostic pop 173 | #pragma GCC diagnostic pop 174 | #endif 175 | -------------------------------------------------------------------------------- /examples/example010a_hypergeometric_1f1.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2018 - 2022. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | namespace example010a_hypergeometric 17 | { 18 | template 19 | auto hypergeometric_1f1(const T& AP, const T& CP, const T& ZM) -> T // NOLINT(readability-identifier-naming,bugprone-easily-swappable-parameters) 20 | { 21 | // Implement a rational approximation of hypergeometric_1f1. 22 | // This C++11 code uses a computational scheme similar to 23 | // one shown in Y.L. Luke, "Algorithms for the Comuptation 24 | // of Mathematical Functions", Academic Press, New York, 1977. 25 | // The original Fortran77 source can be found in the subroutine 26 | // R1F1() on page 188. Slight corrections are made here 27 | // in order to repair one or two type-setting errors in the 28 | // original publication. 29 | 30 | // Luke's original Fortran77 programs and algorithmic work are fascinating 31 | // since they are generic and scalable --- decades ahead of their time. 32 | // Here, in fact, the calculation is scaled to 1,001 decimal digits 33 | // of precision. 34 | 35 | // Retain some stylistic elements and comments from Luke's 36 | // original Fortran77 coding style. 37 | 38 | const T Z(-ZM); // NOLINT(readability-identifier-naming) 39 | 40 | // C 41 | // C INITIALIZATION : 42 | // C 43 | 44 | const T Z2(Z / 2U); // NOLINT(readability-identifier-naming) 45 | 46 | const T my_zero(0U); 47 | const T my_one (1U); 48 | const T my_two (2U); 49 | 50 | std::array A; // NOLINT(readability-identifier-naming) 51 | std::array B; // NOLINT(readability-identifier-naming) 52 | 53 | { 54 | const T CT1X((AP * Z) / CP); // NOLINT(readability-identifier-naming) 55 | const T CT2X(Z2 / (1U + CP)); // NOLINT(readability-identifier-naming) 56 | 57 | A[0U] = my_one; 58 | B[0U] = my_one; 59 | B[1U] = my_one + (((1U + AP) * Z2) / CP); 60 | A[1U] = B[1U] - CT1X; 61 | B[2U] = my_one + ((((my_two + B[1U]) * (2U + AP)) * CT2X) / 3U); 62 | A[2U] = B[2U] - ((my_one + CT2X) * CT1X); 63 | } 64 | 65 | std::uint_fast16_t CT1 = UINT16_C(3); // NOLINT(readability-identifier-naming) 66 | T CT2; // NOLINT(readability-identifier-naming) 67 | 68 | std::array N // NOLINT(readability-identifier-naming) 69 | { 70 | { 71 | UINT16_C(3), 72 | UINT16_C(2), 73 | UINT16_C(1), 74 | UINT16_C(0) 75 | } 76 | }; 77 | 78 | std::array G; // NOLINT(readability-identifier-naming) 79 | 80 | // C 81 | // C FOR I=3,...,N , THE VALUES A(I) AND B(I) ARE CALCULATED 82 | // C USING THE RECURRENCE RELATIONS BELOW. 83 | // C 84 | 85 | const T Z2Z2 = (Z2 * Z2); // NOLINT(readability-identifier-naming) 86 | 87 | for( ; N[0U] < UINT16_C(10000); ++N[0U]) 88 | { 89 | // C 90 | // C CALCULATION OF THE MULTIPLIERS FOR THE RECURSION 91 | // C 92 | 93 | // Use simplification with computer algebra and integer values 94 | // where possible to reduce the total work of the following 95 | // calculations from: 96 | // 8 multiplications and 7 divisions (8 + (7 * 3)) = 29 to 97 | // 7 multiplications and 4 divisions (7 + (4 * 3)) = 19, 98 | // where division is assumed to require 3 times more work 99 | // than multiplication does. 100 | 101 | CT2 = Z2 / (CT1 * (CP + N[1U])); 102 | G[0U] = my_one + (CT2 * (N[2U] - AP)); 103 | CT2 = (CT2 * (AP + N[1U])) / (CP + N[2U]); 104 | G[1U] = CT2 * ((CP - N[1U]) + (((AP + N[0U]) / (CT1 + 2U)) * Z2)); 105 | G[2U] = ((CT2 * (AP - N[2U])) * ((AP + N[2U]) * Z2Z2)) / (static_cast(static_cast(CT1 - my_two) * CT1) * (CP + N[3U])); 106 | 107 | // C ----------------------------------------------------------------- 108 | // C THE RECURRENCE RELATIONS FOR A(I) and B(I) ARE AS FOLLOWS 109 | // C ----------------------------------------------------------------- 110 | 111 | A[3U] = std::inner_product(G.crbegin(), G.crend(), A.cbegin(), my_zero); 112 | B[3U] = std::inner_product(G.crbegin(), G.crend(), B.cbegin(), my_zero); 113 | 114 | std::copy(N.crbegin() + 1U, N.crend(), N.rbegin()); 115 | 116 | if(N[3U] > UINT16_C(2)) 117 | { 118 | // Check if the iteration difference (delta) is within 119 | // tolerance and break from the recursion if it is. 120 | // Here we analyze the difference between this iteration 121 | // result and the previous iteration result using: 122 | // 123 | // | |(A2/B2)]| | 124 | // delta = | 1 - |--------| | 125 | // | |(A3/B3) | | 126 | // 127 | // | |(A2*B3)| | 128 | // = | 1 - |-------| |, 129 | // | |(A3*B2)| | 130 | // 131 | // where the absolute value of the ratio in the second term 132 | // is used and the absolute value of delta is used. 133 | 134 | using std::fabs; 135 | 136 | const T ratio = fabs((A[2U] * B[3U]) / (A[3U] * B[2U])); 137 | const T delta = fabs(my_one - ratio); 138 | 139 | if(delta < std::numeric_limits::epsilon()) 140 | { 141 | break; 142 | } 143 | } 144 | 145 | // Shift the arrays for the next recursion. 146 | std::copy(A.cbegin() + 1U, A.cend(), A.begin()); 147 | std::copy(B.cbegin() + 1U, B.cend(), B.begin()); 148 | 149 | CT1 = static_cast(CT1 + UINT16_C(2)); 150 | } 151 | 152 | // Return the rational approximation. This is given 153 | // by the ratio of the final recursions of A and B. 154 | return ((N[0U] < UINT16_C(10000)) ? (A.back() / B.back()) : T(0U)); 155 | } 156 | } // namespace example010a_hypergeometric 157 | 158 | #if defined(WIDE_DECIMAL_NAMESPACE) 159 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example010a_hypergeometric_1f1() -> bool 160 | #else 161 | auto ::math::wide_decimal::example010a_hypergeometric_1f1() -> bool 162 | #endif 163 | { 164 | #if defined(WIDE_DECIMAL_NAMESPACE) 165 | using dec1001_t = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t(INT32_C(1001))>; 166 | #else 167 | using dec1001_t = ::math::wide_decimal::decwide_t(INT32_C(1001))>; 168 | #endif 169 | 170 | const dec1001_t a( dec1001_t(2U) / 3U); 171 | const dec1001_t b( dec1001_t(4U) / 3U); 172 | const dec1001_t z(-dec1001_t(3U) / 4U); 173 | 174 | const dec1001_t h1f1 = example010a_hypergeometric::hypergeometric_1f1(a, b, z); 175 | 176 | // N[Hypergeometric1F1[2/3, 4/3, -3/4], 1003] 177 | const dec1001_t control 178 | { 179 | "0." 180 | "7081686536671296176070489154441892975263864254727871399151279335156755130218980066854878718659644876" 181 | "1305121691418288067229656427737120644431158087451536612475482465245551262861209703714089698028175454" 182 | "0070644713429820469109420541161232888933036256421986450730383363242819718385845578123146346562416912" 183 | "8459987657984935712740682227830255529693892427453550857117109315771584082876374760460718792291350348" 184 | "5190554952923571564136649540077735757762129258093268390205343996981829581788815350317949553374856332" 185 | "4600791123444332864835615846878224843114597006279577350905460171544671226390900903288844703332800883" 186 | "7461634557128794965583053125950999187778364988189708317696297046872660631251555306433290041457209364" 187 | "7846449827307910707408292805642488619055129649252986312848264653807329387537374580180299791208841957" 188 | "4522132120358559031634677139462281867313156223643446521436399244700681185183813207181756167736113034" 189 | "8578271847519210395098212613256528348855147753328519068248226379214308876937283270363298187389819025" 190 | "524" 191 | }; 192 | 193 | using std::fabs; 194 | 195 | const dec1001_t closeness = fabs(1 - (h1f1 / control)); 196 | 197 | const auto result_is_ok = (closeness < (std::numeric_limits::epsilon() * static_cast(UINT8_C(10)))); 198 | 199 | return result_is_ok; 200 | } 201 | 202 | // Enable this if you would like to activate this main() as a standalone example. 203 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE010A_HYPERGEOMETRIC_1F1) 204 | 205 | #include 206 | #include 207 | 208 | auto main() -> int 209 | { 210 | const auto result_is_ok = ::math::wide_decimal::example010a_hypergeometric_1f1(); 211 | 212 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 213 | } 214 | 215 | #endif 216 | -------------------------------------------------------------------------------- /examples/example012_rational_floor_ceil.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2023. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #if defined(__clang__) 19 | #if defined __has_feature && (__has_feature(thread_sanitizer) || __has_feature(address_sanitizer)) 20 | #define DECWIDE_T_REDUCE_TEST_DEPTH 21 | #endif 22 | #elif defined(__GNUC__) 23 | #if defined(__SANITIZE_THREAD__) || defined(__SANITIZE_ADDRESS__) || defined(WIDE_DECIMAL_HAS_COVERAGE) 24 | #define DECWIDE_T_REDUCE_TEST_DEPTH 25 | #endif 26 | #endif 27 | 28 | namespace example012_rational 29 | { 30 | auto dist_sign() -> unsigned 31 | { 32 | static std::minstd_rand0 my_eng(util::util_pseudorandom_time_point_seed::value()); 33 | 34 | static std::uniform_int_distribution my_dist_sign 35 | ( 36 | 0U, 37 | 1U 38 | ); 39 | 40 | return my_dist_sign(my_eng); 41 | } 42 | 43 | constexpr auto lo_index_min = static_cast(INT32_C(101)); 44 | #if !defined(DECWIDE_T_REDUCE_TEST_DEPTH) 45 | constexpr auto lo_index_max = static_cast(INT32_C(1010)); 46 | #else 47 | constexpr auto lo_index_max = static_cast(INT32_C(210)); 48 | #endif 49 | constexpr auto hi_index_min = static_cast(INT32_C(10001)); 50 | constexpr auto hi_index_max = static_cast(INT32_C(40010)); 51 | 52 | static_assert(hi_index_min < hi_index_max, "Error hi_index_min must be less than hi_index_max"); 53 | static_assert(lo_index_min < lo_index_max, "Error lo_index_min must be less than lo_index_max"); 54 | 55 | template 56 | auto test_rational_floor() -> bool 57 | { 58 | using decimal_type = DecimalType; 59 | 60 | static_assert(std::numeric_limits::digits10 < 16, // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 61 | "Error: This test is designed for less than 16 decimal digits"); 62 | 63 | using decimal_type = DecimalType; 64 | 65 | bool result_is_ok = true; 66 | 67 | for(auto lo_index = lo_index_min; 68 | lo_index < lo_index_max; // NOLINT(altera-id-dependent-backward-branch) 69 | lo_index = static_cast(lo_index + static_cast(INT32_C(7)))) 70 | { 71 | for(auto hi_index = hi_index_min; 72 | hi_index < hi_index_max; // NOLINT(altera-id-dependent-backward-branch) 73 | hi_index = static_cast(hi_index + static_cast(INT32_C(17)))) 74 | { 75 | const auto lo_is_neg = static_cast(static_cast(dist_sign() % 2U) == static_cast(UINT8_C(0))); 76 | const auto hi_is_neg = static_cast(static_cast(dist_sign() % 2U) == static_cast(UINT8_C(0))); 77 | 78 | const auto lo = static_cast((!lo_is_neg) ? lo_index : -lo_index); 79 | const auto hi = static_cast((!hi_is_neg) ? hi_index : -hi_index); 80 | 81 | const auto lo_hi = static_cast(lo * hi); 82 | 83 | const decimal_type a = decimal_type { lo_hi } / decimal_type { lo }; 84 | const decimal_type b = floor(a); 85 | 86 | result_is_ok = ((static_cast(a) == b) && result_is_ok); 87 | 88 | if(!result_is_ok) 89 | { 90 | break; 91 | } 92 | } 93 | } 94 | 95 | return result_is_ok; 96 | } 97 | 98 | template 99 | auto test_rational_ceil() -> bool 100 | { 101 | using decimal_type = DecimalType; 102 | 103 | static_assert(std::numeric_limits::digits10 < 16, // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 104 | "Error: This test is designed for less than 16 decimal digits"); 105 | 106 | using decimal_type = DecimalType; 107 | 108 | bool result_is_ok = true; 109 | 110 | for(auto lo_index = lo_index_min; 111 | lo_index < lo_index_max; // NOLINT(altera-id-dependent-backward-branch) 112 | lo_index = static_cast(lo_index + static_cast(INT32_C(7)))) 113 | { 114 | for(auto hi_index = hi_index_min; 115 | hi_index < hi_index_max; // NOLINT(altera-id-dependent-backward-branch) 116 | hi_index = static_cast(hi_index + static_cast(INT32_C(17)))) 117 | { 118 | const auto lo_is_neg = static_cast(static_cast(dist_sign() % 2U) == static_cast(UINT8_C(0))); 119 | const auto hi_is_neg = static_cast(static_cast(dist_sign() % 2U) == static_cast(UINT8_C(0))); 120 | 121 | const auto lo = static_cast((!lo_is_neg) ? lo_index : -lo_index); 122 | const auto hi = static_cast((!hi_is_neg) ? hi_index : -hi_index); 123 | 124 | const auto lo_hi = static_cast(lo * hi); 125 | 126 | const decimal_type a = decimal_type { lo_hi } / decimal_type { lo }; 127 | const decimal_type b = ceil(a); 128 | 129 | result_is_ok = ((static_cast(a) == b) && result_is_ok); 130 | 131 | if(!result_is_ok) 132 | { 133 | break; 134 | } 135 | } 136 | } 137 | 138 | return result_is_ok; 139 | } 140 | } // namespace example012_rational 141 | 142 | #if defined(WIDE_DECIMAL_NAMESPACE) 143 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example012_rational_floor_ceil() -> bool 144 | #else 145 | auto ::math::wide_decimal::example012_rational_floor_ceil() -> bool 146 | #endif 147 | { 148 | bool result_is_ok = true; 149 | 150 | // Test floor/ceil for 10 decimal digits. 151 | { 152 | #if defined(WIDE_DECIMAL_NAMESPACE) 153 | using decimal_type = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t(INT32_C(10)), std::uint32_t, void>; 154 | #else 155 | using decimal_type = ::math::wide_decimal::decwide_t(INT32_C(10)), std::uint32_t, void>; 156 | #endif 157 | 158 | result_is_ok = (example012_rational::test_rational_floor() && result_is_ok); 159 | result_is_ok = (example012_rational::test_rational_ceil () && result_is_ok); 160 | } 161 | 162 | // Test floor/ceil for 12 decimal digits. 163 | { 164 | #if defined(WIDE_DECIMAL_NAMESPACE) 165 | using decimal_type = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t(INT32_C(12)), std::uint32_t, void>; 166 | #else 167 | using decimal_type = ::math::wide_decimal::decwide_t(INT32_C(12)), std::uint32_t, void>; 168 | #endif 169 | 170 | result_is_ok = (example012_rational::test_rational_floor() && result_is_ok); 171 | result_is_ok = (example012_rational::test_rational_ceil () && result_is_ok); 172 | } 173 | 174 | return result_is_ok; 175 | } 176 | 177 | // Enable this if you would like to activate this main() as a standalone example. 178 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE012_RATIONAL_FLOOR_CEIL) 179 | 180 | #include 181 | #include 182 | 183 | auto main() -> int 184 | { 185 | const auto result_is_ok = ::math::wide_decimal::example012_rational_floor_ceil(); 186 | 187 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 188 | } 189 | 190 | #endif 191 | -------------------------------------------------------------------------------- /examples/example013_embeddable_sqrt.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2022. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define WIDE_DECIMAL_DISABLE_IOSTREAM 14 | #define WIDE_DECIMAL_DISABLE_DYNAMIC_MEMORY_ALLOCATION 15 | #define WIDE_DECIMAL_DISABLE_CONSTRUCT_FROM_STRING 16 | #define WIDE_DECIMAL_DISABLE_CACHED_CONSTANTS 17 | #define WIDE_DECIMAL_DISABLE_USE_STD_FUNCTION 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #if defined(WIDE_DECIMAL_NAMESPACE) 24 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example013_embeddable_sqrt() -> bool 25 | #else 26 | auto ::math::wide_decimal::example013_embeddable_sqrt() -> bool 27 | #endif 28 | { 29 | using local_limb_type = std::uint16_t; 30 | 31 | constexpr std::int32_t wide_decimal_digits10 = INT32_C(101); 32 | 33 | #if defined(WIDE_DECIMAL_NAMESPACE) 34 | constexpr std::int32_t local_elem_number = 35 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::detail::decwide_t_helper::elem_number; 36 | #else 37 | constexpr std::int32_t local_elem_number = 38 | ::math::wide_decimal::detail::decwide_t_helper::elem_number; 39 | #endif 40 | 41 | using local_allocator_type = util::n_slot_array_allocator; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 42 | 43 | #if defined(WIDE_DECIMAL_NAMESPACE) 44 | using dec101_t = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t; 45 | #else 46 | using dec101_t = ::math::wide_decimal::decwide_t; 47 | #endif 48 | 49 | using std::sqrt; 50 | 51 | const dec101_t s = sqrt(dec101_t(123456U) / 100); 52 | 53 | // N[Sqrt[123456/100], 111] 54 | // 35.1363060095963986639333846404180557597515182871693145281659761647177108954528909286350312191322209780537650946 55 | 56 | dec101_t control; 57 | 58 | typename dec101_t::representation_type rep 59 | ( 60 | { 35U, 1363U, 600U, 9596U, 3986U, 6393U, 3384U, 6404U, 1805U, 5759U, 7515U, 1828U, 7169U, 3145U, 2816U, 5976U, 1647U, 1771U, 895U, 4528U, 9092U, 8635U, 312U, 1913U, 2220U, 9780U } // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 61 | ); 62 | 63 | std::copy(rep.cbegin(), rep.cend(), control.representation().begin()); 64 | 65 | using std::fabs; 66 | 67 | const dec101_t closeness = fabs(1 - (s / control)); 68 | 69 | const auto result_is_ok = (closeness < (std::numeric_limits::epsilon() * static_cast(UINT8_C(10)))); 70 | 71 | return result_is_ok; 72 | } 73 | 74 | // Enable this if you would like to activate this main() as a standalone example. 75 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE013_EMBEDDABLE_SQRT) 76 | 77 | #if !defined(WIDE_DECIMAL_DISABLE_IOSTREAM) 78 | #include 79 | #include 80 | #endif 81 | 82 | auto main() -> int 83 | { 84 | const auto result_is_ok = ::math::wide_decimal::example013_embeddable_sqrt(); 85 | 86 | #if !defined(WIDE_DECIMAL_DISABLE_IOSTREAM) 87 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 88 | #endif 89 | 90 | return (result_is_ok ? 0 : -1); 91 | } 92 | 93 | #endif // WIDE_DECIMAL_STANDALONE_EXAMPLE013_EMBEDDABLE_SQRT 94 | -------------------------------------------------------------------------------- /examples/example013a_embeddable_agm.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2022. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12)) 9 | #pragma GCC diagnostic push 10 | #pragma GCC diagnostic ignored "-Wstringop-overflow" 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #if (defined(__GNUC__) && defined(__AVR__)) 18 | #include 19 | 20 | #define MY_PROGMEM PROGMEM 21 | #else 22 | #define MY_PROGMEM 23 | #endif 24 | 25 | #define WIDE_DECIMAL_DISABLE_IOSTREAM 26 | #define WIDE_DECIMAL_DISABLE_DYNAMIC_MEMORY_ALLOCATION 27 | #define WIDE_DECIMAL_DISABLE_CONSTRUCT_FROM_STRING 28 | #define WIDE_DECIMAL_DISABLE_CACHED_CONSTANTS 29 | #define WIDE_DECIMAL_DISABLE_USE_STD_FUNCTION 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #if(__cplusplus >= 201703L) 36 | namespace mcal::memory::progmem { 37 | #else 38 | namespace mcal { namespace memory { namespace progmem { // NOLINT(modernize-concat-nested-namespaces) 39 | #endif 40 | 41 | using std::array; 42 | 43 | #if(__cplusplus >= 201703L) 44 | } // namespace mcal::memory::progmem 45 | #else 46 | } // namespace progmem 47 | } // namespace memory 48 | } // namespace mcal 49 | #endif 50 | 51 | #if defined(WIDE_DECIMAL_NAMESPACE) 52 | auto WIDE_DECIMAL_NAMESPACE::math::wide_decimal::example013a_embeddable_agm() -> bool 53 | #else 54 | auto ::math::wide_decimal::example013a_embeddable_agm() -> bool 55 | #endif 56 | { 57 | // N[Pi, 106] and truncate the final digit. 58 | using local_limb_type = std::uint16_t; 59 | 60 | constexpr std::int32_t wide_decimal_digits10 = INT32_C(53); 61 | 62 | #if defined(WIDE_DECIMAL_NAMESPACE) 63 | constexpr std::int32_t local_elem_number = 64 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::detail::decwide_t_helper::elem_number; 65 | #else 66 | constexpr std::int32_t local_elem_number = 67 | ::math::wide_decimal::detail::decwide_t_helper::elem_number; 68 | #endif 69 | 70 | using local_allocator_type = util::n_slot_array_allocator; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 71 | 72 | #if defined(WIDE_DECIMAL_NAMESPACE) 73 | using dec53_t = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t; 79 | #else 80 | using dec53_t = ::math::wide_decimal::decwide_t; 86 | #endif 87 | 88 | static const mcal::memory::progmem::array app_benchmark_pi_agm_control MY_PROGMEM = 89 | {{ 90 | static_cast(UINT16_C( 3)), 91 | static_cast(UINT16_C(1415)), 92 | static_cast(UINT16_C(9265)), 93 | static_cast(UINT16_C(3589)), 94 | static_cast(UINT16_C(7932)), 95 | static_cast(UINT16_C(3846)), 96 | static_cast(UINT16_C(2643)), 97 | static_cast(UINT16_C(3832)), 98 | static_cast(UINT16_C(7950)), 99 | static_cast(UINT16_C(2884)), 100 | static_cast(UINT16_C(1971)), 101 | static_cast(UINT16_C(6939)), 102 | static_cast(UINT16_C(9375)), 103 | static_cast(UINT16_C(1058)) 104 | }}; 105 | 106 | #if defined(WIDE_DECIMAL_NAMESPACE) 107 | const dec53_t my_pi = 108 | WIDE_DECIMAL_NAMESPACE::math::wide_decimal::pi(); 114 | #else 115 | const dec53_t my_pi = 116 | ::math::wide_decimal::pi(); 122 | #endif 123 | 124 | const auto result_is_ok = std::equal(app_benchmark_pi_agm_control.cbegin(), 125 | app_benchmark_pi_agm_control.cend(), 126 | my_pi.crepresentation().cbegin()); 127 | 128 | return result_is_ok; 129 | } 130 | 131 | // Enable this if you would like to activate this main() as a standalone example. 132 | #if defined(WIDE_DECIMAL_STANDALONE_EXAMPLE013A_EMBEDDABLE_AGM) 133 | 134 | #if !defined(WIDE_DECIMAL_DISABLE_IOSTREAM) 135 | #include 136 | #include 137 | #endif 138 | 139 | auto main() -> int 140 | { 141 | const auto result_is_ok = ::math::wide_decimal::example013a_embeddable_agm(); 142 | 143 | #if !defined(WIDE_DECIMAL_DISABLE_IOSTREAM) 144 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 145 | #endif 146 | 147 | return (result_is_ok ? 0 : -1); 148 | } 149 | 150 | #endif // WIDE_DECIMAL_STANDALONE_EXAMPLE013A_EMBEDDABLE_AGM 151 | 152 | #if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12)) 153 | #pragma GCC diagnostic pop 154 | #endif 155 | -------------------------------------------------------------------------------- /examples/example_decwide_t.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2021 - 2024. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #ifndef EXAMPLE_DECWIDE_T_2021_04_13_H // NOLINT(llvm-header-guard) 9 | #define EXAMPLE_DECWIDE_T_2021_04_13_H 10 | 11 | // This file contains function prototypes of the decwide_t examples. 12 | 13 | #include 14 | 15 | #if !defined(WIDE_DECIMAL_NAMESPACE_BEGIN) 16 | #error WIDE_DECIMAL_NAMESPACE_BEGIN is not defined. Ensure that is properly included. 17 | #endif 18 | 19 | #if !defined(WIDE_DECIMAL_NAMESPACE_END) 20 | #error WIDE_DECIMAL_NAMESPACE_END is not defined. Ensure that is properly included. 21 | #endif 22 | 23 | WIDE_DECIMAL_NAMESPACE_BEGIN 24 | 25 | #if(__cplusplus >= 201703L) 26 | namespace math::wide_decimal { 27 | #else 28 | namespace math { namespace wide_decimal { // NOLINT(modernize-concat-nested-namespaces) 29 | #endif 30 | 31 | auto example000_multiply_nines () -> bool; 32 | auto example000a_multiply_pi_squared () -> bool; 33 | auto example001_roots_sqrt () -> bool; 34 | auto example001a_roots_seventh () -> bool; 35 | auto example001b_roots_almost_integer () -> bool; 36 | auto example001c_roots_sqrt_limb08 () -> bool; 37 | auto example001d_pow2_from_list () -> bool; 38 | auto example001e_algebra_and_constexpr () -> bool; 39 | auto example002_pi () -> bool; 40 | auto example002a_pi_small_limb () -> bool; 41 | auto example002b_pi_100k () -> bool; 42 | auto example002c_pi_quintic () -> bool; 43 | auto example002d_pi_limb08 () -> bool; 44 | auto example003_zeta () -> bool; 45 | auto example004_bessel_recur () -> bool; 46 | auto example005_polylog_series () -> bool; 47 | auto example006_logarithm () -> bool; 48 | auto example007_catalan_series () -> bool; 49 | auto example008_bernoulli_tgamma () -> bool; 50 | auto example009_boost_math_standalone () -> bool; 51 | auto example009a_boost_math_standalone () -> bool; 52 | auto example009b_boost_math_standalone () -> bool; 53 | auto example010_hypergeometric_2f1 () -> bool; 54 | auto example010a_hypergeometric_1f1 () -> bool; 55 | auto example011_trig_trapezoid_integral() -> bool; 56 | auto example012_rational_floor_ceil () -> bool; 57 | auto example013_embeddable_sqrt () -> bool; 58 | auto example013a_embeddable_agm () -> bool; 59 | 60 | #if(__cplusplus >= 201703L) 61 | } // namespace math::wide_decimal 62 | #else 63 | } // namespace wide_decimal 64 | } // namespace math 65 | #endif 66 | 67 | WIDE_DECIMAL_NAMESPACE_END 68 | 69 | #endif // EXAMPLE_DECWIDE_T_2021_04_13_H 70 | -------------------------------------------------------------------------------- /math/wide_decimal/decwide_t_detail_namespace.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2022 - 2024. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #ifndef DECWIDE_T_DETAIL_NAMESPACE_2022_02_15_H // NOLINT(llvm-header-guard) 9 | #define DECWIDE_T_DETAIL_NAMESPACE_2022_02_15_H 10 | 11 | #if defined(WIDE_DECIMAL_NAMESPACE_BEGIN) || defined(WIDE_DECIMAL_NAMESPACE_END) 12 | #error internal pre-processor macro already defined 13 | #endif 14 | 15 | #if defined(WIDE_DECIMAL_NAMESPACE) 16 | #define WIDE_DECIMAL_NAMESPACE_BEGIN namespace WIDE_DECIMAL_NAMESPACE { // NOLINT(cppcoreguidelines-macro-usage) 17 | #define WIDE_DECIMAL_NAMESPACE_END } // namespace WIDE_DECIMAL_NAMESPACE // NOLINT(cppcoreguidelines-macro-usage) 18 | #else 19 | #define WIDE_DECIMAL_NAMESPACE_BEGIN 20 | #define WIDE_DECIMAL_NAMESPACE_END 21 | #endif 22 | 23 | #endif // DECWIDE_T_DETAIL_NAMESPACE_2022_02_15_H 24 | -------------------------------------------------------------------------------- /mcal_lcd/mcal_lcd_base.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2022. 3 | // Distributed under the Boost Software License, 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #ifndef MCAL_LCD_BASE_2020_06_10_H // NOLINT(llvm-header-guard) 9 | #define MCAL_LCD_BASE_2020_06_10_H 10 | 11 | #include 12 | 13 | #include 14 | 15 | #if(__cplusplus >= 201703L) 16 | namespace mcal::lcd { 17 | #else 18 | namespace mcal { namespace lcd { // NOLINT(modernize-concat-nested-namespaces) 19 | #endif 20 | 21 | class lcd_base : private util::noncopyable // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) 22 | { 23 | public: 24 | virtual ~lcd_base() = default; 25 | 26 | virtual auto init() -> bool = 0; 27 | 28 | virtual auto write(const char* pstr, 29 | std::uint_fast8_t length, 30 | std::uint_fast8_t line_index) -> bool = 0; 31 | 32 | protected: 33 | lcd_base() = default; // LCOV_EXCL_LINE 34 | 35 | virtual auto set_line_index(const std::uint8_t index) -> bool { static_cast(index); return true; } // LCOV_EXCL_LINE 36 | }; 37 | 38 | #if(__cplusplus >= 201703L) 39 | } // namespace mcal::lcd 40 | #else 41 | } // namespace lcd 42 | } // namespace mcal 43 | #endif 44 | 45 | #endif // MCAL_LCD_BASE_2020_06_10_H 46 | -------------------------------------------------------------------------------- /mcal_lcd/mcal_lcd_console.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2022. 3 | // Distributed under the Boost Software License, 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #ifndef MCAL_LCD_CONSOLE_2020_06_10_H // NOLINT(llvm-header-guard) 9 | #define MCAL_LCD_CONSOLE_2020_06_10_H 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #if(__cplusplus >= 201703L) 17 | namespace mcal::lcd { 18 | #else 19 | namespace mcal { namespace lcd { // NOLINT(modernize-concat-nested-namespaces) 20 | #endif 21 | 22 | class lcd_console : public mcal::lcd::lcd_base // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) 23 | { 24 | public: 25 | lcd_console() = default; // LCOV_EXCL_LINE 26 | 27 | ~lcd_console() override = default; 28 | 29 | auto write(const char* pstr, 30 | std::uint_fast8_t length, // NOLINT(bugprone-easily-swappable-parameters) 31 | std::uint_fast8_t line_index) -> bool override 32 | { 33 | static_cast(line_index); 34 | 35 | bool write_is_ok { }; 36 | 37 | if((pstr != nullptr) && (length > 0U)) 38 | { 39 | const std::string str(pstr, pstr + length); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 40 | 41 | std::cout << str << std::endl; 42 | 43 | write_is_ok = true; 44 | } 45 | else 46 | { 47 | write_is_ok = false; 48 | } 49 | 50 | return write_is_ok; 51 | } 52 | 53 | auto init() -> bool override { return true; } // LCOV_EXCL_LINE 54 | }; 55 | 56 | #if(__cplusplus >= 201703L) 57 | } // namespace mcal::lcd 58 | #else 59 | } // namespace lcd 60 | } // namespace mcal 61 | #endif 62 | 63 | #endif // MCAL_LCD_CONSOLE_2020_06_10_H 64 | -------------------------------------------------------------------------------- /mcal_lcd/mcal_lcd_generic_st7066.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2024. 3 | // Distributed under the Boost Software License, 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #ifndef MCAL_LCD_GENERIC_ST7066_2020_05_07_H // NOLINT(llvm-header-guard) 9 | #define MCAL_LCD_GENERIC_ST7066_2020_05_07_H 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #if(__cplusplus >= 201703L) 21 | namespace mcal::lcd { 22 | #else 23 | namespace mcal { namespace lcd { // NOLINT(modernize-concat-nested-namespaces) 24 | #endif 25 | 26 | template 38 | class lcd_generic_st7066 final : public mcal::lcd::lcd_base 39 | { 40 | private: 41 | using timer_type = util::timer; 42 | 43 | public: 44 | lcd_generic_st7066() = default; 45 | 46 | ~lcd_generic_st7066() override = default; 47 | 48 | auto init(void) -> bool override 49 | { 50 | port_pin_rs__type::set_pin_low(); 51 | port_pin_rw__type::set_pin_low(); 52 | port_pin_e___type::set_pin_high(); 53 | 54 | P1_set(UINT8_C(0)); 55 | 56 | port_pin_rs__type::set_direction_output(); 57 | port_pin_rw__type::set_direction_output(); 58 | port_pin_e___type::set_direction_output(); 59 | 60 | P1_set_direction_output(); 61 | 62 | port_pin_e___type::set_pin_low(); 63 | 64 | blocking_delay(timer_type::milliseconds(15U)); // Set a timer which is at least 15ms from system start. 65 | command(UINT8_C(0x30)); // Command 0x30 = Wake up 66 | blocking_delay(timer_type::milliseconds(7U)); // Must wait 5ms, busy flag not available. 67 | command(UINT8_C(0x30)); // Command 0x30 = Wake up 2 68 | blocking_delay(timer_type::microseconds(200U)); // Must wait 160us, busy flag not available 69 | command(UINT8_C(0x30)); // Command 0x30 = Wake up 3 70 | blocking_delay(timer_type::microseconds(200U)); // Must wait 160us, busy flag not available 71 | command(UINT8_C(0x38)); // Function set: 8-bit/2-line 72 | command(UINT8_C(0x10)); // Set cursor 73 | command(UINT8_C(0x0C)); // Display ON; Cursor ON 74 | command(UINT8_C(0x06)); // Entry mode set 75 | 76 | const auto write_clear_lines_is_ok = ( write_n(nullptr, 0U, 0U) 77 | && write_n(nullptr, 0U, 1U)); 78 | 79 | 80 | return write_clear_lines_is_ok; 81 | } 82 | 83 | auto write(const char* pstr, 84 | std::uint_fast8_t length, 85 | std::uint_fast8_t line_index) -> bool override 86 | { 87 | std::uint_fast8_t char_index = 0U; 88 | 89 | command(std::uint8_t(0x80U + ((line_index == 0U) ? 0x00U : 0x40U))); 90 | 91 | if(pstr != nullptr) 92 | { 93 | // Write the line at line_index. 94 | for( ; char_index < (std::min)(lcd_line_width, length); ++char_index) 95 | { 96 | write(std::uint8_t(pstr[char_index])); 97 | } 98 | } 99 | 100 | for( ; char_index < lcd_line_width; ++char_index) 101 | { 102 | write(std::uint8_t(char(' '))); 103 | } 104 | 105 | return true; 106 | } 107 | 108 | private: 109 | static void blocking_delay(const typename timer_type::tick_type blocking_delay_value) 110 | { 111 | timer_type::blocking_delay(blocking_delay_value); 112 | } 113 | 114 | auto write(const std::uint8_t i) -> void 115 | { 116 | P1_set(i); // P1 = i; // Put data on the output Port 117 | port_pin_rs__type::set_pin_high(); // D_I =1; // D/I=HIGH : send data 118 | port_pin_rw__type::set_pin_low(); // R_W =0; // R/W=LOW : Write 119 | port_pin_e___type::set_pin_high(); // E = 1; 120 | blocking_delay(timer_type::microseconds(10U)); // Delay(1); // Enable pulse width >= 300ns 121 | port_pin_e___type::set_pin_low(); // E = 0; // Clock enable: falling edge 122 | } 123 | 124 | auto command(std::uint8_t i) -> void 125 | { 126 | P1_set(i); // P1 = i; // Put data on output Port 127 | port_pin_rs__type::set_pin_low(); // D_I =0; // D/I=LOW : send instruction 128 | port_pin_rw__type::set_pin_low(); // R_W =0; // R/W=LOW : Write 129 | port_pin_e___type::set_pin_high(); // E = 1; 130 | blocking_delay(timer_type::microseconds(10U)); // Delay(1); // Enable pulse width >= 300ns 131 | port_pin_e___type::set_pin_low(); // E = 0; // Clock enable: falling edge 132 | blocking_delay(timer_type::microseconds(40U)); // Command execution delay 133 | } 134 | 135 | auto P1_set(const std::uint8_t c) -> void 136 | { 137 | (static_cast(c & UINT8_C(0x01)) != UINT8_C(0)) ? port_pin_db0_type::set_pin_high() : port_pin_db0_type::set_pin_low(); 138 | (static_cast(c & UINT8_C(0x02)) != UINT8_C(0)) ? port_pin_db1_type::set_pin_high() : port_pin_db1_type::set_pin_low(); 139 | (static_cast(c & UINT8_C(0x04)) != UINT8_C(0)) ? port_pin_db2_type::set_pin_high() : port_pin_db2_type::set_pin_low(); 140 | (static_cast(c & UINT8_C(0x08)) != UINT8_C(0)) ? port_pin_db3_type::set_pin_high() : port_pin_db3_type::set_pin_low(); 141 | (static_cast(c & UINT8_C(0x10)) != UINT8_C(0)) ? port_pin_db4_type::set_pin_high() : port_pin_db4_type::set_pin_low(); 142 | (static_cast(c & UINT8_C(0x20)) != UINT8_C(0)) ? port_pin_db5_type::set_pin_high() : port_pin_db5_type::set_pin_low(); 143 | (static_cast(c & UINT8_C(0x40)) != UINT8_C(0)) ? port_pin_db6_type::set_pin_high() : port_pin_db6_type::set_pin_low(); 144 | (static_cast(c & UINT8_C(0x80)) != UINT8_C(0)) ? port_pin_db7_type::set_pin_high() : port_pin_db7_type::set_pin_low(); 145 | } 146 | 147 | static auto P1_set_direction_output() -> void 148 | { 149 | port_pin_db0_type::set_direction_output(); 150 | port_pin_db1_type::set_direction_output(); 151 | port_pin_db2_type::set_direction_output(); 152 | port_pin_db3_type::set_direction_output(); 153 | port_pin_db4_type::set_direction_output(); 154 | port_pin_db5_type::set_direction_output(); 155 | port_pin_db6_type::set_direction_output(); 156 | port_pin_db7_type::set_direction_output(); 157 | } 158 | }; 159 | 160 | #if(__cplusplus >= 201703L) 161 | } // namespace mcal::lcd 162 | #else 163 | } // namespace lcd 164 | } // namespace mcal 165 | #endif 166 | 167 | #endif // MCAL_LCD_GENERIC_ST7066_2020_05_07_H 168 | -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | sonar.projectKey=ckormanyos_wide-decimal 2 | sonar.organization=ckormanyos 3 | 4 | # This is the name and version displayed in the SonarCloud UI. 5 | #sonar.projectName=wide-decimal 6 | sonar.projectVersion=1.0 7 | 8 | # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. 9 | sonar.sources=. 10 | 11 | # Encoding of the source code. Default is default system encoding 12 | #sonar.sourceEncoding=UTF-8 13 | 14 | sonar.python.version=3.10 15 | -------------------------------------------------------------------------------- /target/build/test_examples_emulator.gdb: -------------------------------------------------------------------------------- 1 | # /////////////////////////////////////////////////////////////////// 2 | # // Copyright Christopher Kormanyos 2020 - 2024. 3 | # // Distributed under the Boost Software License, 4 | # // Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | # // or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | # // 7 | 8 | # Connect to the target (e.g., OpenOCD or another GDB server). 9 | target remote localhost:9999 10 | monitor halt 11 | 12 | # Ensure that the program is loaded. 13 | load 14 | 15 | # Set a breakpoint at the specified subroutine. 16 | break example_get_standalone_result 17 | 18 | # Start or continue program execution. 19 | continue 20 | 21 | # Format and print the value of a variable. 22 | printf "value 0x%X\n\n", example_standalone_result 23 | 24 | # Delete (all) breakpoint(s). 25 | delete 26 | 27 | # Perform a non-elegant quit of the GDB session. 28 | quit 29 | -------------------------------------------------------------------------------- /target/micros/stm32f429/make/stm32f429.ld: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Copyright Christopher Kormanyos 2007 - 2022. 4 | Distributed under the Boost Software License, 5 | Version 1.0. (See accompanying file LICENSE_1_0.txt 6 | or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | */ 8 | 9 | /* Linker script for STM32F4xx ARM(R) Cortex(TM)-M4 MCU */ 10 | 11 | ENTRY(__my_startup) 12 | 13 | INPUT(libc.a libm.a libgcc.a) 14 | 15 | OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 16 | OUTPUT_ARCH(arm) 17 | 18 | /* The beginning and end of the program ROM area */ 19 | /* Set up a ROM area with a size of 512K */ 20 | _rom_begin = 0x08000000; 21 | _rom_end = 0x08080000; 22 | 23 | /* The beginning and end (i.e., the top) of the stack */ 24 | /* Set up a stack with a size of 16K */ 25 | _stack_begin = 0x2001C000; 26 | _stack_end = 0x20020000; 27 | 28 | __initial_stack_pointer = 0x20020000 - 4; 29 | 30 | MEMORY 31 | { 32 | ROM(rx) : ORIGIN = 0x08000000, LENGTH = 512K 33 | RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 128K - 16K 34 | } 35 | 36 | SECTIONS 37 | { 38 | . = 0x08000000; 39 | . = ALIGN(4); 40 | 41 | /* ISR vectors */ 42 | .isr_vector : 43 | { 44 | *(.isr_vector) 45 | . = ALIGN(0x10); 46 | KEEP(*(.isr_vector)) 47 | } > ROM = 0xAAAA 48 | 49 | /* startup */ 50 | .startup : 51 | { 52 | *(.startup) 53 | . = ALIGN(0x10); 54 | KEEP(*(.startup)) 55 | } > ROM = 0x5555 56 | 57 | /* Program code (text), read-only data and static ctors */ 58 | .text : 59 | { 60 | _ctors_begin = .; 61 | KEEP(*(SORT(.init_array.*))) 62 | KEEP(*(.init_array*)) 63 | _ctors_end = .; 64 | *(.progmem*) 65 | . = ALIGN(4); 66 | *(.text) 67 | . = ALIGN(4); 68 | *(.text*) 69 | . = ALIGN(4); 70 | *(.rodata) 71 | . = ALIGN(4); 72 | *(.rodata*) 73 | . = ALIGN(4); 74 | *(.glue_7) 75 | . = ALIGN(4); 76 | *(.glue_7t) 77 | . = ALIGN(4); 78 | } > ROM 79 | 80 | .ARM.extab : 81 | { 82 | . = ALIGN(4); 83 | *(.ARM.extab) 84 | *(.gnu.linkonce.armextab.*) 85 | . = ALIGN(4); 86 | } > ROM 87 | 88 | .exidx : 89 | { 90 | . = ALIGN(4); 91 | PROVIDE(__exidx_start = .); 92 | *(.ARM.exidx*) 93 | . = ALIGN(4); 94 | PROVIDE(__exidx_end = .); 95 | } > ROM 96 | 97 | .ARM.attributes : 98 | { 99 | *(.ARM.attributes) 100 | } > ROM 101 | 102 | . = 0x20000000; 103 | . = ALIGN(4); 104 | 105 | /* The ROM-to-RAM initialized data section */ 106 | .data : 107 | { 108 | _data_begin = .; 109 | *(.data) 110 | . = ALIGN(4); 111 | KEEP (*(.data)) 112 | *(.data*) 113 | . = ALIGN(4); 114 | KEEP (*(.data*)) 115 | _data_end = .; 116 | } > RAM AT > ROM 117 | 118 | /* The uninitialized (zero-cleared) data section */ 119 | .bss : 120 | { 121 | _bss_begin = .; 122 | *(.bss) 123 | . = ALIGN(4); 124 | KEEP (*(.bss)) 125 | *(.bss*) 126 | . = ALIGN(4); 127 | KEEP (*(.bss*)) 128 | _bss_end = .; 129 | } > RAM 130 | 131 | PROVIDE(end = .); 132 | PROVIDE(_fini = .); 133 | 134 | _rom_data_begin = LOADADDR(.data); 135 | } 136 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | enable_testing() 2 | find_package(Threads) 3 | if (Boost_FOUND) 4 | add_executable(test_decwide_t 5 | test_decwide_t_algebra.cpp 6 | test_decwide_t_algebra_edge.cpp 7 | test_decwide_t_examples.cpp 8 | test.cpp) 9 | target_compile_features(test_decwide_t PRIVATE cxx_std_14) 10 | target_include_directories(test_decwide_t PRIVATE ${PROJECT_SOURCE_DIR}) 11 | target_link_libraries(test_decwide_t Examples ${CMAKE_THREAD_LIBS_INIT}) 12 | add_test(test test_decwide_t) 13 | endif() 14 | -------------------------------------------------------------------------------- /test/coverity.c: -------------------------------------------------------------------------------- 1 | /* Coverity Scan model */ 2 | 3 | void dummy(void) 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /test/independent_algebra_test_decwide_t_base.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2023. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #ifndef INDEPENDENT_ALGEBRA_TEST_DECWIDE_T_BASE_2020_10_17_H // NOLINT(llvm-header-guard) 9 | #define INDEPENDENT_ALGEBRA_TEST_DECWIDE_T_BASE_2020_10_17_H 10 | 11 | #include 12 | 13 | #include 14 | 15 | WIDE_DECIMAL_NAMESPACE_BEGIN 16 | 17 | #if(__cplusplus >= 201703L) 18 | namespace test::independent_algebra { 19 | #else 20 | namespace test { namespace independent_algebra { // NOLINT(modernize-concat-nested-namespaces) 21 | #endif 22 | 23 | class independent_algebra_test_decwide_t_base // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) 24 | { 25 | public: 26 | virtual ~independent_algebra_test_decwide_t_base() = default; 27 | 28 | virtual void get_string(std::string&, bool) const = 0; // NOLINT(google-runtime-references) 29 | 30 | protected: 31 | independent_algebra_test_decwide_t_base() = default; 32 | }; 33 | 34 | #if(__cplusplus >= 201703L) 35 | } // namespace test::independent_algebra 36 | #else 37 | } // namespace independent_algebra 38 | } // namespace test 39 | #endif 40 | 41 | WIDE_DECIMAL_NAMESPACE_END 42 | 43 | #endif // INDEPENDENT_ALGEBRA_TEST_DECWIDE_T_BASE_2020_10_17_H 44 | -------------------------------------------------------------------------------- /test/independent_algebra_test_decwide_t_constants.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2022. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #ifndef INDEPENDENT_ALGEBRA_TEST_DECWIDE_T_CONSTANTS_2022_02_11_H // NOLINT(llvm-header-guard) 9 | #define INDEPENDENT_ALGEBRA_TEST_DECWIDE_T_CONSTANTS_2022_02_11_H 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | WIDE_DECIMAL_NAMESPACE_BEGIN 17 | 18 | #if(__cplusplus >= 201703L) 19 | namespace test::independent_algebra { 20 | #else 21 | namespace test { namespace independent_algebra { // NOLINT(modernize-concat-nested-namespaces) 22 | #endif 23 | 24 | template 25 | struct constants; 26 | 27 | template 28 | struct constants 29 | { 30 | private: 31 | using floating_point_type = FloatingPointType; 32 | 33 | struct initializer 34 | { 35 | // Static data initializer 36 | initializer() 37 | { 38 | constants::my_value_pi (); 39 | constants::my_value_ln_two(); 40 | } 41 | 42 | initializer(const initializer&) = delete; 43 | initializer(initializer&&) = delete; 44 | 45 | auto operator=(const initializer&) -> initializer& = delete; 46 | auto operator=(initializer&&) noexcept -> initializer& = delete; 47 | 48 | ~initializer() = default; // LCOV_EXCL_LINE 49 | 50 | // LCOV_EXCL_START 51 | auto do_nothing() const -> void 52 | { 53 | // Do nothing on purpose. 54 | } 55 | // LCOV_EXCL_STOP 56 | }; 57 | 58 | static initializer init; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) 59 | 60 | public: 61 | static auto my_value_pi() -> const floating_point_type& 62 | { 63 | init.do_nothing(); 64 | static const floating_point_type val(constants::calc_pi()); 65 | return val; 66 | } 67 | 68 | static auto my_value_ln_two() -> const floating_point_type& 69 | { 70 | init.do_nothing(); 71 | static const floating_point_type val(constants::calc_ln_two()); 72 | return val; 73 | } 74 | 75 | private: 76 | static auto calc_pi() -> floating_point_type 77 | { 78 | // Use a quadratically convergent Gauss AGM to compute pi. 79 | 80 | floating_point_type val_pi; 81 | 82 | floating_point_type a(1U); 83 | 84 | // Initialize bB to 0.5. 85 | floating_point_type bB(0.5F); // NOLINT(readability-identifier-naming,cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 86 | 87 | // Initialize t to 0.375. 88 | floating_point_type t(static_cast(3U) / 8U); // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 89 | 90 | floating_point_type s(bB); 91 | 92 | // This loop is designed for a maximum of several million 93 | // decimal digits of pi. The index k should reach no higher 94 | // than about 25 or 30. After about 20 iterations, the precision 95 | // is about one million decimal digits. 96 | 97 | const auto digits10_iteration_goal = 98 | static_cast 99 | ( 100 | static_cast(std::numeric_limits::digits10 / 2) 101 | + static_cast(9U) 102 | ); 103 | 104 | using std::log; 105 | using std::lround; 106 | 107 | const auto digits10_scale = 108 | static_cast 109 | ( 110 | lround 111 | ( 112 | static_cast(1000.0F * log(static_cast(std::numeric_limits::radix))) / log(10.0F) 113 | ) 114 | ); 115 | 116 | for(auto k = static_cast(UINT8_C(0)); 117 | k < static_cast(UINT8_C(48)); 118 | ++k) 119 | { 120 | using std::sqrt; 121 | 122 | a += sqrt(bB); 123 | a /= 2U; 124 | val_pi = a; 125 | val_pi *= a; 126 | bB = val_pi; 127 | bB -= t; 128 | bB *= 2U; 129 | 130 | floating_point_type iterate_term(bB); 131 | 132 | iterate_term -= val_pi; 133 | iterate_term *= static_cast(1ULL << (k + 1U)); // NOLINT(google-runtime-int) 134 | 135 | s += iterate_term; 136 | 137 | // Test the number of precise digits from this iteration. 138 | // If it is there are enough precise digits, then the calculation 139 | // is finished. 140 | const auto ib = 141 | (std::max) 142 | ( 143 | static_cast(INT8_C(0)), 144 | static_cast(-ilogb(iterate_term)) 145 | ); 146 | 147 | const auto digits10_of_iteration = 148 | static_cast 149 | ( 150 | static_cast(static_cast(ib) * digits10_scale) / UINT32_C(1000) 151 | ); 152 | 153 | // Estimate the approximate decimal digits of this iteration term. 154 | // If we have attained about half of the total desired digits 155 | // with this iteration term, then the calculation is finished 156 | // because the change from the next iteration will be 157 | // insignificantly small. 158 | 159 | if(digits10_of_iteration > digits10_iteration_goal) 160 | { 161 | break; 162 | } 163 | 164 | t = val_pi; 165 | t += bB; 166 | t /= 4U; 167 | } 168 | 169 | return (val_pi + bB) / s; 170 | } 171 | 172 | static auto calc_ln_two() -> floating_point_type 173 | { 174 | // Use an AGM method to compute log(2). 175 | 176 | // Set a0 = 1 177 | // Set b0 = 1 / (2^(m-2)) 178 | 179 | floating_point_type ak(1U); 180 | 181 | constexpr auto n_times_factor = 182 | static_cast 183 | ( 184 | static_cast(std::numeric_limits::digits10) * 1.67F 185 | ); 186 | 187 | // Ensure that the resulting power is non-negative. 188 | // Also enforce that m >= 3. 189 | const auto m = 190 | (std::max) 191 | ( 192 | static_cast(n_times_factor), 193 | static_cast(3) 194 | ); 195 | 196 | floating_point_type bk = 197 | ldexp(floating_point_type(1U), static_cast(2 - m)); 198 | 199 | const auto digits10_iteration_goal = 200 | static_cast 201 | ( 202 | static_cast(std::numeric_limits::digits10 / 2) 203 | + static_cast(9U) 204 | ); 205 | 206 | using std::log; 207 | using std::lround; 208 | 209 | const auto digits10_scale = 210 | static_cast 211 | ( 212 | lround 213 | ( 214 | static_cast(1000.0F * log(static_cast(std::numeric_limits::radix))) / log(10.0F) 215 | ) 216 | ); 217 | 218 | for(auto k = static_cast(INT8_C(0)); 219 | k < static_cast(INT8_C(64)); 220 | ++k) 221 | { 222 | using std::ilogb; 223 | 224 | // Check for the number of significant digits to be 225 | // at least half of the requested digits. If at least 226 | // half of the requested digits have been achieved, 227 | // then break after the upcoming iteration. 228 | 229 | const auto ib = (std::max)(static_cast(0), 230 | static_cast(-ilogb(ak - bk))); 231 | 232 | const auto digits10_of_iteration = 233 | static_cast 234 | ( 235 | static_cast(static_cast(ib) * digits10_scale) / UINT32_C(1000) 236 | ); 237 | 238 | const floating_point_type ak_tmp(ak); 239 | 240 | ak += bk; 241 | 242 | if(digits10_of_iteration > digits10_iteration_goal) 243 | { 244 | break; 245 | } 246 | 247 | using std::sqrt; 248 | 249 | ak /= 2; 250 | bk *= ak_tmp; 251 | bk = sqrt(bk); 252 | } 253 | 254 | // We are now finished with the AGM iteration for log(2). 255 | // Note at this time that (ak = bk) = AGM(...) 256 | // Retrieve the value of pi and divide by (a * (2 * m)). 257 | 258 | return my_value_pi() / (ak * m); 259 | } 260 | }; 261 | 262 | template 263 | typename constants::initializer constants::init; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables,cert-err58-cpp) 264 | 265 | #if(__cplusplus >= 201703L) 266 | } // namespace test::independent_algebra 267 | #else 268 | } // namespace independent_algebra 269 | } // namespace test 270 | #endif 271 | 272 | WIDE_DECIMAL_NAMESPACE_END 273 | 274 | #endif // INDEPENDENT_ALGEBRA_TEST_DECWIDE_T_CONSTANTS_2022_02_11_H 275 | -------------------------------------------------------------------------------- /test/independent_algebra_test_decwide_t_wide_decimal.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2023. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #ifndef INDEPENDENT_ALGEBRA_TEST_DECWIDE_T_WIDE_DECIMAL_2020_10_17_H // NOLINT(llvm-header-guard) 9 | #define INDEPENDENT_ALGEBRA_TEST_DECWIDE_T_WIDE_DECIMAL_2020_10_17_H 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | WIDE_DECIMAL_NAMESPACE_BEGIN 18 | 19 | #if(__cplusplus >= 201703L) 20 | namespace test::independent_algebra { 21 | #else 22 | namespace test { namespace independent_algebra { // NOLINT(modernize-concat-nested-namespaces) 23 | #endif 24 | 25 | template 26 | class independent_algebra_test_decwide_t_decwide_t : public independent_algebra_test_decwide_t_base // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) 27 | { 28 | public: 29 | #if defined(WIDE_DECIMAL_NAMESPACE) 30 | using float_type = WIDE_DECIMAL_NAMESPACE::math::wide_decimal::decwide_t; 31 | #else 32 | using float_type = ::math::wide_decimal::decwide_t; 33 | #endif 34 | 35 | float_type my_decwide_t; // NOLINT(misc-non-private-member-variables-in-classes) 36 | 37 | independent_algebra_test_decwide_t_decwide_t() : my_decwide_t() { } 38 | 39 | explicit independent_algebra_test_decwide_t_decwide_t(const char* str) 40 | : my_decwide_t(str) { } 41 | 42 | ~independent_algebra_test_decwide_t_decwide_t() override = default; 43 | 44 | auto get_string(std::string& str, bool use_fixed) const -> void override 45 | { 46 | std::stringstream ss; 47 | 48 | ss << ((!use_fixed) ? std::scientific : std::fixed) 49 | << std::uppercase 50 | << std::setprecision(static_cast(std::numeric_limits::digits10 + 1)) 51 | << my_decwide_t; 52 | 53 | str = ss.str(); 54 | } 55 | }; 56 | 57 | template 58 | auto eval_add( independent_algebra_test_decwide_t_decwide_t& result, 59 | const independent_algebra_test_decwide_t_decwide_t& a, 60 | const independent_algebra_test_decwide_t_decwide_t& b) -> void 61 | { 62 | result.my_decwide_t = a.my_decwide_t + b.my_decwide_t; 63 | } 64 | 65 | template 66 | auto eval_sub( independent_algebra_test_decwide_t_decwide_t& result, 67 | const independent_algebra_test_decwide_t_decwide_t& a, 68 | const independent_algebra_test_decwide_t_decwide_t& b) -> void 69 | { 70 | result.my_decwide_t = a.my_decwide_t - b.my_decwide_t; 71 | } 72 | 73 | template 74 | auto eval_mul( independent_algebra_test_decwide_t_decwide_t& result, 75 | const independent_algebra_test_decwide_t_decwide_t& a, 76 | const independent_algebra_test_decwide_t_decwide_t& b) -> void 77 | { 78 | result.my_decwide_t = a.my_decwide_t * b.my_decwide_t; 79 | } 80 | 81 | template 82 | auto eval_div( independent_algebra_test_decwide_t_decwide_t& result, 83 | const independent_algebra_test_decwide_t_decwide_t& a, 84 | const independent_algebra_test_decwide_t_decwide_t& b) -> void 85 | { 86 | result.my_decwide_t = a.my_decwide_t / b.my_decwide_t; 87 | } 88 | 89 | template 90 | auto eval_sqrt( independent_algebra_test_decwide_t_decwide_t& result, 91 | const independent_algebra_test_decwide_t_decwide_t& a) -> void 92 | { 93 | result.my_decwide_t = sqrt(a.my_decwide_t); 94 | } 95 | 96 | template 97 | auto eval_log( independent_algebra_test_decwide_t_decwide_t& result, 98 | const independent_algebra_test_decwide_t_decwide_t& a) -> void 99 | { 100 | result.my_decwide_t = log(a.my_decwide_t); 101 | } 102 | 103 | #if(__cplusplus >= 201703L) 104 | } // namespace test::independent_algebra 105 | #else 106 | } // namespace independent_algebra 107 | } // namespace test 108 | #endif 109 | 110 | WIDE_DECIMAL_NAMESPACE_END 111 | 112 | #endif // INDEPENDENT_ALGEBRA_TEST_DECWIDE_T_WIDE_DECIMAL_2020_10_17_H 113 | -------------------------------------------------------------------------------- /test/parallel_for.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2017 - 2023. 3 | // Distributed under the Boost Software License, 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #ifndef PARALLEL_FOR_2017_12_18_H // NOLINT(llvm-header-guard) 9 | #define PARALLEL_FOR_2017_12_18_H 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace my_concurrency 16 | { 17 | template 19 | auto parallel_for(index_type start, 20 | index_type end, 21 | callable_function_type parallel_function) -> void 22 | { 23 | // Estimate the number of threads available. 24 | const auto number_of_threads_hint = 25 | static_cast 26 | ( 27 | std::thread::hardware_concurrency() 28 | ); 29 | 30 | const auto number_of_threads = // NOLINT(altera-id-dependent-backward-branch) 31 | static_cast 32 | ( 33 | (number_of_threads_hint == static_cast(UINT8_C(0))) ? static_cast(UINT8_C(4)) : number_of_threads_hint // NOLINT(altera-id-dependent-backward-branch) 34 | ); 35 | 36 | // Set the size of a slice for the range functions. 37 | const auto n = 38 | static_cast 39 | ( 40 | static_cast(end - start) + static_cast(1) 41 | ); 42 | 43 | const auto slice = 44 | (std::max) 45 | ( 46 | static_cast(std::round(static_cast(n) / static_cast(number_of_threads))), 47 | static_cast(1) 48 | ); 49 | 50 | // Inner loop. 51 | const auto launch_range = 52 | [¶llel_function](index_type index_lo, index_type index_hi) 53 | { 54 | for(auto i = index_lo; i < index_hi; ++i) // NOLINT(altera-id-dependent-backward-branch) 55 | { 56 | parallel_function(i); 57 | } 58 | }; 59 | 60 | // Create the thread pool and launch the jobs. 61 | std::vector pool { }; 62 | 63 | pool.reserve(number_of_threads); 64 | 65 | auto i1 = start; 66 | auto i2 = (std::min)(static_cast(start + slice), end); 67 | 68 | for(auto i = static_cast(0U); ((static_cast(i + 1) < static_cast(number_of_threads)) && (i1 < end)); ++i) // NOLINT(altera-id-dependent-backward-branch) 69 | { 70 | pool.emplace_back(launch_range, i1, i2); 71 | 72 | i1 = i2; 73 | 74 | i2 = (std::min)(static_cast(i2 + slice), end); 75 | } 76 | 77 | if(i1 < end) 78 | { 79 | pool.emplace_back(launch_range, i1, end); 80 | } 81 | 82 | // Wait for the jobs to finish. 83 | for(auto& thread_in_pool : pool) 84 | { 85 | if(thread_in_pool.joinable()) 86 | { 87 | thread_in_pool.join(); 88 | } 89 | } 90 | } 91 | 92 | // Provide a serial version for easy comparison. 93 | template 95 | auto sequential_for(index_type start, 96 | index_type end, 97 | callable_function_type sequential_function) -> void 98 | { 99 | for(index_type i = start; i < end; ++i) 100 | { 101 | sequential_function(i); 102 | } 103 | } 104 | } // namespace my_concurrency 105 | 106 | #endif // PARALLEL_FOR_2017_12_18_H 107 | -------------------------------------------------------------------------------- /test/stopwatch.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2013 - 2024. 3 | // Distributed under the Boost Software License, 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #ifndef STOPWATCH_2024_03_28_H // NOLINT(llvm-header-guard) 9 | #define STOPWATCH_2024_03_28_H 10 | 11 | #include 12 | #include 13 | 14 | #if defined(_MSC_VER) && !defined(__GNUC__) 15 | #define STOPWATCH_NODISCARD 16 | #else 17 | #if (defined(__cplusplus) && (__cplusplus >= 201703L)) 18 | #define STOPWATCH_NODISCARD [[nodiscard]] // NOLINT(cppcoreguidelines-macro-usage) 19 | #else 20 | #define STOPWATCH_NODISCARD 21 | #endif 22 | #endif 23 | 24 | // See also: https://godbolt.org/z/37a4n9f4Y 25 | 26 | namespace concurrency { 27 | 28 | struct stopwatch 29 | { 30 | public: 31 | using time_point_type = std::uintmax_t; 32 | 33 | auto reset() -> void 34 | { 35 | m_start = now(); 36 | } 37 | 38 | template 39 | static auto elapsed_time(const stopwatch& my_stopwatch) noexcept -> RepresentationRequestedTimeType 40 | { 41 | using local_time_type = RepresentationRequestedTimeType; 42 | 43 | return 44 | local_time_type 45 | { 46 | static_cast(my_stopwatch.elapsed()) 47 | / local_time_type { UINTMAX_C(1000000000) } 48 | }; 49 | } 50 | 51 | private: 52 | time_point_type m_start { now() }; // NOLINT(readability-identifier-naming) 53 | 54 | STOPWATCH_NODISCARD static auto now() -> time_point_type 55 | { 56 | #if defined(__CYGWIN__) 57 | 58 | return static_cast(std::clock()); 59 | 60 | #else 61 | 62 | timespec ts { }; 63 | 64 | const int ntsp { timespec_get(&ts, TIME_UTC) }; 65 | 66 | static_cast(ntsp); 67 | 68 | return 69 | static_cast 70 | ( 71 | static_cast(static_cast(ts.tv_sec) * UINTMAX_C(1000000000)) 72 | + static_cast(ts.tv_nsec) 73 | ); 74 | 75 | #endif 76 | } 77 | 78 | STOPWATCH_NODISCARD auto elapsed() const -> time_point_type 79 | { 80 | const time_point_type stop { now() }; 81 | 82 | #if defined(__CYGWIN__) 83 | 84 | const time_point_type 85 | elapsed_ns 86 | { 87 | static_cast 88 | ( 89 | static_cast(static_cast(stop - m_start) * UINTMAX_C(1000000000)) 90 | / static_cast(CLOCKS_PER_SEC) 91 | ) 92 | }; 93 | 94 | #else 95 | 96 | const time_point_type 97 | elapsed_ns 98 | { 99 | static_cast 100 | ( 101 | stop - m_start 102 | ) 103 | }; 104 | 105 | #endif 106 | 107 | return elapsed_ns; 108 | } 109 | }; 110 | 111 | } // namespace concurrency 112 | 113 | #endif // STOPWATCH_2024_03_28_H 114 | -------------------------------------------------------------------------------- /test/test_decwide_t_algebra.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2023. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #ifndef TEST_DECWIDE_T_ALGEBRA_2020_11_05_H // NOLINT(llvm-header-guard) 9 | #define TEST_DECWIDE_T_ALGEBRA_2020_11_05_H 10 | 11 | #include 12 | 13 | #if !defined(WIDE_DECIMAL_NAMESPACE_BEGIN) 14 | #error WIDE_DECIMAL_NAMESPACE_BEGIN is not defined. Ensure that is properly included. 15 | #endif 16 | 17 | #if !defined(WIDE_DECIMAL_NAMESPACE_END) 18 | #error WIDE_DECIMAL_NAMESPACE_END is not defined. Ensure that is properly included. 19 | #endif 20 | 21 | WIDE_DECIMAL_NAMESPACE_BEGIN 22 | 23 | auto test_decwide_t_algebra_add_____() -> bool; // NOLINT(readability-identifier-naming,bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) 24 | auto test_decwide_t_algebra_sub_____() -> bool; // NOLINT(readability-identifier-naming,bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) 25 | auto test_decwide_t_algebra_mul_____() -> bool; // NOLINT(readability-identifier-naming,bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) 26 | auto test_decwide_t_algebra_div_____() -> bool; // NOLINT(readability-identifier-naming,bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) 27 | auto test_decwide_t_algebra_sqrt____() -> bool; // NOLINT(readability-identifier-naming,bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) 28 | auto test_decwide_t_algebra_log_____() -> bool; // NOLINT(readability-identifier-naming,bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) 29 | auto test_decwide_t_algebra_edge____() -> bool; // NOLINT(readability-identifier-naming,bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) 30 | 31 | WIDE_DECIMAL_NAMESPACE_END 32 | 33 | #endif // TEST_DECWIDE_T_ALGEBRA_2020_11_05_H 34 | -------------------------------------------------------------------------------- /test/test_decwide_t_examples.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2023. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #if defined(__clang__) 16 | #if defined __has_feature && (__has_feature(thread_sanitizer) || __has_feature(address_sanitizer)) 17 | #define DECWIDE_T_REDUCE_TEST_DEPTH 18 | #endif 19 | #elif defined(__GNUC__) 20 | #if defined(__SANITIZE_THREAD__) || defined(__SANITIZE_ADDRESS__) || defined(WIDE_DECIMAL_HAS_COVERAGE) 21 | #define DECWIDE_T_REDUCE_TEST_DEPTH 22 | #endif 23 | #endif 24 | 25 | #if defined(WIDE_DECIMAL_NAMESPACE) 26 | auto WIDE_DECIMAL_NAMESPACE::test_decwide_t_examples_part1__() -> bool // NOLINT(readability-identifier-naming) 27 | #else 28 | auto test_decwide_t_examples_part1__() -> bool // NOLINT(readability-identifier-naming) 29 | #endif 30 | { 31 | #if defined(WIDE_DECIMAL_NAMESPACE) 32 | using namespace WIDE_DECIMAL_NAMESPACE::math::wide_decimal; // NOLINT(google-build-using-namespace) 33 | #else 34 | using namespace math::wide_decimal; // NOLINT(google-build-using-namespace) 35 | #endif 36 | 37 | bool result_is_ok = true; 38 | 39 | result_is_ok &= example000_multiply_nines (); std::cout << "example000_multiply_nines : " << std::boolalpha << result_is_ok << std::endl; 40 | result_is_ok &= example000a_multiply_pi_squared (); std::cout << "example000a_multiply_pi_squared : " << std::boolalpha << result_is_ok << std::endl; 41 | result_is_ok &= example001_roots_sqrt (); std::cout << "example001_roots_sqrt : " << std::boolalpha << result_is_ok << std::endl; 42 | result_is_ok &= example001a_roots_seventh (); std::cout << "example001a_roots_seventh : " << std::boolalpha << result_is_ok << std::endl; 43 | result_is_ok &= example001b_roots_almost_integer (); std::cout << "example001b_roots_almost_integer : " << std::boolalpha << result_is_ok << std::endl; 44 | result_is_ok &= example001c_roots_sqrt_limb08 (); std::cout << "example001c_roots_sqrt_limb08 : " << std::boolalpha << result_is_ok << std::endl; 45 | result_is_ok &= example001d_pow2_from_list (); std::cout << "example001d_pow2_from_list : " << std::boolalpha << result_is_ok << std::endl; 46 | result_is_ok &= example001e_algebra_and_constexpr (); std::cout << "example001e_algebra_and_constexpr : " << std::boolalpha << result_is_ok << std::endl; 47 | #if !defined(DECWIDE_T_REDUCE_TEST_DEPTH) 48 | result_is_ok &= example002_pi (); std::cout << "example002_pi : " << std::boolalpha << result_is_ok << std::endl; 49 | result_is_ok &= example002a_pi_small_limb (); std::cout << "example002a_pi_small_limb : " << std::boolalpha << result_is_ok << std::endl; 50 | #endif 51 | result_is_ok &= example002b_pi_100k (); std::cout << "example002b_pi_100k : " << std::boolalpha << result_is_ok << std::endl; 52 | #if !defined(DECWIDE_T_REDUCE_TEST_DEPTH) 53 | result_is_ok &= example002c_pi_quintic (); std::cout << "example002c_pi_quintic : " << std::boolalpha << result_is_ok << std::endl; 54 | result_is_ok &= example002d_pi_limb08 (); std::cout << "example002d_pi_limb08 : " << std::boolalpha << result_is_ok << std::endl; 55 | #endif 56 | 57 | return result_is_ok; 58 | } 59 | 60 | #if defined(WIDE_DECIMAL_NAMESPACE) 61 | auto WIDE_DECIMAL_NAMESPACE::test_decwide_t_examples_part2__() -> bool // NOLINT(readability-identifier-naming) 62 | #else 63 | auto test_decwide_t_examples_part2__() -> bool // NOLINT(readability-identifier-naming) 64 | #endif 65 | { 66 | #if defined(WIDE_DECIMAL_NAMESPACE) 67 | using namespace WIDE_DECIMAL_NAMESPACE::math::wide_decimal; // NOLINT(google-build-using-namespace) 68 | #else 69 | using namespace math::wide_decimal; // NOLINT(google-build-using-namespace) 70 | #endif 71 | 72 | bool result_is_ok = true; 73 | 74 | result_is_ok &= example003_zeta (); std::cout << "example003_zeta : " << std::boolalpha << result_is_ok << std::endl; 75 | result_is_ok &= example004_bessel_recur (); std::cout << "example004_bessel_recur : " << std::boolalpha << result_is_ok << std::endl; 76 | result_is_ok &= example005_polylog_series (); std::cout << "example005_polylog_series : " << std::boolalpha << result_is_ok << std::endl; 77 | #if !defined(DECWIDE_T_REDUCE_TEST_DEPTH) 78 | result_is_ok &= example006_logarithm (); std::cout << "example006_logarithm : " << std::boolalpha << result_is_ok << std::endl; 79 | result_is_ok &= example007_catalan_series (); std::cout << "example007_catalan_series : " << std::boolalpha << result_is_ok << std::endl; 80 | result_is_ok &= example008_bernoulli_tgamma (); std::cout << "example008_bernoulli_tgamma : " << std::boolalpha << result_is_ok << std::endl; 81 | #endif 82 | result_is_ok &= example009_boost_math_standalone (); std::cout << "example009_boost_math_standalone : " << std::boolalpha << result_is_ok << std::endl; 83 | result_is_ok &= example009a_boost_math_standalone (); std::cout << "example009a_boost_math_standalone : " << std::boolalpha << result_is_ok << std::endl; 84 | result_is_ok &= example009b_boost_math_standalone (); std::cout << "example009b_boost_math_standalone : " << std::boolalpha << result_is_ok << std::endl; 85 | result_is_ok &= example010_hypergeometric_2f1 (); std::cout << "example010_hypergeometric_2f1 : " << std::boolalpha << result_is_ok << std::endl; 86 | result_is_ok &= example010a_hypergeometric_1f1 (); std::cout << "example010a_hypergeometric_1f1 : " << std::boolalpha << result_is_ok << std::endl; 87 | result_is_ok &= example011_trig_trapezoid_integral (); std::cout << "example011_trig_trapezoid_integral : " << std::boolalpha << result_is_ok << std::endl; 88 | result_is_ok &= example012_rational_floor_ceil (); std::cout << "example012_rational_floor_ceil : " << std::boolalpha << result_is_ok << std::endl; 89 | result_is_ok &= example013_embeddable_sqrt (); std::cout << "example013_embeddable_sqrt : " << std::boolalpha << result_is_ok << std::endl; 90 | result_is_ok &= example013a_embeddable_agm (); std::cout << "example013a_embeddable_agm : " << std::boolalpha << result_is_ok << std::endl; 91 | 92 | return result_is_ok; 93 | } 94 | -------------------------------------------------------------------------------- /test/test_decwide_t_examples.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2023. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #ifndef TEST_DECWIDE_T_EXAMPLES_2020_11_05_H // NOLINT(llvm-header-guard) 9 | #define TEST_DECWIDE_T_EXAMPLES_2020_11_05_H 10 | 11 | #include 12 | 13 | #if !defined(WIDE_DECIMAL_NAMESPACE_BEGIN) 14 | #error WIDE_DECIMAL_NAMESPACE_BEGIN is not defined. Ensure that is properly included. 15 | #endif 16 | 17 | #if !defined(WIDE_DECIMAL_NAMESPACE_END) 18 | #error WIDE_DECIMAL_NAMESPACE_END is not defined. Ensure that is properly included. 19 | #endif 20 | 21 | WIDE_DECIMAL_NAMESPACE_BEGIN 22 | 23 | auto test_decwide_t_examples_part1__() -> bool; // NOLINT(readability-identifier-naming,bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) 24 | auto test_decwide_t_examples_part2__() -> bool; // NOLINT(readability-identifier-naming,bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) 25 | 26 | WIDE_DECIMAL_NAMESPACE_END 27 | 28 | #endif // TEST_DECWIDE_T_EXAMPLES_2020_11_05_H 29 | -------------------------------------------------------------------------------- /test/test_high_precision_log.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2022- 2025. // 3 | // Distributed under the Boost Software License, // 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt // 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) // 6 | /////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if !defined(WIDE_DECIMAL_NAMESPACE) 17 | #define WIDE_DECIMAL_NAMESPACE ckormanyos 18 | #endif 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | 25 | // cd /mnt/c/Users/User/Documents/Ks/PC_Software/NumericalPrograms/ExtendedNumberTypes/wide_decimal 26 | // When using g++ and -std=c++20 27 | // g++ -finline-functions -march=native -mtune=native -O3 -Werror -Wall -Wextra -std=c++20 -DWIDE_DECIMAL_NAMESPACE=ckormanyos -I. -I/mnt/c/boost/boost_1_83_0 test/test_high_precision_log.cpp -pthread -lpthread -lgmp -lmpfr -o test_high_precision_log.exe 28 | // ./test_high_precision_log.exe 29 | 30 | namespace test_high_precision_log 31 | { 32 | constexpr auto my_digits10 = static_cast(INT32_C(1000011)); 33 | 34 | using local_boost_high_precision_backend_type = boost::multiprecision::mpfr_float_backend; 35 | using local_boost_high_precision_number_type = boost::multiprecision::number; 36 | 37 | using local_wide_decimal_high_precision_number_type = ckormanyos::math::wide_decimal::decwide_t>; 38 | } // namespace test_high_precision_log 39 | 40 | namespace local 41 | { 42 | #if defined(__clang__) 43 | constexpr auto adders_array_size = static_cast(UINT8_C(5)); 44 | #else 45 | constexpr auto adders_array_size = static_cast(UINT8_C(8)); 46 | #endif 47 | 48 | using adders_array_type = std::array; 49 | 50 | #if defined(__clang__) 51 | constexpr adders_array_type adders = 52 | { 53 | static_cast(UINT8_C(0)), 54 | static_cast(UINT8_C(6)), 55 | static_cast(UINT8_C(12)), 56 | static_cast(UINT16_C(9999)), 57 | static_cast(UINT64_C(999999999999999999)) 58 | }; 59 | #else 60 | constexpr adders_array_type adders = 61 | { 62 | static_cast(UINT8_C(0)), 63 | static_cast(UINT8_C(3)), 64 | static_cast(UINT8_C(6)), 65 | static_cast(UINT8_C(9)), 66 | static_cast(UINT8_C(12)), 67 | static_cast(UINT8_C(15)), 68 | static_cast(UINT16_C(9999)), 69 | static_cast(UINT64_C(999999999999999999)) 70 | }; 71 | #endif 72 | 73 | static_assert(static_cast(static_cast(adders[0U] + static_cast(UINT64_C(3))) % 3U) == static_cast(UINT8_C(0)), "Error adder must provie fractional part 1/3 in this test"); 74 | static_assert(static_cast(static_cast(adders[1U] + static_cast(UINT64_C(3))) % 3U) == static_cast(UINT8_C(0)), "Error adder must provie fractional part 1/3 in this test"); 75 | static_assert(static_cast(static_cast(adders[2U] + static_cast(UINT64_C(3))) % 3U) == static_cast(UINT8_C(0)), "Error adder must provie fractional part 1/3 in this test"); 76 | static_assert(static_cast(static_cast(adders[3U] + static_cast(UINT64_C(3))) % 3U) == static_cast(UINT8_C(0)), "Error adder must provie fractional part 1/3 in this test"); 77 | static_assert(static_cast(static_cast(adders[4U] + static_cast(UINT64_C(3))) % 3U) == static_cast(UINT8_C(0)), "Error adder must provie fractional part 1/3 in this test"); 78 | #if defined(__clang__) 79 | #else 80 | static_assert(static_cast(static_cast(adders[5U] + static_cast(UINT64_C(3))) % 3U) == static_cast(UINT8_C(0)), "Error adder must provie fractional part 1/3 in this test"); 81 | static_assert(static_cast(static_cast(adders[6U] + static_cast(UINT64_C(3))) % 3U) == static_cast(UINT8_C(0)), "Error adder must provie fractional part 1/3 in this test"); 82 | static_assert(static_cast(static_cast(adders[7U] + static_cast(UINT64_C(3))) % 3U) == static_cast(UINT8_C(0)), "Error adder must provie fractional part 1/3 in this test"); 83 | #endif 84 | 85 | template 87 | static auto do_calcs_log() -> bool 88 | { 89 | using local_hp_float_left_type = HighPrecisionFloatLeftType; 90 | using local_hp_float_right_type = HighPrecisionFloatRightType; 91 | 92 | const auto tol = 93 | local_hp_float_left_type 94 | ( 95 | std::numeric_limits::epsilon() 96 | * static_cast(UINT32_C(100000000)) 97 | ); 98 | 99 | auto result_is_ok = true; 100 | 101 | std::atomic_flag do_calcs_log_lock = ATOMIC_FLAG_INIT; 102 | 103 | using local_size_type = typename adders_array_type::size_type; 104 | 105 | const auto my_one = local_hp_float_left_type(static_cast(UINT8_C(1))); 106 | 107 | my_concurrency::parallel_for 108 | ( 109 | static_cast(UINT8_C(0)), 110 | static_cast(local::adders_array_size), 111 | [&result_is_ok, &do_calcs_log_lock, &tol, &my_one](typename adders_array_type::size_type index) 112 | { 113 | const auto one_plus_adder_at_index = static_cast(static_cast(UINT64_C(1)) + adders[index]); 114 | 115 | const auto x_left = local_hp_float_left_type (one_plus_adder_at_index) / static_cast(UINT8_C(3)); 116 | const auto x_right = local_hp_float_right_type(one_plus_adder_at_index) / static_cast(UINT8_C(3)); 117 | 118 | using std::log; 119 | 120 | const auto y_left = log(x_left); 121 | const auto y_right = log(x_right); 122 | 123 | local_hp_float_left_type ratio { }; 124 | 125 | { 126 | std::stringstream strm; 127 | 128 | strm << std::setprecision(test_high_precision_log::my_digits10) << y_right; 129 | 130 | ratio = y_left / local_hp_float_left_type(strm.str().c_str()); 131 | } 132 | 133 | while(do_calcs_log_lock.test_and_set()) { ; } 134 | using std::fabs; 135 | 136 | const auto delta = ((my_one > ratio) ? (my_one - ratio) : (ratio - my_one)); 137 | 138 | const auto is_close_fraction = (delta < tol); 139 | 140 | result_is_ok = (is_close_fraction && result_is_ok); 141 | 142 | { 143 | std::stringstream strm; 144 | 145 | strm << "index: " 146 | << index 147 | << ", is_close_fraction: " 148 | << std::boolalpha 149 | << is_close_fraction; 150 | 151 | const auto str_from_strm = strm.str(); 152 | 153 | std::cout << str_from_strm << std::endl; 154 | } 155 | 156 | do_calcs_log_lock.clear(); 157 | } 158 | ); 159 | 160 | return result_is_ok; 161 | } 162 | } // namespace local 163 | 164 | auto main() -> int 165 | { 166 | using local_hp_float_left_type = test_high_precision_log::local_wide_decimal_high_precision_number_type; 167 | using local_hp_float_right_type = test_high_precision_log::local_boost_high_precision_number_type; 168 | 169 | const auto begin = std::clock(); 170 | 171 | const auto result_is_ok = local::do_calcs_log(); 172 | 173 | const auto end = std::clock(); 174 | 175 | const auto elapsed = static_cast(static_cast(end - begin) / CLOCKS_PER_SEC); 176 | 177 | std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl; 178 | 179 | std::cout << "High-precision calculations took: " << std::fixed << std::setprecision(1) << elapsed << "s" << std::endl; 180 | 181 | return (result_is_ok ? 0 : -1); 182 | } 183 | -------------------------------------------------------------------------------- /util/memory/util_n_slot_array_allocator.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2024. 3 | // Distributed under the Boost Software License, 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #ifndef UTIL_N_SLOT_ARRAY_ALLOCATOR_2020_10_25_H // NOLINT(llvm-header-guard) 9 | #define UTIL_N_SLOT_ARRAY_ALLOCATOR_2020_10_25_H 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace util { 17 | 18 | // Forward declaration of n_slot_array_allocator template. 19 | template 22 | class n_slot_array_allocator; 23 | 24 | // Template partial specialization of n_slot_array_allocator template for void. 25 | template 27 | class n_slot_array_allocator 28 | { 29 | public: 30 | using value_type = void; 31 | using pointer = value_type*; 32 | using const_pointer = const value_type*; 33 | 34 | template 35 | struct rebind 36 | { 37 | using other = n_slot_array_allocator; 38 | }; 39 | }; 40 | 41 | template 44 | class n_slot_array_allocator // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) 45 | { 46 | private: 47 | static constexpr std::uint_fast32_t slot_width = SlotWidth; 48 | static constexpr std::size_t slot_count = SlotCount; 49 | 50 | using slot_array_type = std::array(slot_width)>; 51 | using slot_array_memory_type = std::array; 52 | using slot_array_flags_type = std::array; 53 | 54 | public: 55 | using size_type = std::size_t; 56 | using value_type = typename slot_array_type::value_type; 57 | using pointer = value_type*; 58 | using const_pointer = const value_type*; 59 | using reference = value_type&; 60 | using const_reference = const value_type&; 61 | 62 | constexpr n_slot_array_allocator() = default; // LCOV_EXCL_LINE 63 | 64 | constexpr n_slot_array_allocator(const n_slot_array_allocator&) = default; // LCOV_EXCL_LINE 65 | 66 | template 67 | struct rebind 68 | { 69 | using other = n_slot_array_allocator; 70 | }; 71 | 72 | constexpr auto max_size() const noexcept -> size_type { return slot_count; } 73 | 74 | constexpr auto address( reference x) const -> pointer { return &x; } 75 | constexpr auto address(const_reference x) const -> const_pointer { return &x; } 76 | 77 | auto allocate(size_type count, const_pointer p_hint = nullptr) -> pointer 78 | { 79 | static_cast(count); 80 | static_cast(p_hint); 81 | 82 | pointer p { nullptr }; 83 | 84 | // TBD: There is most likely significant optimization potential 85 | // capable of being unlocked if a storage/lookup mechanism can be 86 | // devised that uses a binary search when finding the next free slot. 87 | 88 | // (TBD) In fact, constant-time allocation probably possible, as shown in: 89 | // SmallObjectAllocator from Modern C++ Design by Andrei Alexandrescu. 90 | 91 | for(auto i = static_cast(UINT8_C(0)); i < slot_count; ++i) 92 | { 93 | using local_flags_value_type = typename slot_array_flags_type::value_type; 94 | 95 | if(slot_flags[i] == static_cast(UINT8_C(0))) // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) 96 | { 97 | slot_flags[i] = static_cast(UINT8_C(1)); // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) 98 | 99 | p = static_cast(slot_array_memory[i].data()); // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) 100 | 101 | if(i > slot_max_index) 102 | { 103 | slot_max_index = i; 104 | 105 | static_cast(slot_max_index); 106 | } 107 | 108 | break; 109 | } 110 | } 111 | 112 | return p; 113 | } 114 | 115 | auto construct(pointer p, const value_type& x) -> void 116 | { 117 | // The memory in the n-slot allocator already exists 118 | // in an uninitialized form. Construction can safely 119 | // simply set the value in the uninitialized memory. 120 | 121 | *p = x; 122 | } 123 | 124 | auto destroy(pointer p) const -> void { static_cast(p); } // LCOV_EXCL_LINE 125 | 126 | auto deallocate(pointer p_slot, size_type sz) -> void 127 | { 128 | static_cast(sz); 129 | 130 | typename slot_array_memory_type::size_type index { }; 131 | 132 | for(auto& slot_array_memory_entry : slot_array_memory) 133 | { 134 | if(p_slot == static_cast(slot_array_memory_entry.data())) 135 | { 136 | using local_flags_value_type = typename slot_array_flags_type::value_type; 137 | 138 | slot_flags[index] = static_cast(UINT8_C(0)); // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) 139 | 140 | break; 141 | } 142 | 143 | ++index; 144 | } 145 | } 146 | 147 | private: 148 | static slot_array_memory_type slot_array_memory; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) 149 | static slot_array_flags_type slot_flags; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) 150 | static std::size_t slot_max_index; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) 151 | }; 152 | 153 | template 156 | typename n_slot_array_allocator::slot_array_memory_type n_slot_array_allocator::slot_array_memory; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables,hicpp-uppercase-literal-suffix,readability-uppercase-literal-suffix) 157 | 158 | template 161 | typename n_slot_array_allocator::slot_array_flags_type n_slot_array_allocator::slot_flags; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables,hicpp-uppercase-literal-suffix,readability-uppercase-literal-suffix) 162 | 163 | template 166 | std::size_t n_slot_array_allocator::slot_max_index; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables,hicpp-uppercase-literal-suffix,readability-uppercase-literal-suffix) 167 | 168 | // Global comparison operators (required by the standard). 169 | template 172 | auto operator==(const n_slot_array_allocator& left, 173 | const n_slot_array_allocator& right) -> bool 174 | { 175 | static_cast(left.max_size()); 176 | static_cast(right.max_size()); 177 | 178 | return true; 179 | } 180 | 181 | template 184 | auto operator!=(const n_slot_array_allocator& left, 185 | const n_slot_array_allocator& right) -> bool 186 | { 187 | static_cast(left.max_size()); 188 | static_cast(right.max_size()); 189 | 190 | return false; 191 | } 192 | 193 | } // namespace util 194 | 195 | #endif // UTIL_N_SLOT_ARRAY_ALLOCATOR_2020_10_25_H 196 | -------------------------------------------------------------------------------- /util/stdcpp/stdcpp_patch.cpp: -------------------------------------------------------------------------------- 1 | #if defined(__GNUC__) && defined(__AVR__) 2 | #include 3 | 4 | void operator delete(void*) noexcept; 5 | void operator delete(void*, void*) noexcept; 6 | #if(__cplusplus >= 201400L) 7 | void operator delete(void*, std::size_t) noexcept; 8 | #endif 9 | 10 | void operator delete(void*) noexcept { } 11 | void operator delete(void*, void*) noexcept { } 12 | #if(__cplusplus >= 201400L) 13 | void operator delete(void*, std::size_t) noexcept { } 14 | #endif 15 | #else 16 | void stdcpp_patch_dummy() noexcept; 17 | 18 | void stdcpp_patch_dummy() noexcept { } 19 | #endif 20 | -------------------------------------------------------------------------------- /util/utility/util_baselexical_cast.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2020 - 2024. 3 | // Distributed under the Boost Software License, 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #ifndef UTIL_BASELEXICAL_CAST_2020_06_28_H // NOLINT(llvm-header-guard) 9 | #define UTIL_BASELEXICAL_CAST_2020_06_28_H 10 | 11 | #if ((defined(__cplusplus) && (__cplusplus >= 201703L)) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))) 12 | #if !(defined(__GNUC__) && defined(__AVR__)) 13 | #define UTIL_BASELEXICAL_CAST_HAS_CHARCONV 14 | #endif 15 | #endif 16 | 17 | #if defined(UTIL_BASELEXICAL_CAST_HAS_CHARCONV) 18 | #include 19 | #include 20 | #else 21 | #include 22 | #include 23 | #include 24 | #include 25 | #endif 26 | 27 | namespace util { 28 | 29 | #if defined(UTIL_BASELEXICAL_CAST_HAS_CHARCONV) 30 | 31 | template(UINT8_C(10)), 33 | const bool UpperCase = true> 34 | auto baselexical_cast(const UnsignedIntegerType& u, char* first, char* last) -> const char* 35 | { 36 | constexpr auto my_base = static_cast(BaseRepresentation); 37 | 38 | const auto result = std::to_chars(first, last, u, my_base); 39 | 40 | return result.ptr; 41 | } 42 | 43 | #else 44 | 45 | template 48 | struct baselexical_cast_helper 49 | { 50 | private: 51 | using output_value_type = typename std::iterator_traits::value_type; 52 | 53 | public: 54 | static auto extract(output_value_type) noexcept -> output_value_type = delete; 55 | }; 56 | 57 | template 59 | struct baselexical_cast_helper(UINT8_C(16))> 60 | { 61 | private: 62 | using output_value_type = typename std::iterator_traits::value_type; 63 | 64 | public: 65 | static auto extract(output_value_type c) noexcept -> output_value_type 66 | { 67 | if(c <= static_cast(INT8_C(9))) 68 | { 69 | c = 70 | static_cast 71 | ( 72 | c + static_cast('0') 73 | ); 74 | } 75 | else if((c >= static_cast(0xA)) && (c <= static_cast(INT8_C(0xF)))) // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 76 | { 77 | c = 78 | static_cast 79 | ( 80 | static_cast(UpperCase ? static_cast('A') : static_cast('a')) 81 | + static_cast(c - static_cast(INT8_C(0xA))) 82 | ); 83 | } 84 | 85 | return c; 86 | } 87 | }; 88 | 89 | template 91 | struct baselexical_cast_helper(UINT8_C(10))> 92 | { 93 | private: 94 | using output_value_type = typename std::iterator_traits::value_type; 95 | 96 | public: 97 | static auto extract(output_value_type c) noexcept -> output_value_type 98 | { 99 | if(c <= static_cast(INT8_C(9))) 100 | { 101 | c = 102 | static_cast 103 | ( 104 | c + static_cast('0') 105 | ); 106 | } 107 | 108 | return c; 109 | } 110 | }; 111 | 112 | template(UINT8_C(10)), 115 | const bool UpperCase = true> 116 | auto baselexical_cast(const UnsignedIntegerType& u, OutputIterator out, OutputIterator out_dummy) -> OutputIterator 117 | { 118 | static_cast(out_dummy); 119 | 120 | using unsigned_integer_type = UnsignedIntegerType; 121 | using output_value_type = typename std::iterator_traits::value_type; 122 | 123 | if(u == static_cast(UINT8_C(0))) 124 | { 125 | *out = 126 | static_cast 127 | ( 128 | baselexical_cast_helper::extract(static_cast(UINT8_C(0))) 129 | ); 130 | } 131 | else 132 | { 133 | unsigned_integer_type x(u); 134 | 135 | auto out_first = out; 136 | 137 | while(x != static_cast(UINT8_C(0))) // NOLINT(altera-id-dependent-backward-branch) 138 | { 139 | const auto c = 140 | static_cast 141 | ( 142 | x % static_cast(BaseRepresentation) 143 | ); 144 | 145 | *out = 146 | static_cast 147 | ( 148 | baselexical_cast_helper::extract(c) 149 | ); 150 | 151 | x = 152 | static_cast 153 | ( 154 | x / static_cast(BaseRepresentation) 155 | ); 156 | 157 | if(x != static_cast(UINT8_C(0))) 158 | { 159 | ++out; 160 | } 161 | } 162 | 163 | #if (defined(__GNUC__) && !defined(__clang__)&& (__GNUC__ > 12)) 164 | #pragma GCC diagnostic push 165 | #pragma GCC diagnostic ignored "-Wstringop-overflow=" 166 | #endif 167 | 168 | std::reverse(out_first, out + static_cast(UINT8_C(1))); 169 | 170 | #if (defined(__GNUC__) && !defined(__clang__)&& (__GNUC__ > 12)) 171 | #pragma GCC diagnostic pop 172 | #endif 173 | } 174 | 175 | return out + static_cast(UINT8_C(1)); 176 | } 177 | 178 | #endif 179 | 180 | } // namespace util 181 | 182 | #endif // UTIL_BASELEXICAL_CAST_2020_06_28_H 183 | -------------------------------------------------------------------------------- /util/utility/util_noncopyable.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2007 - 2023. 3 | // Distributed under the Boost Software License, 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #ifndef UTIL_NONCOPYABLE_2008_12_16_H // NOLINT(llvm-header-guard) 9 | #define UTIL_NONCOPYABLE_2008_12_16_H 10 | 11 | // Taken (with slight modification) from boost::noncopyable. 12 | 13 | namespace util { 14 | namespace my_noncopyable_namespace { 15 | 16 | class noncopyable 17 | { 18 | protected: 19 | noncopyable() = default; // LCOV_EXCL_LINE 20 | ~noncopyable() = default; // LCOV_EXCL_LINE 21 | 22 | private: 23 | // Emphasize: The following members are private. 24 | noncopyable(const noncopyable&) = delete; // NOLINT(hicpp-use-equals-delete,modernize-use-equals-delete) 25 | noncopyable(noncopyable&&) = delete; // NOLINT(hicpp-use-equals-delete,modernize-use-equals-delete) 26 | 27 | auto operator=(const noncopyable&) -> noncopyable& = delete; // NOLINT(hicpp-use-equals-delete,modernize-use-equals-delete) 28 | auto operator=(noncopyable&&) -> noncopyable& = delete; // NOLINT(hicpp-use-equals-delete,modernize-use-equals-delete) 29 | }; 30 | 31 | } // namespace my_noncopyable_namespace 32 | 33 | using noncopyable = my_noncopyable_namespace::noncopyable; 34 | 35 | } // namespace util 36 | 37 | #endif // UTIL_NONCOPYABLE_2008_12_16_H 38 | -------------------------------------------------------------------------------- /util/utility/util_pseudorandom_time_point_seed.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright Christopher Kormanyos 2023- 2024. 3 | // Distributed under the Boost Software License, 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #ifndef UTIL_PSEUDORANDOM_TIME_POINT_SEED_2023_10_27_H // NOLINT(llvm-header-guard) 9 | #define UTIL_PSEUDORANDOM_TIME_POINT_SEED_2023_10_27_H 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | namespace util { 22 | 23 | struct util_pseudorandom_time_point_seed 24 | { 25 | public: 26 | template 27 | static auto value() -> IntegralType 28 | { 29 | using strftime_uint8_array_type = std::array(UINT8_C(64))>; 30 | 31 | strftime_uint8_array_type buf_u8 { }; 32 | buf_u8.fill(static_cast(UINT8_C(0))); 33 | 34 | std::size_t str_tm_len { }; 35 | 36 | { 37 | // Get the time. 38 | const std::time_t now = std::time(nullptr); 39 | 40 | using strftime_char_array_type = std::array::value>; 41 | 42 | strftime_char_array_type buf { }; 43 | buf.fill('\0'); 44 | 45 | #if defined(_MSC_VER) 46 | #pragma warning(push) 47 | #pragma warning(disable : 4996) 48 | #endif 49 | // Format the time in a calendar-style. 50 | strftime(buf.data(), buf.size(), "%c", std::localtime(&now)); // NOLINT(concurrency-mt-unsafe) 51 | #if defined(_MSC_VER) 52 | #pragma warning( pop ) 53 | #endif 54 | 55 | { 56 | std::stringstream strm; 57 | 58 | // Append the clock()-time in arbitrary units. 59 | strm << buf.data() 60 | << '+' 61 | << std::setfill('0') 62 | << std::setw(static_cast(INT8_C(9))) 63 | << std::clock(); 64 | 65 | const auto str_tm = strm.str(); 66 | 67 | str_tm_len = str_tm.length(); 68 | 69 | std::copy(str_tm.cbegin(), str_tm.cend(), buf_u8.begin()); 70 | } 71 | } 72 | 73 | using local_integral_type = IntegralType; 74 | 75 | return static_cast(crc_crc64(buf_u8.data(), str_tm_len)); 76 | } 77 | 78 | static constexpr auto test() noexcept -> bool; 79 | 80 | private: 81 | template 83 | static constexpr auto crc_bitwise_template(const std::uint8_t* message, 84 | const std::size_t count, 85 | const UnsignedIntegralType polynomial, // NOLINT(bugprone-easily-swappable-parameters) 86 | const UnsignedIntegralType initial_value, 87 | const UnsignedIntegralType final_xor_value) -> UnsignedIntegralType 88 | { 89 | using value_type = UnsignedIntegralType; 90 | 91 | // The data_type is fixed to exactly 8-bits in width at the moment. 92 | using data_type = std::uint8_t; 93 | 94 | value_type crc = initial_value; 95 | 96 | // Perform the polynomial division, one element at a time. 97 | for(auto data_index = static_cast(UINT8_C(0)); data_index < count; ++data_index) 98 | { 99 | // Obtain the next data element (and reflect it if necessary). 100 | const data_type next_data_element = message[data_index]; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 101 | 102 | { 103 | constexpr auto left_shift_amount = 104 | static_cast 105 | ( 106 | std::numeric_limits::digits - std::numeric_limits::digits 107 | ); 108 | 109 | crc ^= static_cast(static_cast(next_data_element) << left_shift_amount); 110 | } 111 | 112 | // Process the next data byte, one bit at a time. 113 | for(std::uint_fast8_t index = 0U; 114 | index < static_cast(std::numeric_limits::digits); 115 | ++index) 116 | { 117 | const auto high_bit_value = 118 | static_cast 119 | ( 120 | crc 121 | & static_cast 122 | ( 123 | static_cast(UINT8_C(1)) << static_cast(std::numeric_limits::digits - 1) 124 | ) 125 | ); 126 | 127 | const bool high_bit_of_crc_is_set = (high_bit_value != static_cast(UINT8_C(0))); 128 | 129 | crc = crc << static_cast(UINT8_C(1)); 130 | 131 | if(high_bit_of_crc_is_set) 132 | { 133 | // Shift through the polynomial. Also left-justify the 134 | // polynomial within the width of value_type, if necessary. 135 | 136 | crc ^= static_cast(polynomial); 137 | } 138 | } 139 | } 140 | 141 | // Perform the final XOR on the result. 142 | crc ^= final_xor_value; 143 | 144 | return crc; 145 | } 146 | 147 | static constexpr auto crc_crc64(const std::uint8_t* message, const std::size_t count) -> std::uint64_t 148 | { 149 | // check: 0x6C40DF5F0B497347 150 | return crc_bitwise_template(UINT8_C(64)), std::uint64_t> 151 | ( 152 | message, 153 | count, 154 | static_cast(UINT64_C(0x42F0E1EBA9EA3693)), 155 | static_cast(UINT64_C(0x0000000000000000)), 156 | static_cast(UINT64_C(0x0000000000000000)) 157 | ); 158 | } 159 | }; 160 | 161 | constexpr auto util_pseudorandom_time_point_seed::test() noexcept -> bool 162 | { 163 | constexpr std::uint8_t crc64_test_data[static_cast(UINT8_C(9))] = // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 164 | { 165 | 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U, 0x38U, 0x39U 166 | }; 167 | 168 | constexpr auto crc64_test_result = crc_bitwise_template(UINT8_C(64)), std::uint64_t> 169 | ( 170 | crc64_test_data, // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) 171 | sizeof(crc64_test_data), 172 | static_cast(UINT64_C(0x42F0E1EBA9EA3693)), 173 | static_cast(UINT64_C(0x0000000000000000)), 174 | static_cast(UINT64_C(0x0000000000000000)) 175 | ); 176 | 177 | // check: 0x6C40DF5F0B497347 178 | return (crc64_test_result == static_cast(UINT64_C(0x6C40DF5F0B497347))); 179 | } 180 | 181 | static_assert(util::util_pseudorandom_time_point_seed::test(), "Error: crc64 implementation is not working properly"); 182 | 183 | } // namespace util 184 | 185 | #endif // UTIL_PSEUDORANDOM_TIME_POINT_SEED_2023_10_27_H 186 | -------------------------------------------------------------------------------- /wide_decimal.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30907.101 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wide_decimal", "wide_decimal.vcxproj", "{E8006465-B814-49F0-B17C-5CC35591686D}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionItems", "{67024DAA-EB45-4603-8B77-A834C6A9CDF2}" 9 | ProjectSection(SolutionItems) = preProject 10 | .clang-tidy = .clang-tidy 11 | CMakeLists.txt = CMakeLists.txt 12 | codecov.yml = codecov.yml 13 | LICENSE_1_0.txt = LICENSE_1_0.txt 14 | sonar-project.properties = sonar-project.properties 15 | EndProjectSection 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | wide-decimal-debug|x64 = wide-decimal-debug|x64 20 | wide-decimal-release|x64 = wide-decimal-release|x64 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {E8006465-B814-49F0-B17C-5CC35591686D}.wide-decimal-debug|x64.ActiveCfg = wide-decimal-debug|x64 24 | {E8006465-B814-49F0-B17C-5CC35591686D}.wide-decimal-debug|x64.Build.0 = wide-decimal-debug|x64 25 | {E8006465-B814-49F0-B17C-5CC35591686D}.wide-decimal-release|x64.ActiveCfg = wide-decimal-release|x64 26 | {E8006465-B814-49F0-B17C-5CC35591686D}.wide-decimal-release|x64.Build.0 = wide-decimal-release|x64 27 | EndGlobalSection 28 | GlobalSection(SolutionProperties) = preSolution 29 | HideSolutionNode = FALSE 30 | EndGlobalSection 31 | GlobalSection(ExtensibilityGlobals) = postSolution 32 | SolutionGuid = {86125F66-3207-4137-970A-AEF86CF9E05E} 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /wide_decimal_vs2022.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.2.32519.379 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wide_decimal_vs2022", "wide_decimal_vs2022.vcxproj", "{E8006465-B814-49F0-B17C-5CC35591686D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | wide-decimal-debug|x64 = wide-decimal-debug|x64 11 | wide-decimal-release|x64 = wide-decimal-release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {E8006465-B814-49F0-B17C-5CC35591686D}.wide-decimal-debug|x64.ActiveCfg = wide-decimal-debug|x64 15 | {E8006465-B814-49F0-B17C-5CC35591686D}.wide-decimal-debug|x64.Build.0 = wide-decimal-debug|x64 16 | {E8006465-B814-49F0-B17C-5CC35591686D}.wide-decimal-release|x64.ActiveCfg = wide-decimal-release|x64 17 | {E8006465-B814-49F0-B17C-5CC35591686D}.wide-decimal-release|x64.Build.0 = wide-decimal-release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {86125F66-3207-4137-970A-AEF86CF9E05E} 24 | EndGlobalSection 25 | EndGlobal 26 | --------------------------------------------------------------------------------