diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/.gitmodules @@ -0,0 +1 @@ + diff --git a/.travis.yml b/.travis.yml index eda50ac0d..3e7289198 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,42 @@ # Copyright 2016, 2017 Peter Dimov +# Copyright 2020 Mikhail Komarov # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) +# +# This file should be used in couple of configurations: +# +# 1. Configuration for building at boostorg/multiprecision TravisCI. +# This means no actual build with CMake should be performed, only configuration. +# +# 2. Configuration for building with less CI-loaded projects. +# This means not only configuration with CMake should be performed, but also +# build and test should be executed. +# To make this script be fine for building and testing with CMake, uncommend +# copy and paste following lines before the last 'fi' at 'script' section: +# +#------------------------------------------------------------------------------# +#if [[ $TEST_SUITE == compile_fail ]]; then +# if [[ $TRAVIS_OS_NAME == linux ]]; then +# ctest --build-and-test .. . --build-generator "Unix Makefiles" --tests-regex "multiprecision_test_compile_fail_*" -j $(($(nproc) + 1)); +# elif [[ $TRAVIS_OS_NAME == osx ]]; then +# ctest --build-and-test .. . --build-generator "Unix Makefiles" --tests-regex "multiprecision_test_compile_fail_*" -j $(($(sysctl -n hw.ncpu) + 1)); +# fi +#else +# if [[ $TRAVIS_OS_NAME == linux ]]; then +# cmake --build . --target multiprecision_test_suite_$TEST_SUITE -- -j$(($(nproc) + 1)); +# elif [[ $TRAVIS_OS_NAME == osx ]]; then +# cmake --build . --target multiprecision_test_suite_$TEST_SUITE -- -j$(($(sysctl -n hw.ncpu) + 1)); +# fi +#fi +#------------------------------------------------------------------------------# language: cpp -sudo: false +sudo: true python: "2.7" -dist : xenial +dist: xenial os: - linux @@ -18,6 +46,9 @@ branches: only: - master - develop + - cmake-develop + - cmake-master + - 6-shanks-tonelli env: matrix: @@ -30,11 +61,12 @@ matrix: include: - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++03 TEST_SUITE=arithmetic_tests + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03 TEST_SUITE=arithmetic_tests addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -42,13 +74,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++11 TEST_SUITE=arithmetic_tests + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11 TEST_SUITE=arithmetic_tests addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -56,13 +90,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++14 TEST_SUITE=arithmetic_tests + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14 TEST_SUITE=arithmetic_tests addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -70,13 +106,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++03 TEST_SUITE=cpp_int_tests + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z TEST_SUITE=arithmetic_tests addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -84,13 +122,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++11 TEST_SUITE=cpp_int_tests + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03 TEST_SUITE=cpp_int_tests addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -98,13 +138,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++14 TEST_SUITE=cpp_int_tests + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11 TEST_SUITE=cpp_int_tests addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -112,13 +154,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++03 TEST_SUITE=functions_and_limits + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14 TEST_SUITE=cpp_int_tests addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -126,13 +170,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++11 TEST_SUITE=functions_and_limits + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z TEST_SUITE=cpp_int_tests addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -140,6 +186,55 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03 TEST_SUITE=functions_and_limits + addons: + apt: + packages: + - g++-6 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11 TEST_SUITE=functions_and_limits + addons: + apt: + packages: + - g++-6 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14 TEST_SUITE=functions_and_limits + addons: + apt: + packages: + - g++-6 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++14 TEST_SUITE=functions_and_limits @@ -147,6 +242,23 @@ matrix: apt: packages: - g++-6 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z TEST_SUITE=functions_and_limits + addons: + apt: + packages: + - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -154,13 +266,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++03 TEST_SUITE="conversions performance" + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03 TEST_SUITE=conversions addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -168,13 +282,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++11 TEST_SUITE="conversions performance" + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11 TEST_SUITE=conversions addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -182,13 +298,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++14 TEST_SUITE="conversions performance" + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14 TEST_SUITE=conversions addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -196,13 +314,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++03 TEST_SUITE=misc + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++14 TEST_SUITE=conversions addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -210,13 +330,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++11 TEST_SUITE=misc + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z TEST_SUITE=conversions addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -224,6 +346,55 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03 TEST_SUITE=misc + addons: + apt: + packages: + - g++-6 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11 TEST_SUITE=misc + addons: + apt: + packages: + - g++-6 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14 TEST_SUITE=misc + addons: + apt: + packages: + - g++-6 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++14 TEST_SUITE=misc @@ -231,6 +402,7 @@ matrix: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -238,13 +410,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++03 TEST_SUITE="compile_fail examples" + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z TEST_SUITE=misc addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -252,13 +426,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++11 TEST_SUITE="compile_fail examples" + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03 TEST_SUITE="examples compile_fail" addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -266,13 +442,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++14 TEST_SUITE="compile_fail examples" + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11 TEST_SUITE="examples compile_fail" addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -280,13 +458,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++03 TEST_SUITE=concepts + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14 TEST_SUITE="examples compile_fail" addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -294,13 +474,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++11 TEST_SUITE=concepts + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z TEST_SUITE="examples compile_fail" addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -308,13 +490,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++14 TEST_SUITE=concepts + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03 TEST_SUITE=concepts addons: apt: packages: - g++-6 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -322,6 +506,55 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11 TEST_SUITE=concepts + addons: + apt: + packages: + - g++-6 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14 TEST_SUITE=concepts + addons: + apt: + packages: + - g++-6 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z TEST_SUITE=concepts + addons: + apt: + packages: + - g++-6 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 TEST_SUITE=arithmetic_tests @@ -329,6 +562,7 @@ matrix: apt: packages: - g++-5 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -336,6 +570,7 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 TEST_SUITE=cpp_int_tests @@ -343,6 +578,7 @@ matrix: apt: packages: - g++-5 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -350,6 +586,7 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 TEST_SUITE=functions_and_limits @@ -357,6 +594,7 @@ matrix: apt: packages: - g++-5 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -364,13 +602,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 TEST_SUITE="conversions performance" + env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 TEST_SUITE=conversions addons: apt: packages: - g++-5 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -378,6 +618,7 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 TEST_SUITE=misc @@ -385,6 +626,7 @@ matrix: apt: packages: - g++-5 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -392,6 +634,7 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 TEST_SUITE="compile_fail examples" @@ -399,6 +642,7 @@ matrix: apt: packages: - g++-5 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -406,6 +650,7 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 TEST_SUITE=concepts @@ -413,6 +658,71 @@ matrix: apt: packages: - g++-5 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++03 TEST_SUITE=arithmetic_tests + addons: + apt: + packages: + - g++-8 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++11 TEST_SUITE=arithmetic_tests + addons: + apt: + packages: + - g++-8 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++14 TEST_SUITE=arithmetic_tests + addons: + apt: + packages: + - g++-8 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++17 TEST_SUITE=arithmetic_tests + addons: + apt: + packages: + - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -420,13 +730,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++17 TEST_SUITE=arithmetic_tests + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++03 TEST_SUITE=cpp_int_tests addons: apt: packages: - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -434,13 +746,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++17 TEST_SUITE=cpp_int_tests + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++11 TEST_SUITE=cpp_int_tests addons: apt: packages: - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -448,13 +762,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++17 TEST_SUITE=functions_and_limits + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++14 TEST_SUITE=cpp_int_tests addons: apt: packages: - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -462,13 +778,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++17 TEST_SUITE="conversions performance" + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++17 TEST_SUITE=cpp_int_tests addons: apt: packages: - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -476,13 +794,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++17 TEST_SUITE=misc + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++03 TEST_SUITE=functions_and_limits addons: apt: packages: - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -490,13 +810,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++17 TEST_SUITE="compile_fail examples" + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++11 TEST_SUITE=functions_and_limits addons: apt: packages: - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -504,13 +826,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test - + - llvm-toolchain-xenial-8 + - os: linux - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++17 TEST_SUITE=concepts + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++14 TEST_SUITE=functions_and_limits addons: apt: packages: - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -518,13 +842,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-9 CXXSTD=gnu++17 TEST_SUITE=arithmetic_tests + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++14 TEST_SUITE=functions_and_limits addons: apt: packages: - - g++-9 + - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -532,13 +858,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-9 CXXSTD=gnu++17 TEST_SUITE=cpp_int_tests + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++17 TEST_SUITE=functions_and_limits addons: apt: packages: - - g++-9 + - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -546,13 +874,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-9 CXXSTD=gnu++17 TEST_SUITE=functions_and_limits + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++03 TEST_SUITE=conversions addons: apt: packages: - - g++-9 + - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -560,13 +890,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-9 CXXSTD=gnu++17 TEST_SUITE="conversions performance" + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++11 TEST_SUITE=conversions addons: apt: packages: - - g++-9 + - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -574,28 +906,31 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-9 CXXSTD=gnu++17 TEST_SUITE="misc include=/usr/include/eigen3" + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++14 TEST_SUITE=conversions addons: apt: packages: - - g++-9 + - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev - libmpfi-dev - libtommath-dev - - libeigen3-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=gcc COMPILER=g++-9 CXXSTD=gnu++17 TEST_SUITE="compile_fail examples" + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++14 TEST_SUITE=conversions addons: apt: packages: - - g++-9 + - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -603,13 +938,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test - + - llvm-toolchain-xenial-8 + - os: linux - env: TOOLSET=gcc COMPILER=g++-9 CXXSTD=gnu++17 TEST_SUITE=concepts + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++17 TEST_SUITE=conversions addons: apt: packages: - - g++-9 + - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -617,13 +954,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=clang COMPILER=clang++-9 CXXSTD=c++17 TEST_SUITE=arithmetic_tests + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++03 TEST_SUITE=misc addons: apt: packages: - - clang-9 + - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -631,15 +970,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test - - sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main' - key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=clang COMPILER=clang++-9 CXXSTD=c++17 TEST_SUITE=cpp_int_tests + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++11 TEST_SUITE=misc addons: apt: packages: - - clang-9 + - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -647,15 +986,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test - - sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main' - key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=clang COMPILER=clang++-9 CXXSTD=c++17 TEST_SUITE=functions_and_limits + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++14 TEST_SUITE=misc addons: apt: packages: - - clang++-9 + - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -663,15 +1002,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test - - sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main' - key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=clang COMPILER=clang++-9 CXXSTD=c++17 TEST_SUITE="conversions performance" + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++14 TEST_SUITE=misc addons: apt: packages: - - clang-9 + - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -679,15 +1018,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test - - sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main' - key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=clang COMPILER=clang++-9 CXXSTD=c++17 TEST_SUITE=misc + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++17 TEST_SUITE=misc addons: apt: packages: - - clang-9 + - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -695,15 +1034,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test - - sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main' - key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' + - llvm-toolchain-xenial-8 - os: linux - env: TOOLSET=clang COMPILER=clang++-9 CXXSTD=c++17 TEST_SUITE="compile_fail examples" + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++03 TEST_SUITE="compile_fail examples" addons: apt: packages: - - clang-9 + - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -711,15 +1050,15 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test - - sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main' - key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' - + - llvm-toolchain-xenial-8 + - os: linux - env: TOOLSET=clang COMPILER=clang++-9 CXXSTD=c++17 TEST_SUITE=concepts + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++11 TEST_SUITE="compile_fail examples" addons: apt: packages: - - clang-9 + - g++-8 + - cmake - libgmp-dev - libmpfr-dev - libmpc-dev @@ -727,8 +1066,103 @@ matrix: - libtommath-dev sources: - ubuntu-toolchain-r-test - - sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main' - key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++14 TEST_SUITE="compile_fail examples" + addons: + apt: + packages: + - g++-8 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++17 TEST_SUITE="compile_fail examples" + addons: + apt: + packages: + - g++-8 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++03 TEST_SUITE=concepts + addons: + apt: + packages: + - g++-8 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++11 TEST_SUITE=concepts + addons: + apt: + packages: + - g++-8 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++14 TEST_SUITE=concepts + addons: + apt: + packages: + - g++-8 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++17 TEST_SUITE=concepts + addons: + apt: + packages: + - g++-8 + - cmake + - libgmp-dev + - libmpfr-dev + - libmpc-dev + - libmpfi-dev + - libtommath-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 - os: osx env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14 TEST_SUITE=arithmetic_tests @@ -743,7 +1177,7 @@ matrix: osx_image: xcode9.3 - os: osx - env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14 TEST_SUITE="conversions performance" + env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14 TEST_SUITE=conversions osx_image: xcode9.3 - os: osx @@ -771,7 +1205,7 @@ matrix: osx_image: xcode8.3 - os: osx - env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14 TEST_SUITE="conversions performance" + env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14 TEST_SUITE=conversions osx_image: xcode8.3 - os: osx @@ -799,7 +1233,7 @@ matrix: osx_image: xcode7.3 - os: osx - env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14 TEST_SUITE="conversions performance" + env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14 TEST_SUITE=conversions osx_image: xcode7.3 - os: osx @@ -816,11 +1250,16 @@ matrix: install: - cd .. - - git clone -b $TRAVIS_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + - if [[ $TRAVIS_BRANCH == master || $TRAVIS_BRANCH == cmake-master ]]; then + git clone -b master --depth 1 https://github.com/boostorg/boost.git boost-root; + elif [[ $TRAVIS_BRANCH == develop || $TRAVIS_BRANCH == cmake-develop ]]; then + git clone -b develop --depth 1 https://github.com/boostorg/boost.git boost-root; + else + git clone -b develop --depth 1 https://github.com/boostorg/boost.git boost-root; + fi - cd boost-root - git submodule update --init tools/build - git submodule update --init libs/config - - git submodule update --init libs/polygon - git submodule update --init tools/boost_install - git submodule update --init libs/headers - git submodule update --init tools/boostdep @@ -832,10 +1271,23 @@ install: script: - |- echo "using $TOOLSET : : $COMPILER : -std=$CXXSTD ;" > ~/user-config.jam - - (cd libs/config/test && ../../../b2 config_info_travis_install toolset=$TOOLSET && ./config_info_travis) - - (cd libs/multiprecision/test && ../../../b2 -j3 toolset=$TOOLSET $TEST_SUITE define=CI_SUPPRESS_KNOWN_ISSUES define=SLOW_COMPILER) + - if [[ $TRAVIS_OS_NAME == linux ]]; then + proc=$(($(nproc) + 1)); + elif [[ $TRAVIS_OS_NAME == osx ]]; then + proc=$(($(sysctl -n hw.ncpu) + 1)); + fi; + - (cd libs/config/test && ../../../b2 config_info_travis_install toolset=$TOOLSET && ./config_info_travis); + - (cd libs/multiprecision/test && ../../../b2 -j$proc toolset=$TOOLSET $TEST_SUITE define=CI_SUPPRESS_KNOWN_ISSUES define=SLOW_COMPILER); + - sudo ./b2 -j$proc install; + - cd $TRAVIS_BUILD_DIR && mkdir cmake-build && cd cmake-build; + - if [[ $(echo $CXXSTD | sed 's/[^0-9]*//g') == 03 ]]; then + CXXSTD=c++98; + fi; + - if [[ $CXXSTD == c++1z ]]; then + CXXSTD=c++17; + fi; + - cmake -DBUILD_TESTS=TRUE -DCMAKE_CXX_STANDARD=$(echo $CXXSTD | sed 's/[^0-9]*//g') -DBUILD_WITH_CI_KNOWN_ISSUES_SUPPRESS=TRUE ..; notifications: email: on_success: always - diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..5cb947570 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,92 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# Copyright (c) 2018-2020 Alexey Moskvin +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.5) + +set(BOOST_CMAKE FALSE) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake" + "${CMAKE_CURRENT_LIST_DIR}/cmake/packages" + "${CMAKE_CURRENT_LIST_DIR}/cmake/modules/share/modules/cmake") + +include(CMDeploy) +include(CMConfig) +include(CMSetupVersion) + +cm_setup_version(VERSION 1.73.0) + +option(BUILD_WITH_CI_KNOWN_ISSUES_SUPPRESS "Build for CI suppressing known issues" FALSE) +option(BUILD_TESTS "Build unit tests" FALSE) + +if(BUILD_WITH_CI_KNOWN_ISSUES_SUPPRESS) + add_definitions(-DCI_SUPPRESS_KNOWN_ISSUES) +endif() + +if("${CMAKE_WORKSPACE_NAME}" STREQUAL "boost") + set(BOOST_CMAKE TRUE) + + cm_project(multiprecision WORKSPACE_NAME ${CMAKE_WORKSPACE_NAME}) + + find_package(${CMAKE_WORKSPACE_NAME}_core) + find_package(${CMAKE_WORKSPACE_NAME}_static_assert) + find_package(${CMAKE_WORKSPACE_NAME}_predef) + find_package(${CMAKE_WORKSPACE_NAME}_mpl) + find_package(${CMAKE_WORKSPACE_NAME}_random) + find_package(${CMAKE_WORKSPACE_NAME}_functional) + find_package(${CMAKE_WORKSPACE_NAME}_assert) + find_package(${CMAKE_WORKSPACE_NAME}_type_traits) + find_package(${CMAKE_WORKSPACE_NAME}_smart_ptr) + find_package(${CMAKE_WORKSPACE_NAME}_rational) + find_package(${CMAKE_WORKSPACE_NAME}_lexical_cast) + find_package(${CMAKE_WORKSPACE_NAME}_integer) + find_package(${CMAKE_WORKSPACE_NAME}_array) + find_package(${CMAKE_WORKSPACE_NAME}_config) + find_package(${CMAKE_WORKSPACE_NAME}_throw_exception) + find_package(${CMAKE_WORKSPACE_NAME}_math) + + add_library(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE) + set_property(TARGET ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PROPERTY EXPORT_NAME ${CURRENT_PROJECT_NAME}) + + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::core) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::static_assert) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::predef) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::mpl) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::random) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::functional) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::assert) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::type_traits) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::smart_ptr) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::rational) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::lexical_cast) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::integer) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::array) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::config) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::throw_exception) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::math) + +else() + cm_workspace(boost SOURCES_DIR "${CMAKE_CURRENT_LIST_DIR}") + + cm_project(multiprecision WORKSPACE_NAME ${CMAKE_WORKSPACE_NAME}) + + find_package(Boost COMPONENTS REQUIRED random) + + add_library(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE) + set_property(TARGET ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PROPERTY EXPORT_NAME ${CURRENT_PROJECT_NAME}) + + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${Boost_LIBRARIES}) +endif() + +cm_deploy(TARGETS ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} + INCLUDE ${CURRENT_SOURCES_DIR}/include + NAMESPACE ${CMAKE_WORKSPACE_NAME}::) + +if(BUILD_TESTS) + add_subdirectory(test) +endif() diff --git a/appveyor.yml b/appveyor.yml index a2ce9b2bf..895469b5f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,7 @@ # Copyright 2016 Peter Dimov +# Copyright 2019 Aleksey Moskvin +# Copyright 2019 Mikhail Komarov +# Copyright 2019 Nil Foundation AG # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) @@ -10,80 +13,124 @@ branches: only: - master - develop + - cmake-develop + - 2-modular-adaptor platform: - x64 +os: unstable + environment: matrix: - - ARGS: --toolset=msvc-9.0 address-model=32 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + ARGS: --toolset=msvc-14.2 address-model=64 cxxstd=17 TARGETS: arithmetic_tests cpp_int_tests functions_and_limits - - ARGS: --toolset=msvc-9.0 address-model=32 - TARGETS: conversions misc compile_fail examples concepts - - ARGS: --toolset=msvc-10.0 address-model=32 + TARGETS_CMAKE: multiprecision_test_suite_arithmetic_tests multiprecision_test_suite_cpp_int_tests multiprecision_test_suite_functions_and_limits + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + ARGS: --toolset=msvc-14.2 address-model=64 cxxstd=17 TARGETS: arithmetic_tests cpp_int_tests functions_and_limits - - ARGS: --toolset=msvc-10.0 address-model=32 - TARGETS: conversions misc compile_fail examples concepts - - ARGS: --toolset=msvc-11.0 address-model=32 + TARGETS_CMAKE: multiprecision_test_suite_conversions multiprecision_test_suite_misc multiprecision_test_suite_compile_fail multiprecision_test_suite_examples multiprecision_test_suite_concepts + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + ARGS: --toolset=msvc-14.1 address-model=64 cxxstd=17 TARGETS: arithmetic_tests cpp_int_tests functions_and_limits - - ARGS: --toolset=msvc-11.0 address-model=32 - TARGETS: conversions misc compile_fail examples concepts - - ARGS: --toolset=msvc-12.0 address-model=32 + TARGETS_CMAKE: multiprecision_test_suite_arithmetic_tests multiprecision_test_suite_cpp_int_tests multiprecision_test_suite_functions_and_limits + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + ARGS: --toolset=msvc-14.1 address-model=64 cxxstd=17 + TARGETS: arithmetic_tests cpp_int_tests functions_and_limits + TARGETS_CMAKE: multiprecision_test_suite_conversions multiprecision_test_suite_misc multiprecision_test_suite_compile_fail multiprecision_test_suite_examples multiprecision_test_suite_concepts + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + ARGS: --toolset=msvc-14.0 address-model=64 cxxstd=17 + TARGETS: arithmetic_tests cpp_int_tests functions_and_limits + TARGETS_CMAKE: multiprecision_test_suite_arithmetic_tests multiprecision_test_suite_cpp_int_tests multiprecision_test_suite_functions_and_limits + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + ARGS: --toolset=msvc-14.0 address-model=64 cxxstd=17 TARGETS: arithmetic_tests cpp_int_tests functions_and_limits - - ARGS: --toolset=msvc-12.0 address-model=32 + TARGETS_CMAKE: multiprecision_test_suite_conversions multiprecision_test_suite_misc multiprecision_test_suite_compile_fail multiprecision_test_suite_examples multiprecision_test_suite_concepts + + - ARGS: --toolset=msvc-10.0 address-model=32 + TARGETS: arithmetic_tests cpp_int_tests functions_and_limits + TARGETS_CMAKE: multiprecision_test_suite_arithmetic_tests multiprecision_test_suite_cpp_int_tests multiprecision_test_suite_functions_and_limits + - ARGS: --toolset=msvc-10.0 address-model=32 TARGETS: conversions misc compile_fail examples concepts - - ARGS: --toolset=msvc-14.0 address-model=32 + TARGETS_CMAKE: multiprecision_test_suite_conversions multiprecision_test_suite_misc multiprecision_test_suite_compile_fail multiprecision_test_suite_examples multiprecision_test_suite_concepts + + - ARGS: --toolset=msvc-11.0 address-model=32 TARGETS: arithmetic_tests cpp_int_tests functions_and_limits - - ARGS: --toolset=msvc-14.0 address-model=32 + TARGETS_CMAKE: multiprecision_test_suite_arithmetic_tests multiprecision_test_suite_cpp_int_tests multiprecision_test_suite_functions_and_limits + - ARGS: --toolset=msvc-11.0 address-model=32 TARGETS: conversions misc compile_fail examples concepts - - ARGS: --toolset=msvc-12.0 address-model=64 + TARGETS_CMAKE: multiprecision_test_suite_conversions multiprecision_test_suite_misc multiprecision_test_suite_compile_fail multiprecision_test_suite_examples multiprecision_test_suite_concepts + + - ARGS: --toolset=msvc-12.0 address-model=32 TARGETS: arithmetic_tests cpp_int_tests functions_and_limits - - ARGS: --toolset=msvc-12.0 address-model=64 + TARGETS_CMAKE: multiprecision_test_suite_arithmetic_tests multiprecision_test_suite_cpp_int_tests multiprecision_test_suite_functions_and_limits + - ARGS: --toolset=msvc-12.0 address-model=32 TARGETS: conversions misc compile_fail examples concepts - - ARGS: --toolset=msvc-14.0 address-model=64 + TARGETS_CMAKE: multiprecision_test_suite_conversions multiprecision_test_suite_misc multiprecision_test_suite_compile_fail multiprecision_test_suite_examples multiprecision_test_suite_concepts + + - ARGS: --toolset=msvc-14.0 address-model=32 TARGETS: arithmetic_tests cpp_int_tests functions_and_limits - - ARGS: --toolset=msvc-14.0 address-model=64 + TARGETS_CMAKE: multiprecision_test_suite_arithmetic_tests multiprecision_test_suite_cpp_int_tests multiprecision_test_suite_functions_and_limits + - ARGS: --toolset=msvc-14.0 address-model=32 TARGETS: conversions misc compile_fail examples concepts - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - ARGS: --toolset=msvc-14.2 address-model=64 cxxstd=17 + TARGETS_CMAKE: multiprecision_test_suite_conversions multiprecision_test_suite_misc multiprecision_test_suite_compile_fail multiprecision_test_suite_examples multiprecision_test_suite_concepts + + - ARGS: --toolset=msvc-12.0 address-model=64 TARGETS: arithmetic_tests cpp_int_tests functions_and_limits - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - ARGS: --toolset=msvc-14.2 address-model=64 cxxstd=17 + TARGETS_CMAKE: multiprecision_test_suite_arithmetic_tests multiprecision_test_suite_cpp_int_tests multiprecision_test_suite_functions_and_limits + - ARGS: --toolset=msvc-12.0 address-model=64 TARGETS: conversions misc compile_fail examples concepts - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - ARGS: --toolset=msvc-14.2 address-model=32 cxxstd=17 + TARGETS_CMAKE: multiprecision_test_suite_conversions multiprecision_test_suite_misc multiprecision_test_suite_compile_fail multiprecision_test_suite_examples multiprecision_test_suite_concepts + + - ARGS: --toolset=msvc-14.0 address-model=64 TARGETS: arithmetic_tests cpp_int_tests functions_and_limits - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - ARGS: --toolset=msvc-14.2 address-model=32 cxxstd=17 + TARGETS_CMAKE: multiprecision_test_suite_arithmetic_tests multiprecision_test_suite_cpp_int_tests multiprecision_test_suite_functions_and_limits + - ARGS: --toolset=msvc-14.0 address-model=64 TARGETS: conversions misc compile_fail examples concepts - - ARGS: --toolset=gcc address-model=64 + TARGETS_CMAKE: multiprecision_test_suite_conversions multiprecision_test_suite_misc multiprecision_test_suite_compile_fail multiprecision_test_suite_examples multiprecision_test_suite_concepts + + - ARGS: --toolset=gcc address-model=64 TARGETS: arithmetic_tests cpp_int_tests functions_and_limits PATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;%PATH% - - ARGS: --toolset=gcc address-model=64 + TARGETS_CMAKE: multiprecision_test_suite_arithmetic_tests multiprecision_test_suite_cpp_int_tests multiprecision_test_suite_functions_and_limits + + - ARGS: --toolset=gcc address-model=64 TARGETS: conversions misc compile_fail examples concepts PATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;%PATH% - - ARGS: --toolset=gcc address-model=64 cxxstd=2a cxxstd-dialect=gnu + TARGETS_CMAKE: multiprecision_test_suite_conversions multiprecision_test_suite_misc multiprecision_test_suite_compile_fail multiprecision_test_suite_examples multiprecision_test_suite_concepts + + - ARGS: --toolset=gcc address-model=64 cxxstd=2a cxxstd-dialect=gnu TARGETS: arithmetic_tests cpp_int_tests functions_and_limits PATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;%PATH% - - ARGS: --toolset=gcc address-model=64 cxxstd=2a cxxstd-dialect=gnu + TARGETS_CMAKE: multiprecision_test_suite_arithmetic_tests multiprecision_test_suite_cpp_int_tests multiprecision_test_suite_functions_and_limits + + - ARGS: --toolset=gcc address-model=64 cxxstd=2a cxxstd-dialect=gnu TARGETS: conversions misc compile_fail examples concepts PATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;%PATH% + TARGETS_CMAKE: multiprecision_test_suite_conversions multiprecision_test_suite_misc multiprecision_test_suite_compile_fail multiprecision_test_suite_examples multiprecision_test_suite_concepts install: - cd .. - - git clone -b %APPVEYOR_REPO_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + - if not %APPVEYOR_REPO_BRANCH% == "master" if not %APPVEYOR_REPO_BRANCH% == "develop" ( + git clone -b develop --depth 1 https://github.com/boostorg/boost.git boost-root + ) Else ( + git clone -b %APPVEYOR_REPO_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + ) - cd boost-root - git submodule update --init tools/build - git submodule update --init tools/boost_install - git submodule update --init libs/headers - git submodule update --init libs/config - - git submodule update --init libs/polygon - xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\multiprecision - git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py multiprecision - - bootstrap + - bootstrap.bat - b2 headers + - b2 install build: off @@ -93,3 +140,10 @@ test_script: - config_info_travis - cd ..\..\multiprecision\test - ..\..\..\b2 --hash -j3 %ARGS% %TARGETS% define=CI_SUPPRESS_KNOWN_ISSUES + + - cd .. + - for /f %%a in ('dir /b C:\Boost\lib\cmake\Boost-*') do (set boost_dir=C:\Boost\lib\cmake\%%a) + - mkdir cmake-build + - cd cmake-build + - cmake -DBoost_DIR=%boost_dir% -DBUILD_TESTS=TRUE -DCMAKE_CXX_STANDARD=14 -DBUILD_WITH_CI_KNOWN_ISSUES_SUPPRESS=TRUE -DBUILD_SHARED_LIBS=TRUE -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE --build .. +# - cmake --build C:/projects/boost-root/libs/multiprecision/cmake-build --target %TARGETS_CMAKE% diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt new file mode 100644 index 000000000..1f0da6fe2 --- /dev/null +++ b/cmake/modules/CMakeLists.txt @@ -0,0 +1,15 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +cmake_minimum_required (VERSION 3.5) + +install(DIRECTORY share/modules/cmake DESTINATION cm) + +enable_testing() +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C ${CMAKE_CFG_INTDIR}) +add_subdirectory(test) diff --git a/cmake/modules/share/modules/cmake/CMConfig.cmake b/cmake/modules/share/modules/cmake/CMConfig.cmake new file mode 100644 index 000000000..6eb1a3fa1 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMConfig.cmake @@ -0,0 +1,202 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) +include(CMFuture) +enable_testing() + +function(contains_path FILEPATH SUBPATH RESULT) + file(RELATIVE_PATH PATH "${SUBPATH}" "${FILEPATH}") + if(${PATH} MATCHES "\\.\\./") + set(${RESULT} FALSE PARENT_SCOPE) + else() + set(${RESULT} TRUE PARENT_SCOPE) + endif() +endfunction() + +function(add_subdirectories INPUT_DIRECTORY) + set(options) + set(oneValueArgs SUBMODULE_DEFINITION_HEADER) + set(multiValueArgs EXCLUDE_DIRS EXCLUDE_LIBS) + + set(INCLUDED_DIRS) + set(INCLUDED_LIBS) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + file(GLOB_RECURSE LIBS ${INPUT_DIRECTORY}/*CMakeLists.txt) + + if(PARSE_EXCLUDE_DIRS) + set(EXCLUDED_DIRS) + + foreach(ITERATOR ${LIBS}) + foreach(DIR_ITERATOR IN LISTS PARSE_EXCLUDE_DIRS) + contains_path(${ITERATOR} ${DIR_ITERATOR} CONTAINS) + if(${CONTAINS}) + list(APPEND EXCLUDED_DIRS ${ITERATOR}) + endif() + endforeach() + endforeach() + + list(REMOVE_ITEM LIBS ${EXCLUDED_DIRS}) + endif() + + foreach(lib ${LIBS}) + file(READ ${lib} CONTENT) + if(PARSE_SUBMODULE_DEFINITION_HEADER) + if("${CONTENT}" MATCHES ${PARSE_SUBMODULE_DEFINITION_HEADER}) + get_filename_component(LIB_DIR ${lib} DIRECTORY) + get_filename_component(LIB_NAME ${LIB_DIR} NAME) + if(PARSE_EXCLUDE_LIBS OR PARSE_EXCLUDE_DIRS) + if(NOT "${LIB_NAME}" IN_LIST PARSE_EXCLUDE_LIBS AND NOT "${LIB_DIR}" IN_LIST PARSE_EXCLUDE_DIRS) + list(APPEND INCLUDED_LIBS ${LIB_NAME}) + list(APPEND INCLUDED_DIRS ${LIB_DIR}) + add_subdirectory(${LIB_DIR}) + endif() + else() + list(APPEND INCLUDED_LIBS ${LIB_NAME}) + list(APPEND INCLUDED_DIRS ${LIB_DIR}) + add_subdirectory(${LIB_DIR}) + endif() + endif() + else() + get_filename_component(LIB_DIR ${lib} DIRECTORY) + get_filename_component(LIB_NAME ${LIB_DIR} NAME) + if(PARSE_EXCLUDE_LIBS OR PARSE_EXCLUDE_DIRS) + if(NOT "${LIB_NAME}" IN_LIST PARSE_EXCLUDE_LIBS AND NOT "${LIB_DIR}" IN_LIST PARSE_EXCLUDE_DIRS) + list(APPEND INCLUDED_LIBS ${LIB_NAME} PARENT_SCOPE) + list(APPEND INCLUDED_DIRS ${LIB_DIR} PARENT_SCOPE) + add_subdirectory(${LIB_DIR}) + endif() + else() + + list(APPEND INCLUDED_LIBS ${LIB_NAME} PARENT_SCOPE) + list(APPEND INCLUDED_DIRS ${LIB_DIR} PARENT_SCOPE) + add_subdirectory(${LIB_DIR}) + endif() + endif() + endforeach() + + set(INCLUDED_DIRS ${INCLUDED_DIRS} PARENT_SCOPE) + set(INCLUDED_LIBS ${INCLUDED_LIBS} PARENT_SCOPE) +endfunction() + +function(cm_project INPUT_PROJECT_NAME) + set(options) + set(oneValueArgs DESCRIPTION VERSION WORKSPACE_NAME) + set(multiValueArgs LANGUAGES) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(PARSE_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to workspace(): \"${PARSE_UNPARSED_ARGUMENTS}\"") + endif() + + if(PARSE_WORKSPACE_NAME) + if(PARSE_VERSION AND PARSE_LANGUAGES AND PARSE_DESCRIPTION) + project(${INPUT_WORKSPACE_NAME}_${INPUT_PROJECT_NAME} + VERSION ${PARSE_VERSION} + DESCRIPTION ${PARSE_DESCRIPTION} + LANGUAGES ${PARSE_LANGUAGES}) + elseif(PARSE_LANGUAGES) + project(${INPUT_WORKSPACE_NAME}_${INPUT_PROJECT_NAME} ${PARSE_LANGUAGES}) + else() + project(${INPUT_WORKSPACE_NAME}_${INPUT_PROJECT_NAME}) + endif() + endif() + + set(CURRENT_PROJECT_NAME ${INPUT_PROJECT_NAME} PARENT_SCOPE) + set(CMAKE_PROJECT_NAME ${CMAKE_PROJECT_NAME} PARENT_SCOPE) + set(PROJECT_NAME ${INPUT_PROJECT_NAME} PARENT_SCOPE) + + string(TOUPPER ${INPUT_PROJECT_NAME} UPPER_PROJECT_NAME) + set(CURRENT_UPPER_PROJECT_NAME ${UPPER_PROJECT_NAME} PARENT_SCOPE) + + if(PARSE_WORKSPACE_NAME) + file(RELATIVE_PATH RELATIVE_DIR ${CMAKE_WORKSPACE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + + set(CURRENT_SOURCES_DIR ${CMAKE_WORKSPACE_SOURCES_DIR}/${RELATIVE_DIR} PARENT_SCOPE) + set(CURRENT_TEST_SOURCES_DIR ${CMAKE_WORKSPACE_SOURCES_DIR}/${RELATIVE_DIR}/test PARENT_SCOPE) + endif() +endfunction() + +function(cm_workspace WORKSPACE_NAME) + set(options) + set(oneValueArgs DESCRIPTION VERSION SOURCES_DIR) + set(multiValueArgs LANGUAGES) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(PARSE_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to workspace(): \"${PARSE_UNPARSED_ARGUMENTS}\"") + endif() + + project(${WORKSPACE_NAME} ${PARSE_VERSION} ${PARSE_DESCRIPTION} ${PARSE_LANGUAGES}) + set(PROJECT_NAME ${WORKSPACE_NAME} PARENT_SCOPE) + set(CMAKE_PROJECT_NAME ${WORKSPACE_NAME} PARENT_SCOPE) + set(CMAKE_WORKSPACE_NAME ${WORKSPACE_NAME} PARENT_SCOPE) + set(CMAKE_WORKSPACE_LIST ${CMAKE_WORKSPACE_LIST} ${CMAKE_WORKSPACE_NAME} PARENT_SCOPE) + set(CMAKE_WORKSPACE_DIR ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE) + string(TOUPPER ${WORKSPACE_NAME} UPPER_WORKSPACE_NAME) + set(CMAKE_UPPER_WORKSPACE_NAME ${UPPER_WORKSPACE_NAME} PARENT_SCOPE) + + if(PARSE_SOURCES_DIR) + set(CMAKE_WORKSPACE_SOURCES_DIR ${PARSE_SOURCES_DIR} PARENT_SCOPE) + endif() +endfunction() + +function(patch_file INPUT_SOURCE INPUT_PATCH OUTPUT_DIRECTORY) + set(options) + set(oneValueArgs PREFIX_PATCH_NAME POSTFIX_PATCH_NAME) + set(multiValueArgs) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + find_package(Patch) + if(NOT Patch_FOUND) + message("Patch utulity is not found") + endif() + string(REPLACE ${CURRENT_TEST_SOURCES_DIR} ${CMAKE_CURRENT_BINARY_DIR} OUTPUT_FILE ${INPUT_SOURCE}) + file(COPY ${INPUT_SOURCE} DESTINATION ${OUTPUT_DIRECTORY}) + get_filename_component(SOURCE_FILE_NAME ${INPUT_SOURCE} NAME) + set(NEW_SOURCE_FILE_NAME ${PARSE_PREFIX_PATCH_NAME}${SOURCE_FILE_NAME}) + if(PARSE_POSTFIX_PATCH_NAME) + string(REPLACE . ${PARSE_POSTFIX_PATCH_NAME}. NEW_SOURCE_FILE_NAME ${NEW_SOURCE_FILE_NAME}) + endif() + file(RENAME ${OUTPUT_DIRECTORY}/${SOURCE_FILE_NAME} ${OUTPUT_DIRECTORY}/${NEW_SOURCE_FILE_NAME}) + execute_process(COMMAND patch ${OUTPUT_DIRECTORY}/${NEW_SOURCE_FILE_NAME} ${INPUT_PATCH} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) +endfunction() + +function(patch_directory SOURCES_DIRECTORY PATCHES_DIRECTORY OUTPUT_DIRECTORY) + set(options) + set(oneValueArgs PREFIX_PATCH_NAME POSTFIX_PATCH_NAME) + set(multiValueArgs) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + find_package(Patch) + if(NOT Patch_FOUND) + message("Patch utulity is not found") + endif() + file(GLOB_RECURSE PATCHES_FILES LIST_DIRECTORIES FALSE ${PATCHES_DIRECTORY}/*.patch) + file(GLOB_RECURSE SOURCES_FILES LIST_DIRECTORIES FALSE ${SOURCES_DIRECTORY}/*) + foreach(PATCH_FILE IN LISTS PATCHES_FILES) + string(REPLACE ".patch" "" SOURCE_FILE_NAME ${PATCH_FILE}) + string(REPLACE ${PATCHES_DIRECTORY} ${SOURCES_DIRECTORY} SOURCE_FILE_NAME ${SOURCE_FILE_NAME}) + list(FIND SOURCES_FILES ${SOURCE_FILE_NAME} SOURCES_FILE_FIND) + if(${SOURCES_FILE_FIND} EQUAL -1) + message(FATAL_ERROR "Source file for patch is not found: " ${PATCH_FILE}) + endif() + list(GET SOURCES_FILES ${SOURCES_FILE_FIND} SOURCE_FILE) + string(REPLACE ${SOURCES_DIRECTORY} ${OUTPUT_DIRECTORY} OUTPUT_FILE_DIRECTORY ${SOURCE_FILE}) + get_filename_component(OUTPUT_FILE_DIRECTORY ${OUTPUT_FILE_DIRECTORY} DIRECTORY) + patch_file(${SOURCE_FILE} ${PATCH_FILE} ${OUTPUT_FILE_DIRECTORY} + PREFIX_PATCH_NAME ${PARSE_PREFIX_PATCH_NAME} POSTFIX_PATCH_NAME ${PARSE_POSTFIX_PATCH_NAME}) + endforeach() +endfunction() diff --git a/cmake/modules/share/modules/cmake/CMDeploy.cmake b/cmake/modules/share/modules/cmake/CMDeploy.cmake new file mode 100644 index 000000000..4fc048c9c --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMDeploy.cmake @@ -0,0 +1,49 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +include(CMPkgConfig) +include(CMInstallTargets) +include(CMExport) + +function(cm_deploy) + set(options SKIP_HEADER_INSTALL) + set(oneValueArgs NAMESPACE COMPATIBILITY) + set(multiValueArgs TARGETS INCLUDE) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(PARSE_SKIP_HEADER_INSTALL) + cm_install_targets(TARGETS ${PARSE_TARGETS} INCLUDE ${PARSE_INCLUDE} SKIP_HEADER_INSTALL) + else() + cm_install_targets(TARGETS ${PARSE_TARGETS} INCLUDE ${PARSE_INCLUDE} ) + endif() + + cm_auto_pkgconfig(TARGET ${PARSE_TARGETS}) + cm_auto_export(TARGETS ${PARSE_TARGETS} NAMESPACE ${PARSE_NAMESPACE} COMPATIBILITY ${PARSE_COMPATIBILITY}) + + foreach(TARGET ${PARSE_TARGETS}) + get_target_property(TARGET_NAME ${TARGET} EXPORT_NAME) + if(NOT TARGET_NAME) + get_target_property(TARGET_NAME ${TARGET} NAME) + endif() + set(EXPORT_LIB_TARGET ${PARSE_NAMESPACE}${TARGET_NAME}) + if(NOT TARGET ${EXPORT_LIB_TARGET}) + add_library(${EXPORT_LIB_TARGET} ALIAS ${TARGET}) + endif() + set_target_properties(${TARGET} PROPERTIES INTERFACE_FIND_PACKAGE_NAME ${PROJECT_NAME}) + if(COMMAND cm_add_rpath) + get_target_property(TARGET_TYPE ${TARGET} TYPE) + if(NOT "${TARGET_TYPE}" STREQUAL "INTERFACE_LIBRARY") + cm_add_rpath("$") + endif() + endif() + cm_shadow_notify(${EXPORT_LIB_TARGET}) + cm_shadow_notify(${TARGET}) + endforeach() + +endfunction() diff --git a/cmake/modules/share/modules/cmake/CMExport.cmake b/cmake/modules/share/modules/cmake/CMExport.cmake new file mode 100644 index 000000000..e3477c875 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMExport.cmake @@ -0,0 +1,154 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +include(GNUInstallDirs) +include(WriteBasicConfigVersionFile) + +function(cm_get_target_package_source OUT_VAR TARGET) + set(RESULT) + if(TARGET ${TARGET}) + get_property(TARGET_ALIAS TARGET ${TARGET} PROPERTY ALIASED_TARGET) + if(TARGET_ALIAS) + set(TARGET ${TARGET_ALIAS}) + endif() + get_property(TARGET_IMPORTED TARGET ${TARGET} PROPERTY IMPORTED) + if(TARGET_IMPORTED OR TARGET_ALIAS) + get_property(TARGET_FIND_PACKAGE_NAME TARGET ${TARGET} PROPERTY INTERFACE_FIND_PACKAGE_NAME) + if(NOT TARGET_FIND_PACKAGE_NAME) + message(SEND_ERROR "The target ${TARGET_FIND_PACKAGE_NAME} does not have information about find_package() call.") + endif() + set(PKG_NAME ${TARGET_FIND_PACKAGE_NAME}) + get_property(TARGET_FIND_PACKAGE_VERSION TARGET ${TARGET} PROPERTY INTERFACE_FIND_PACKAGE_VERSION) + if(TARGET_FIND_PACKAGE_VERSION) + set(PKG_NAME "${PKG_NAME} ${TARGET_FIND_PACKAGE_VERSION}") + endif() + get_property(TARGET_FIND_PACKAGE_EXACT TARGET ${TARGET} PROPERTY INTERFACE_FIND_PACKAGE_EXACT) + if(TARGET_FIND_PACKAGE_EXACT) + set(PKG_NAME "${PKG_NAME} ${TARGET_FIND_PACKAGE_EXACT}") + endif() + set(RESULT "${PKG_NAME}") + # get_property(TARGET_FIND_PACKAGE_REQUIRED TARGET ${TARGET} PROPERTY INTERFACE_FIND_PACKAGE_REQUIRED) + # get_property(TARGET_FIND_PACKAGE_QUIETLY TARGET ${TARGET} PROPERTY INTERFACE_FIND_PACKAGE_QUIETLY) + endif() + else() + if("${TARGET}" MATCHES "::") + set(TARGET_NAME "$") + else() + set(TARGET_NAME "${TARGET}") + endif() + cm_shadow_exists(HAS_TARGET ${TARGET}) + set(RESULT "$<${HAS_TARGET}:$>") + endif() + set(${OUT_VAR} "${RESULT}" PARENT_SCOPE) +endfunction() + +function(cm_auto_export) + set(options) + set(oneValueArgs NAMESPACE EXPORT NAME COMPATIBILITY) + set(multiValueArgs TARGETS) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER) + set(PACKAGE_NAME ${PROJECT_NAME}) + if(PARSE_NAME) + set(PACKAGE_NAME ${PARSE_NAME}) + endif() + + string(TOUPPER ${PACKAGE_NAME} PACKAGE_NAME_UPPER) + string(TOLOWER ${PACKAGE_NAME} PACKAGE_NAME_LOWER) + + set(TARGET_FILE ${PROJECT_NAME_LOWER}-targets) + if(PARSE_EXPORT) + set(TARGET_FILE ${PARSE_EXPORT}) + endif() + set(CONFIG_NAME ${PACKAGE_NAME_LOWER}-config) + set(TARGET_VERSION ${PROJECT_VERSION}) + + set(BIN_INSTALL_DIR ${CMAKE_INSTALL_BINDIR}) + set(LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}) + set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}) + set(CONFIG_PACKAGE_INSTALL_DIR ${LIB_INSTALL_DIR}/cmake/${PACKAGE_NAME_LOWER}) + + set(CONFIG_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}.cmake") + + set(CONFIG_FILE_CONTENT " +include(CMakeFindDependencyMacro) +") + + if(PARSE_TARGETS) + # Add dependencies + foreach(TARGET ${PARSE_TARGETS}) + get_property(TARGET_LIBS TARGET ${TARGET} PROPERTY INTERFACE_LINK_LIBRARIES) + foreach(LIB ${TARGET_LIBS}) + cm_get_target_package_source(PKG_SRC ${LIB}) + set(HAS_PKG_SRC "$") + string(APPEND CONFIG_FILE_CONTENT "# $<$:Skip >Library: ${LIB}\n") + string(APPEND CONFIG_FILE_CONTENT "$<${HAS_PKG_SRC}:find_dependency(${PKG_SRC})>\n") + endforeach() + endforeach() + # Compute targets imported name + set(EXPORT_LIB_TARGETS) + foreach(TARGET ${PARSE_TARGETS}) + get_target_property(TARGET_NAME ${TARGET} EXPORT_NAME) + if(NOT TARGET_NAME) + get_target_property(TARGET_NAME ${TARGET} NAME) + endif() + set(EXPORT_LIB_TARGET_${TARGET} ${PARSE_NAMESPACE}${TARGET_NAME}) + list(APPEND EXPORT_LIB_TARGETS ${EXPORT_LIB_TARGET_${TARGET}}) + endforeach() + # Export custom properties + set(EXPORT_PROPERTIES) + foreach(TARGET ${PARSE_TARGETS}) + # TODO: Make this a property: the custom properties to be exported + foreach(PROPERTY INTERFACE_PKG_CONFIG_NAME) + set(PROP "$") + set(EXPORT_PROPERTIES "${EXPORT_PROPERTIES} +$<$:set_target_properties(${EXPORT_LIB_TARGET_${TARGET}} PROPERTIES ${PROPERTY} ${PROP})> +") + endforeach() + endforeach() + string(APPEND CONFIG_FILE_CONTENT " +include(\"\${CMAKE_CURRENT_LIST_DIR}/${TARGET_FILE}.cmake\") +include(\"\${CMAKE_CURRENT_LIST_DIR}/properties-${TARGET_FILE}.cmake\") +") + endif() + + file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/properties-${TARGET_FILE}.cmake CONTENT "${EXPORT_PROPERTIES}") + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/properties-${TARGET_FILE}.cmake DESTINATION ${CONFIG_PACKAGE_INSTALL_DIR}) + + file(GENERATE OUTPUT "${CONFIG_FILE}" CONTENT "${CONFIG_FILE_CONTENT}") + + set(COMPATIBILITY_ARG SameMajorVersion) + if(PARSE_COMPATIBILITY) + set(COMPATIBILITY_ARG ${PARSE_COMPATIBILITY}) + endif() + write_basic_config_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}-version.cmake + VERSION ${TARGET_VERSION} + COMPATIBILITY ${COMPATIBILITY_ARG} + ) + + set(NAMESPACE_ARG) + if(PARSE_NAMESPACE) + set(NAMESPACE_ARG "NAMESPACE;${PARSE_NAMESPACE}") + endif() + install(EXPORT ${TARGET_FILE} + DESTINATION + ${CONFIG_PACKAGE_INSTALL_DIR} + ${NAMESPACE_ARG} + ) + + install(FILES + ${CONFIG_FILE} + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}-version.cmake + DESTINATION + ${CONFIG_PACKAGE_INSTALL_DIR}) + +endfunction() + diff --git a/cmake/modules/share/modules/cmake/CMFuture.cmake b/cmake/modules/share/modules/cmake/CMFuture.cmake new file mode 100644 index 000000000..bab070386 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMFuture.cmake @@ -0,0 +1,95 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +define_property(TARGET PROPERTY "INTERFACE_FIND_PACKAGE_NAME" + BRIEF_DOCS "The package name that was searched for to create this target" + FULL_DOCS "The package name that was searched for to create this target" +) + +define_property(TARGET PROPERTY "INTERFACE_FIND_PACKAGE_REQUIRED" + BRIEF_DOCS "true if REQUIRED option was given" + FULL_DOCS "true if REQUIRED option was given" +) + +define_property(TARGET PROPERTY "INTERFACE_FIND_PACKAGE_QUIETLY" + BRIEF_DOCS "true if QUIET option was given" + FULL_DOCS "true if QUIET option was given" +) + +define_property(TARGET PROPERTY "INTERFACE_FIND_PACKAGE_EXACT" + BRIEF_DOCS "true if EXACT option was given" + FULL_DOCS "true if EXACT option was given" +) + +define_property(TARGET PROPERTY "INTERFACE_FIND_PACKAGE_VERSION" + BRIEF_DOCS "full requested version string" + FULL_DOCS "full requested version string" +) + +# Custom property to check if target exists +define_property(TARGET PROPERTY "INTERFACE_TARGET_EXISTS" + BRIEF_DOCS "True if target exists" + FULL_DOCS "True if target exists" +) +# Create shadow target to notify that the target exists +macro(cm_shadow_notify TARGET) + if(NOT TARGET _cm_shadow_target_${TARGET}) + add_library(_cm_shadow_target_${TARGET} INTERFACE IMPORTED GLOBAL) + endif() + set_target_properties(_cm_shadow_target_${TARGET} PROPERTIES INTERFACE_TARGET_EXISTS 1) +endmacro() +# Check if target exists by querying the shadow target +macro(cm_shadow_exists OUT TARGET) + if("${TARGET}" MATCHES "^[_a-zA-Z0-9:]+$") + if(NOT TARGET _cm_shadow_target_${TARGET}) + add_library(_cm_shadow_target_${TARGET} INTERFACE IMPORTED GLOBAL) + set_target_properties(_cm_shadow_target_${TARGET} PROPERTIES INTERFACE_TARGET_EXISTS 0) + endif() + set(${OUT} "$") + else() + set(${OUT} "0") + endif() +endmacro() +# Emulate rpath for windows +if(WIN32) + if(NOT COMMAND cm_add_rpath) + foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES} "") + file(WRITE ${CMAKE_BINARY_DIR}/cm_set_rpath_pre-${CONFIG}.cmake "set(RPATH)\n") + file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/cm_set_rpath-${CONFIG}.cmake INPUT ${CMAKE_BINARY_DIR}/cm_set_rpath_pre-${CONFIG}.cmake CONDITION $) + endforeach() + function(cm_add_rpath) + foreach(_RPATH ${ARGN}) + foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES} "") + file(APPEND ${CMAKE_BINARY_DIR}/cm_set_rpath_pre-${CONFIG}.cmake "list(APPEND RPATH \"${_RPATH}\")\n") + endforeach() + endforeach() + endfunction() + endif() +endif() +# Add library extension to track imported targets +if(NOT COMMAND cm_add_library_ext) + macro(cm_add_library_ext LIB) + set(ARG_LIST "${ARGN}") + if("IMPORTED" IN_LIST ARG_LIST) + if(CMAKE_FIND_PACKAGE_NAME) + set_target_properties(${LIB} PROPERTIES INTERFACE_FIND_PACKAGE_NAME ${CMAKE_FIND_PACKAGE_NAME}) + foreach(TYPE REQUIRED QUIETLY EXACT VERSION) + if(${CMAKE_FIND_PACKAGE_NAME}_FIND_${TYPE}) + set_target_properties(${LIB} PROPERTIES INTERFACE_FIND_PACKAGE_${TYPE} ${${CMAKE_FIND_PACKAGE_NAME}_FIND_${TYPE}}) + endif() + endforeach() + endif() + endif() + endmacro() + + macro(add_library) + _add_library(${ARGN}) + cm_add_library_ext(${ARGN}) + endmacro() + +endif() diff --git a/cmake/modules/share/modules/cmake/CMIgnorePackage.cmake b/cmake/modules/share/modules/cmake/CMIgnorePackage.cmake new file mode 100644 index 000000000..a5cabd471 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMIgnorePackage.cmake @@ -0,0 +1,13 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +function(cm_ignore_package NAME) + set(${NAME}_DIR ${CMAKE_BINARY_DIR}/_cm_ignore_packages_/${NAME} CACHE PATH "") + file(WRITE ${${NAME}_DIR}/${NAME}Config.cmake "") +endfunction() + diff --git a/cmake/modules/share/modules/cmake/CMInstallTargets.cmake b/cmake/modules/share/modules/cmake/CMInstallTargets.cmake new file mode 100644 index 000000000..eb447ed2c --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMInstallTargets.cmake @@ -0,0 +1,50 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +include(GNUInstallDirs) + +function(cm_install_targets) + set(options SKIP_HEADER_INSTALL) + set(oneValueArgs EXPORT) + set(multiValueArgs TARGETS INCLUDE) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER) + set(EXPORT_FILE ${PROJECT_NAME_LOWER}-targets) + if(PARSE_EXPORT) + set(EXPORT_FILE ${PARSE_EXPORT}) + endif() + + set(BIN_INSTALL_DIR ${CMAKE_INSTALL_BINDIR}) + set(LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}) + set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}) + + foreach(TARGET ${PARSE_TARGETS}) + foreach(INCLUDE ${PARSE_INCLUDE}) + get_filename_component(INCLUDE_PATH ${INCLUDE} ABSOLUTE) + target_include_directories(${TARGET} INTERFACE $) + endforeach() + target_include_directories(${TARGET} INTERFACE $/${INCLUDE_INSTALL_DIR}>) + endforeach() + + + if(NOT PARSE_SKIP_HEADER_INSTALL) + foreach(INCLUDE ${PARSE_INCLUDE}) + install(DIRECTORY ${INCLUDE}/ DESTINATION ${INCLUDE_INSTALL_DIR}) + endforeach() + endif() + + install(TARGETS ${PARSE_TARGETS} + EXPORT ${EXPORT_FILE} + RUNTIME DESTINATION ${BIN_INSTALL_DIR} + LIBRARY DESTINATION ${LIB_INSTALL_DIR} + ARCHIVE DESTINATION ${LIB_INSTALL_DIR}) + +endfunction() + diff --git a/cmake/modules/share/modules/cmake/CMPkgConfig.cmake b/cmake/modules/share/modules/cmake/CMPkgConfig.cmake new file mode 100644 index 000000000..7057516b1 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMPkgConfig.cmake @@ -0,0 +1,257 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +include(GNUInstallDirs) + +define_property(TARGET PROPERTY "INTERFACE_DESCRIPTION" + BRIEF_DOCS "Description of the target" + FULL_DOCS "Description of the target" +) + +define_property(TARGET PROPERTY "INTERFACE_URL" + BRIEF_DOCS "An URL where people can get more information about and download the package." + FULL_DOCS "An URL where people can get more information about and download the package." +) + +define_property(TARGET PROPERTY "INTERFACE_PKG_CONFIG_REQUIRES" + BRIEF_DOCS "A list of packages required by this package. The versions of these packages may be specified using the comparison operators =, <, >, <= or >=." + FULL_DOCS "A list of packages required by this package. The versions of these packages may be specified using the comparison operators =, <, >, <= or >=." +) + +function(cm_generate_pkgconfig_file) + set(options) + set(oneValueArgs NAME LIB_DIR INCLUDE_DIR DESCRIPTION) + set(multiValueArgs TARGETS CFLAGS LIBS REQUIRES) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + set(LIB_DIR ${CMAKE_INSTALL_LIBDIR}) + if(PARSE_LIB_DIR) + set(LIB_DIR ${PARSE_LIB_DIR}) + endif() + set(INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}) + if(PARSE_INCLUDE_DIR) + set(INCLUDE_DIR ${PARSE_INCLUDE_DIR}) + endif() + + set(LIBS) + set(DESCRIPTION "No description") + if(PARSE_DESCRIPTION) + set(DESCRIPTION ${PARSE_DESCRIPTION}) + endif() + + foreach(TARGET ${PARSE_TARGETS}) + get_property(TARGET_NAME TARGET ${TARGET} PROPERTY NAME) + get_property(TARGET_TYPE TARGET ${TARGET} PROPERTY TYPE) + if(NOT TARGET_TYPE STREQUAL "INTERFACE_LIBRARY") + set(LIBS "${LIBS} -l${TARGET_NAME}") + endif() + endforeach() + + if(LIBS OR PARSE_LIBS) + set(LIBS "Libs: -L\${libdir} ${LIBS} ${PARSE_LIBS}") + endif() + + set(PKG_NAME ${PROJECT_NAME}) + if(PARSE_NAME) + set(PKG_NAME ${PARSE_NAME}) + endif() + + file(WRITE ${PKGCONFIG_FILENAME} +" +prefix=${CMAKE_INSTALL_PREFIX} +exec_prefix=\${prefix} +libdir=\${exec_prefix}/${LIB_DIR} +includedir=\${exec_prefix}/${INCLUDE_DIR} +Name: ${PKG_NAME} +Description: ${DESCRIPTION} +Version: ${PROJECT_VERSION} +Cflags: -I\${includedir} ${PARSE_CFLAGS} +${LIBS} +Requires: ${PARSE_REQUIRES} +" + ) + +endfunction() + +function(cm_preprocess_pkgconfig_property VAR TARGET PROP) + get_target_property(OUT_PROP ${TARGET} ${PROP}) + string(REPLACE "$/${CMAKE_INSTALL_INCLUDEDIR}" "\${includedir}" OUT_PROP "${OUT_PROP}") + string(REPLACE "$/${CMAKE_INSTALL_LIBDIR}" "\${libdir}" OUT_PROP "${OUT_PROP}") + string(REPLACE "$" "\${prefix}" OUT_PROP "${OUT_PROP}") + + set(${VAR} ${OUT_PROP} PARENT_SCOPE) + +endfunction() + +function(cm_auto_pkgconfig_each) + set(options) + set(oneValueArgs NAME TARGET) + set(multiValueArgs) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + set(LIBS) + set(CFLAGS) + set(REQUIRES) + set(DESCRIPTION "No description") + + string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER) + set(PACKAGE_NAME ${PROJECT_NAME}) + + set(TARGET) + if(PARSE_TARGET) + set(TARGET ${PARSE_TARGET}) + else() + message(SEND_ERROR "Target is required for auto pkg config") + endif() + + if(PARSE_NAME) + set(PACKAGE_NAME ${PARSE_NAME}) + endif() + + string(TOUPPER ${PACKAGE_NAME} PACKAGE_NAME_UPPER) + string(TOLOWER ${PACKAGE_NAME} PACKAGE_NAME_LOWER) + + get_property(TARGET_NAME TARGET ${TARGET} PROPERTY NAME) + get_property(TARGET_TYPE TARGET ${TARGET} PROPERTY TYPE) + get_property(TARGET_DESCRIPTION TARGET ${TARGET} PROPERTY INTERFACE_DESCRIPTION) + get_property(TARGET_URL TARGET ${TARGET} PROPERTY INTERFACE_URL) + get_property(TARGET_REQUIRES TARGET ${TARGET} PROPERTY INTERFACE_PKG_CONFIG_REQUIRES) + if(NOT TARGET_TYPE STREQUAL "INTERFACE_LIBRARY") + set(LIBS "${LIBS} -l${TARGET_NAME}") + endif() + + if(TARGET_REQUIRES) + list(APPEND REQUIRES ${TARGET_REQUIRES}) + endif() + + cm_preprocess_pkgconfig_property(LINK_LIBS ${TARGET} INTERFACE_LINK_LIBRARIES) + foreach(LIB ${LINK_LIBS}) + if(TARGET ${LIB}) + get_property(LIB_PKGCONFIG_NAME TARGET ${LIB} PROPERTY INTERFACE_PKG_CONFIG_NAME) + # TODO: Error if this property is missing + if(LIB_PKGCONFIG_NAME) + list(APPEND REQUIRES ${LIB_PKGCONFIG_NAME}) + endif() + else() + if("${LIB}" MATCHES "::") + set(LIB_TARGET_NAME "$") + else() + set(LIB_TARGET_NAME "${LIB}") + endif() + cm_shadow_exists(HAS_LIB_TARGET ${LIB}) + list(APPEND REQUIRES "$<${HAS_LIB_TARGET}:$>") + set(LIBS "${LIBS} $<$:${LIB}>") + endif() + endforeach() + + cm_preprocess_pkgconfig_property(INCLUDE_DIRS ${TARGET} INTERFACE_INCLUDE_DIRECTORIES) + if(INCLUDE_DIRS) + set(CFLAGS "${CFLAGS} $<$:-I$>") + endif() + + cm_preprocess_pkgconfig_property(COMPILE_DEFS ${TARGET} INTERFACE_COMPILE_DEFINITIONS) + if(COMPILE_DEFS) + set(CFLAGS "${CFLAGS} $<$:-D$>") + endif() + + cm_preprocess_pkgconfig_property(COMPILE_OPTS ${TARGET} INTERFACE_COMPILE_OPTIONS) + if(COMPILE_OPTS) + set(CFLAGS "${CFLAGS} $<$:$>") + endif() + + set(CONTENT) + + if(TARGET_DESCRIPTION) + set(DESCRIPTION "${TARGET_DESCRIPTION}") + endif() + + if(TARGET_URL) + set(CONTENT "${CONTENT}\nUrl: ${TARGET_URL}") + endif() + + if(CFLAGS) + set(CONTENT "${CONTENT}\nCflags: ${CFLAGS}") + endif() + + if(LIBS) + set(CONTENT "${CONTENT}\n$<$:Libs: -L\${libdir} ${LIBS}>") + endif() + + if(REQUIRES) + string(REPLACE ";" "," REQUIRES_CONTENT "${REQUIRES}") + set(CONTENT "${CONTENT}\nRequires: ${REQUIRES_CONTENT}") + endif() + + file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME_LOWER}.pc CONTENT +" +prefix=${CMAKE_INSTALL_PREFIX} +exec_prefix=\${prefix} +libdir=\${exec_prefix}/${CMAKE_INSTALL_LIBDIR} +includedir=\${exec_prefix}/${CMAKE_INSTALL_INCLUDEDIR} +Name: ${PACKAGE_NAME_LOWER} +Description: ${DESCRIPTION} +Version: ${PROJECT_VERSION} +${CONTENT} +" + ) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME_LOWER}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + set_property(TARGET ${TARGET} PROPERTY INTERFACE_PKG_CONFIG_NAME ${PACKAGE_NAME_LOWER}) +endfunction() + +function(cm_auto_pkgconfig) + set(options) + set(oneValueArgs NAME) + set(multiValueArgs TARGET) # TODO: Rename to TARGETS + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + list(LENGTH PARSE_TARGET TARGET_COUNT) + + if(TARGET_COUNT EQUAL 1) + cm_auto_pkgconfig_each(TARGET ${PARSE_TARGET} NAME ${PARSE_NAME}) + else() + string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER) + set(PACKAGE_NAME ${PROJECT_NAME}) + + if(PARSE_NAME) + set(PACKAGE_NAME ${PARSE_NAME}) + endif() + + string(TOLOWER ${PACKAGE_NAME} PACKAGE_NAME_LOWER) + + set(GENERATE_PROJECT_PC On) + foreach(TARGET ${PARSE_TARGET}) + if("${TARGET}" STREQUAL "${PACKAGE_NAME_LOWER}") + set(GENERATE_PROJECT_PC Off) + endif() + cm_auto_pkgconfig_each(TARGET ${TARGET} NAME ${TARGET}) + endforeach() + + string(REPLACE ";" "," REQUIRES "${PARSE_TARGET}") + # TODO: Get description from project + set(DESCRIPTION "No description") + + if(GENERATE_PROJECT_PC) + file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME_LOWER}.pc CONTENT +" +Name: ${PACKAGE_NAME_LOWER} +Description: ${DESCRIPTION} +Version: ${PROJECT_VERSION} +Requires: ${REQUIRES} +" + ) + endif() + endif() + + +endfunction() diff --git a/cmake/modules/share/modules/cmake/CMProperties.cmake b/cmake/modules/share/modules/cmake/CMProperties.cmake new file mode 100644 index 000000000..56b156a03 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMProperties.cmake @@ -0,0 +1,105 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2017 Niall Douglas +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# +# +# On MSVC very annoyingly cmake puts /EHsc and /MD(d) into the global flags which means you +# get a warning when you try to disable exceptions or use the static CRT. I hate to use this +# globally imposed solution, but we are going to hack the global flags to use properties to +# determine whether they are on or off +# +# Create custom properties called CXX_EXCEPTIONS, CXX_RTTI and CXX_STATIC_RUNTIME +# These get placed at global, directory and target scopes +foreach(scope GLOBAL DIRECTORY TARGET) + define_property(${scope} PROPERTY "CXX_EXCEPTIONS" INHERITED + BRIEF_DOCS "Enable C++ exceptions, defaults to TRUE at global scope" + FULL_DOCS "Enable C++ exceptions, defaults to TRUE at global scope" + ) + define_property(${scope} PROPERTY "CXX_RTTI" INHERITED + BRIEF_DOCS "Enable C++ runtime type information, defaults to TRUE at global scope" + FULL_DOCS "Enable C++ runtime type information, defaults to TRUE at global scope" + ) + define_property(${scope} PROPERTY "CXX_STATIC_RUNTIME" INHERITED + BRIEF_DOCS "Enable linking against the static C++ runtime, defaults to FALSE at global scope" + FULL_DOCS "Enable linking against the static C++ runtime, defaults to FALSE at global scope" + ) + define_property(${scope} PROPERTY "CXX_WARNINGS" INHERITED + BRIEF_DOCS "Controls the warning level of compilers, defaults to TRUE at global scope" + FULL_DOCS "Controls the warning level of compilers, defaults to TRUE at global scope" + ) + define_property(${scope} PROPERTY "CXX_WARNINGS_AS_ERRORS" INHERITED + BRIEF_DOCS "Treat warnings as errors and abort compilation on a warning, defaults to FALSE at global scope" + FULL_DOCS "Treat warnings as errors and abort compilation on a warning, defaults to FALSE at global scope" + ) + define_property(${scope} PROPERTY "BUILD_SHARED_LIBS" INHERITED + BRIEF_DOCS "Property indicates wether dynamic-linked libraries are going to be built, defaults to + FALSE at global scope" + FULL_DOCS "Property indicates wether dynamic-linked libraries are going to be built, defaults to + FALSE at global scope" + ) +endforeach() +# Set the default for these properties at global scope. If they are not set per target or +# whatever, the next highest scope will be looked up +option(CMAKE_CXX_EXCEPTIONS "Enable C++ exceptions, defaults to TRUE at global scope" TRUE) +option(CMAKE_CXX_RTTI "Enable C++ runtime type information, defaults to TRUE at global scope" TRUE) +option(CMAKE_CXX_STATIC_RUNTIME "Enable linking against the static C++ runtime, defaults to FALSE at global scope" FALSE) +option(CMAKE_CXX_WARNINGS "Controls the warning level of compilers, defaults to TRUE at global scope" TRUE) +option(CMAKE_CXX_WARNINGS_AS_ERRORS "Treat warnings as errors and abort compilation on a warning, defaults to FALSE at global scope" FALSE) + +set_property(GLOBAL PROPERTY CXX_EXCEPTIONS ${CMAKE_CXX_EXCEPTIONS}) +set_property(GLOBAL PROPERTY CXX_RTTI ${CMAKE_CXX_RTTI}) +set_property(GLOBAL PROPERTY CXX_STATIC_RUNTIME ${CMAKE_CXX_STATIC_RUNTIME}) +set_property(GLOBAL PROPERTY CXX_WARNINGS ${CMAKE_CXX_WARNINGS}) +set_property(GLOBAL PROPERTY CXX_WARNINGS_AS_ERRORS ${CMAKE_CXX_WARNINGS_AS_ERRORS}) +set_property(GLOBAL PROPERTY BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) + +if(MSVC) + # Purge unconditional use of /MDd, /MD and /EHsc. + foreach(flag + CMAKE_C_FLAGS CMAKE_CXX_FLAGS + CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG + CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL + CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO + ) + string(REPLACE "/MDd" "" ${flag} "${${flag}}") + string(REPLACE "/MD" "" ${flag} "${${flag}}") + string(REPLACE "/EHsc" "" ${flag} "${${flag}}") + string(REPLACE "/GR" "" ${flag} "${${flag}}") + endforeach() + # Restore those same, but now selected by the properties + add_compile_options( + $<$>,TRUE>:/EHsc> + $<$>,FALSE>:/GR-> + $<$>,FALSE>:$<$:/MDd>$<$>:/MD>> + $<$>,TRUE>:$<$:/MTd>$<$>:/MT>> + $<$>,TRUE>:/W3> + $<$>,FALSE>:/W0> + $<$>,ALL>:/W4> + $<$>,TRUE>:/WX> + ) +else() + add_compile_options( + $<$>,FALSE>:-fno-exceptions> + $<$>,FALSE>:-fno-rtti> + $<$>,TRUE>:-static> + $<$>,TRUE>:-Wall> + $<$>,FALSE>:-w> + $<$>,ALL>:-Wall> + $<$>,ALL>:-pedantic> + $<$>,TRUE>:-Werror> + ) + if(CMAKE_${COMPILER}_COMPILER_ID MATCHES "Clang" OR CMAKE_${COMPILER}_COMPILER_ID MATCHES "AppleClang") + add_compile_options( + $<$>,ALL>:-Weverything> + $<$>,ALL>:-Wno-macro-redefined> + $<$>,ALL>:-Wall> + $<$>,ALL>:-Wno-c++98-compat> + $<$>,ALL>:-Wno-c++98-compat-pedantic> + ) + endif() +endif() \ No newline at end of file diff --git a/cmake/modules/share/modules/cmake/CMSetupVersion.cmake b/cmake/modules/share/modules/cmake/CMSetupVersion.cmake new file mode 100644 index 000000000..3e68716e4 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMSetupVersion.cmake @@ -0,0 +1,60 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +include(GNUInstallDirs) +set(CM_HEADER_VERSION_TEMPLATE_FILE "${CMAKE_CURRENT_LIST_DIR}/version.hpp") + +macro(cm_set_parent VAR) + set(${VAR} ${ARGN} PARENT_SCOPE) + set(${VAR} ${ARGN}) +endmacro() + +function(cm_setup_version) + set(options) + set(oneValueArgs VERSION GENERATE_HEADER PARSE_HEADER PREFIX) + set(multiValueArgs) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + string(TOUPPER ${PROJECT_NAME} PREFIX) + + if(PARSE_PREFIX) + set(PREFIX ${PARSE_PREFIX}) + endif() + + if(PARSE_VERSION) + cm_set_parent(PROJECT_VERSION ${PARSE_VERSION}) + cm_set_parent(${PROJECT_NAME}_VERSION ${PROJECT_VERSION}) + string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" _version_MAJOR "${PROJECT_VERSION}") + string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" _version_MINOR "${PROJECT_VERSION}") + string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" _version_PATCH "${PROJECT_VERSION}") + foreach(level MAJOR MINOR PATCH) + cm_set_parent(${PROJECT_NAME}_VERSION_${level} ${_version_${level}}) + cm_set_parent(PROJECT_VERSION_${level} ${_version_${level}}) + endforeach() + elseif(PARSE_PARSE_HEADER) + foreach(level MAJOR MINOR PATCH) + file(STRINGS ${PARSE_PARSE_HEADER} + _define_${level} + REGEX "#define ${PREFIX}_VERSION_${level}") + string(REGEX MATCH "([0-9]+)" _version_${level} "${_define_${level}}") + # TODO: Check if it is empty + cm_set_parent(${PROJECT_NAME}_VERSION_${level} ${_version_${level}}) + cm_set_parent(PROJECT_VERSION_${level} ${_version_${level}}) + endforeach() + cm_set_parent(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") + cm_set_parent(${PROJECT_NAME}_VERSION ${PROJECT_VERSION}) + endif() + # TODO: Get version from the project + + if(PARSE_GENERATE_HEADER) + configure_file("${CM_HEADER_VERSION_TEMPLATE_FILE}" "${PARSE_GENERATE_HEADER}") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PARSE_GENERATE_HEADER}" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + endif() + +endfunction() diff --git a/cmake/modules/share/modules/cmake/CMTest.cmake b/cmake/modules/share/modules/cmake/CMTest.cmake new file mode 100644 index 000000000..764df19e4 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMTest.cmake @@ -0,0 +1,240 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +option(BUILD_TESTS "Controls whether to build the tests as part of the main build" FALSE) + +enable_testing() + +foreach(scope GLOBAL DIRECTORY) + define_property(${scope} PROPERTY "ENABLE_TESTS" INHERITED + BRIEF_DOCS "Enable tests" + FULL_DOCS "Enable tests" + ) +endforeach() +option(CMAKE_ENABLE_TESTS "Enable tests" ON) +set_property(GLOBAL PROPERTY ENABLE_TESTS ${CMAKE_ENABLE_TESTS}) + +include(ProcessorCount) +processorcount(_cm_ctest_parallel_level) +set(CTEST_PARALLEL_LEVEL ${_cm_ctest_parallel_level} CACHE STRING "CTest parallel level") + +if(NOT TARGET check) + add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C ${CMAKE_CFG_INTDIR} -j ${CTEST_PARALLEL_LEVEL} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +endif() + + +if(NOT TARGET tests) + add_custom_target(tests COMMENT "Build all tests.") + add_dependencies(check tests) +endif() + +if(NOT TARGET check-${PROJECT_NAME}) + add_custom_target(check-${PROJECT_NAME} COMMAND ${CMAKE_CTEST_COMMAND} -L ${PROJECT_NAME} --output-on-failure -C ${CMAKE_CFG_INTDIR} -j ${CTEST_PARALLEL_LEVEL} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +endif() + +if(NOT TARGET tests-${PROJECT_NAME}) + add_custom_target(tests-${PROJECT_NAME} COMMENT "Build all tests for ${PROJECT_NAME}.") + add_dependencies(check-${PROJECT_NAME} tests-${PROJECT_NAME}) +endif() + +function(cm_mark_as_test) + foreach(TEST_TARGET ${ARGN}) + if(NOT BUILD_TESTS) + get_target_property(TEST_TARGET_TYPE ${TEST_TARGET} TYPE) + # We can onle use EXCLUDE_FROM_ALL on build targets + if(NOT "${TEST_TARGET_TYPE}" STREQUAL "INTERFACE_LIBRARY") + set_target_properties(${TEST_TARGET} + PROPERTIES EXCLUDE_FROM_ALL TRUE + ) + endif() + endif() + add_dependencies(tests ${TEST_TARGET}) + add_dependencies(tests-${PROJECT_NAME} ${TEST_TARGET}) + endforeach() +endfunction(cm_mark_as_test) + + +function(cm_create_internal_targets) + if(NOT TARGET _cm_internal_tests-${PROJECT_NAME}) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/_cm_internal_tests-${PROJECT_NAME}.cpp "") + add_library(_cm_internal_tests-${PROJECT_NAME} STATIC ${CMAKE_CURRENT_BINARY_DIR}/_cm_internal_tests-${PROJECT_NAME}.cpp) + cm_mark_as_test(_cm_internal_tests-${PROJECT_NAME}) + endif() +endfunction() + +foreach(scope DIRECTORY TARGET) + define_property(${scope} PROPERTY "CM_TEST_DEPENDENCIES" INHERITED + BRIEF_DOCS "Default test dependencies" + FULL_DOCS "Default test dependencies" + ) +endforeach() + +function(cm_test_link_libraries) + cm_create_internal_targets() + if(BUILD_TESTS) + set_property(DIRECTORY APPEND PROPERTY CM_TEST_DEPENDENCIES ${ARGN}) + target_link_libraries(_cm_internal_tests-${PROJECT_NAME} ${ARGN}) + else() + foreach(TARGET ${ARGN}) + if(TARGET ${TARGET}) + set_property(DIRECTORY APPEND PROPERTY CM_TEST_DEPENDENCIES ${TARGET}) + target_link_libraries(_cm_internal_tests-${PROJECT_NAME} ${TARGET}) + elseif(${TARGET} MATCHES "::") + cm_shadow_exists(HAS_TARGET ${TARGET}) + set_property(DIRECTORY APPEND PROPERTY CM_TEST_DEPENDENCIES $<${HAS_TARGET}:${TARGET}>) + target_link_libraries(_cm_internal_tests-${PROJECT_NAME} $<${HAS_TARGET}:${TARGET}>) + else() + set_property(DIRECTORY APPEND PROPERTY CM_TEST_DEPENDENCIES ${TARGET}) + target_link_libraries(_cm_internal_tests-${PROJECT_NAME} ${TARGET}) + endif() + if(BUILD_SHARED_LIBS) + target_compile_definitions(_cm_internal_tests-${PROJECT_NAME} PRIVATE -DBOOST_TEST_DYN_LINK=1 -DBOOST_TEST_NO_AUTO_LINK=1) + endif() + endforeach() + endif() +endfunction() + +function(cm_target_link_test_libs TARGET) + # target_link_libraries(${TARGET} + # $ + # ) + get_property(DEPS DIRECTORY PROPERTY CM_TEST_DEPENDENCIES) + target_link_libraries(${TARGET} ${DEPS}) +endfunction() + + +function(cm_test) + set(options COMPILE_ONLY WILL_FAIL NO_TEST_LIBS) + set(oneValueArgs NAME SOURCES_PREFIX) + set(multiValueArgs SOURCES CONTENT ARGS) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(PARSE_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to cm_test(): \"${PARSE_UNPARSED_ARGUMENTS}\"") + endif() + + set(SOURCES ${PARSE_SOURCES}) + + if(PARSE_NAME) + set(TEST_NAME ${PARSE_NAME}) + else() + string(MAKE_C_IDENTIFIER "${PROJECT_NAME}_${SOURCES}_test" TEST_NAME) + endif() + + if(PARSE_CONTENT) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generated-${TEST_NAME}.cpp "${PARSE_CONTENT}") + set(SOURCES ${CMAKE_CURRENT_BINARY_DIR}/generated-${TEST_NAME}.cpp) + endif() + + if(PARSE_COMPILE_ONLY) + add_library(${TEST_NAME} STATIC EXCLUDE_FROM_ALL ${SOURCES}) + add_test(NAME ${TEST_NAME} + COMMAND ${CMAKE_COMMAND} --build . --target ${TEST_NAME} --config $ + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + if(PARSE_SOURCES_PREFIX) + target_include_directories(${TEST_NAME} PRIVATE ${PARSE_SOURCES_PREFIX}) + else() + target_include_directories(${TEST_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}) + endif() + + # set_tests_properties(${TEST_NAME} PROPERTIES RESOURCE_LOCK cm_test_compile_only) + else() + add_executable(${TEST_NAME} ${SOURCES}) + cm_mark_as_test(${TEST_NAME}) + if(PARSE_SOURCES_PREFIX) + target_include_directories(${TEST_NAME} PRIVATE ${PARSE_SOURCES_PREFIX}) + else() + target_include_directories(${TEST_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}) + endif() + if(WIN32) + foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES} "") + file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}-test-run-${CONFIG}.cmake CONTENT " +include(\"${CMAKE_BINARY_DIR}/cm_set_rpath-$.cmake\") +if(CMAKE_CROSSCOMPILING) +foreach(RP \${RPATH}) + execute_process(COMMAND winepath -w \${RP} OUTPUT_VARIABLE _RPATH) + string(STRIP \"\${_RPATH}\" _RPATH) + set(ENV{WINEPATH} \"\${_RPATH};\$ENV{WINEPATH}\") +endforeach() +else() +set(ENV{PATH} \"\${RPATH};\$ENV{PATH}\") +endif() +execute_process( + COMMAND $ ${PARSE_ARGS} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + RESULT_VARIABLE RESULT) +if(NOT RESULT EQUAL 0) + message(FATAL_ERROR \"Test failed\") +endif() +" CONDITION $) + endforeach() + add_test(NAME ${TEST_NAME} COMMAND ${CMAKE_COMMAND} -DCMAKE_CROSSCOMPILING=${CMAKE_CROSSCOMPILING} -P ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}-test-run-$.cmake) + else() + add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} ${PARSE_ARGS} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + endif() + endif() + + if(BUILD_SHARED_LIBS) + target_compile_definitions(${TEST_NAME} PRIVATE -DBOOST_TEST_DYN_LINK=1 -DBOOST_TEST_NO_AUTO_LINK=1) + endif() + + if(PARSE_WILL_FAIL) + set_tests_properties(${TEST_NAME} PROPERTIES WILL_FAIL TRUE) + endif() + set_tests_properties(${TEST_NAME} PROPERTIES LABELS ${PROJECT_NAME}) + if(NOT PARSE_NO_TEST_LIBS) + cm_target_link_test_libs(${TEST_NAME}) + endif() +endfunction(cm_test) + +function(cm_test_header) + set(options STATIC NO_TEST_LIBS) + set(oneValueArgs NAME HEADER) + set(multiValueArgs) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(PARSE_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to cm_test_header(): \"${PARSE_UNPARSED_ARGUMENTS}\"") + endif() + + if(PARSE_NAME) + set(TEST_NAME ${PARSE_NAME}) + else() + string(MAKE_C_IDENTIFIER "${PROJECT_NAME}_${PARSE_HEADER}_header_test" TEST_NAME) + endif() + + if(PARSE_STATIC) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/header-main-include-${TEST_NAME}.cpp + "#include <${PARSE_HEADER}>\nint main() {}\n" + ) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/header-static-include-${TEST_NAME}.cpp + "#include <${PARSE_HEADER}>\n" + ) + cm_test(NAME ${TEST_NAME} SOURCES + ${CMAKE_CURRENT_BINARY_DIR}/header-main-include-${TEST_NAME}.cpp + ${CMAKE_CURRENT_BINARY_DIR}/header-static-include-${TEST_NAME}.cpp + ) + else() + cm_test(NAME ${TEST_NAME} CONTENT + "#include <${PARSE_HEADER}>\nint main() {}\n" + ) + endif() + set_tests_properties(${TEST_NAME} PROPERTIES LABELS ${PROJECT_NAME}) +endfunction(cm_test_header) + +macro(cm_add_test_subdirectory) + get_directory_property(_enable_tests_property ENABLE_TESTS) + get_property(_enable_tests_global_property GLOBAL PROPERTY ENABLE_TESTS) + string(TOUPPER "${_enable_tests_property}" _enable_tests_property_upper) + if(_enable_tests_property_upper STREQUAL "OFF" OR _enable_tests_property_upper EQUAL 1) + set(CURRENT_SOURCES_DIR ${CURRENT_SOURCES_DIR}/test) + add_subdirectory(${ARGN}) + endif() +endmacro() diff --git a/cmake/modules/share/modules/cmake/CMToSnakeCase.cmake b/cmake/modules/share/modules/cmake/CMToSnakeCase.cmake new file mode 100644 index 000000000..4a61031e2 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMToSnakeCase.cmake @@ -0,0 +1,18 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +function(to_snake_case str var) + # insert an underscore before any upper case letter + # which is not followed by another upper case letter + string(REGEX REPLACE "(.)([A-Z][a-z]+)" "\\1_\\2" value "${str}") + # insert an underscore before any upper case letter + # which is preseded by a lower case letter or number + string(REGEX REPLACE "([a-z0-9])([A-Z])" "\\1_\\2" value "${value}") + string(TOLOWER "${value}" value) + set(${var} "${value}" PARENT_SCOPE) +endfunction() diff --git a/cmake/modules/share/modules/cmake/version.hpp b/cmake/modules/share/modules/cmake/version.hpp new file mode 100644 index 000000000..116b801ed --- /dev/null +++ b/cmake/modules/share/modules/cmake/version.hpp @@ -0,0 +1,18 @@ +//---------------------------------------------------------------------------// +// +// Copyright (c) 2018-2020 Mikhail Komarov +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef @PREFIX@_GUARD_VERSION_HPP +#define @PREFIX@_GUARD_VERSION_HPP + +#define @PREFIX@_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ +#define @PREFIX@_VERSION_MINOR @PROJECT_VERSION_MINOR@ +#define @PREFIX@_VERSION_PATCH @PROJECT_VERSION_PATCH@ +#define @PREFIX@_VERSION (((@PREFIX@_VERSION_MAJOR) << 24) + ((@PREFIX@_VERSION_MINOR) << 16) + (@PREFIX@_VERSION_PATCH)) + +#endif diff --git a/cmake/packages/FindEigen3.cmake b/cmake/packages/FindEigen3.cmake new file mode 100644 index 000000000..129b62afd --- /dev/null +++ b/cmake/packages/FindEigen3.cmake @@ -0,0 +1,90 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +# Try to find Eigen3 library +# http://eigen.tuxfamily.org +# +# This module supports requiring a minimum version, e.g. you can do +# find_package(Eigen3 3.1.2) +# to require version 3.1.2 or newer of Eigen3. +# +# Once done this will define +# +# EIGEN3_FOUND - system has eigen lib with correct version +# EIGEN3_INCLUDE_DIR - the eigen include directory +# EIGEN3_VERSION - eigen version + +if(NOT Eigen3_FIND_VERSION) + if(NOT Eigen3_FIND_VERSION_MAJOR) + set(Eigen3_FIND_VERSION_MAJOR 2) + endif(NOT Eigen3_FIND_VERSION_MAJOR) + if(NOT Eigen3_FIND_VERSION_MINOR) + set(Eigen3_FIND_VERSION_MINOR 91) + endif(NOT Eigen3_FIND_VERSION_MINOR) + if(NOT Eigen3_FIND_VERSION_PATCH) + set(Eigen3_FIND_VERSION_PATCH 0) + endif(NOT Eigen3_FIND_VERSION_PATCH) + + set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}") +endif(NOT Eigen3_FIND_VERSION) + +macro(_eigen3_check_version) + file(READ "${EIGEN3_INCLUDE_DIRS}/Eigen/src/Core/util/Macros.h" _eigen3_version_header) + + string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}") + set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}") + set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}") + set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}") + + set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION}) + if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) + set(EIGEN3_VERSION_OK FALSE) + else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) + set(EIGEN3_VERSION_OK TRUE) + endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) + + if(NOT EIGEN3_VERSION_OK) + + message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIRS}, " + "but at least version ${Eigen3_FIND_VERSION} is required") + endif(NOT EIGEN3_VERSION_OK) +endmacro(_eigen3_check_version) + +if(EIGEN3_INCLUDE_DIRS) + + # in cache already + _eigen3_check_version() + set(EIGEN3_FOUND ${EIGEN3_VERSION_OK}) + +else(EIGEN3_INCLUDE_DIRS) + + # specific additional paths for some OS + if(WIN32) + set(EIGEN_ADDITIONAL_SEARCH_PATHS ${EIGEN_ADDITIONAL_SEARCH_PATHS} "C:/Program Files/Eigen/include" "C:/Program Files (x86)/Eigen/include") + endif(WIN32) + + find_path(EIGEN3_INCLUDE_DIRS NAMES signature_of_eigen3_matrix_library + PATHS + include + ${EIGEN_ADDITIONAL_SEARCH_PATHS} + ${KDE4_INCLUDE_DIR} + PATH_SUFFIXES eigen3 eigen + ) + + if(EIGEN3_INCLUDE_DIRS) + _eigen3_check_version() + endif(EIGEN3_INCLUDE_DIRS) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIRS EIGEN3_VERSION_OK) + + mark_as_advanced(EIGEN3_INCLUDE_DIRS) + +endif(EIGEN3_INCLUDE_DIRS) \ No newline at end of file diff --git a/cmake/packages/FindGMP.cmake b/cmake/packages/FindGMP.cmake new file mode 100644 index 000000000..f1c739b80 --- /dev/null +++ b/cmake/packages/FindGMP.cmake @@ -0,0 +1,85 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# Copyright (c) 2018-2020 Alexey Moskvin +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# +# +# Try to find the GMP library +# https://gmplib.org/ +# +# This module supports requiring a minimum version, e.g. you can do +# find_package(GMP 6.0.0) +# to require version 6.0.0 to newer of GMP. +# +# Once done this will define +# +# GMP_FOUND - system has GMP lib with correct version +# GMP_INCLUDE_DIRS - the GMP include directory +# GMP_LIBRARIES - the GMP library +# GMP_VERSION - GMP version + +find_path(GMP_INCLUDE_DIRS NAMES gmp.h PATHS $ENV{GMPDIR} ${INCLUDE_INSTALL_DIR}) + +# Set GMP_FIND_VERSION to 5.1.0 if no minimum version is specified +if(NOT GMP_FIND_VERSION) + if(NOT GMP_FIND_VERSION_MAJOR) + set(GMP_FIND_VERSION_MAJOR 5) + endif() + if(NOT GMP_FIND_VERSION_MINOR) + set(GMP_FIND_VERSION_MINOR 1) + endif() + if(NOT GMP_FIND_VERSION_PATCH) + set(GMP_FIND_VERSION_PATCH 0) + endif() + set(GMP_FIND_VERSION + "${GMP_FIND_VERSION_MAJOR}.${GMP_FIND_VERSION_MINOR}.${GMP_FIND_VERSION_PATCH}") +endif() + +if(GMP_INCLUDE_DIRS) + # Since the GMP version macros may be in a file included by gmp.h of the form + # gmp-.*[_]?.*.h (e.g., gmp-x86_64.h), we search each of them. + file(GLOB GMP_HEADERS "${GMP_INCLUDE_DIRS}/gmp.h" "${GMP_INCLUDE_DIRS}/gmp-*.h") + foreach(gmp_header_filename ${GMP_HEADERS}) + file(READ "${gmp_header_filename}" _gmp_version_header) + string(REGEX MATCH + "define[ \t]+__GNU_MP_VERSION[ \t]+([0-9]+)" _gmp_major_version_match + "${_gmp_version_header}") + if(_gmp_major_version_match) + set(GMP_MAJOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_MINOR[ \t]+([0-9]+)" + _gmp_minor_version_match "${_gmp_version_header}") + set(GMP_MINOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_PATCHLEVEL[ \t]+([0-9]+)" + _gmp_patchlevel_version_match "${_gmp_version_header}") + set(GMP_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") + set(GMP_VERSION + ${GMP_MAJOR_VERSION}.${GMP_MINOR_VERSION}.${GMP_PATCHLEVEL_VERSION}) + endif() + endforeach() + + # Check whether found version exists and exceeds the minimum requirement + if(NOT GMP_VERSION) + set(GMP_VERSION_OK FALSE) + message(STATUS "GMP version was not detected") + elseif(${GMP_VERSION} VERSION_LESS ${GMP_FIND_VERSION}) + set(GMP_VERSION_OK FALSE) + message(STATUS "GMP version ${GMP_VERSION} found in ${GMP_INCLUDE_DIRS}, " + "but at least version ${GMP_FIND_VERSION} is required") + else() + set(GMP_VERSION_OK TRUE) + endif() +endif() + +find_library(GMP_LIBRARIES gmp PATHS $ENV{GMPDIR} ${LIB_INSTALL_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GMP DEFAULT_MSG + GMP_INCLUDE_DIRS GMP_LIBRARIES GMP_VERSION_OK) +if(GMP_FOUND) + set(HAVE_GMP "${GMP_FOUND}") +endif() + +mark_as_advanced(GMP_INCLUDE_DIRS GMP_LIBRARIES) \ No newline at end of file diff --git a/cmake/packages/FindGMPXX.cmake b/cmake/packages/FindGMPXX.cmake new file mode 100644 index 000000000..91d0975d7 --- /dev/null +++ b/cmake/packages/FindGMPXX.cmake @@ -0,0 +1,39 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# Copyright (c) 2018-2020 Alexey Moskvin +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# +# +# Try to find the GMPXX libraries +# +# Once done this will define +# GMPXX_FOUND - system has GMPXX lib +# GMPXX_INCLUDE_DIRS - the GMPXX include directory +# GMPXX_LIBRARIES - Libraries needed to use GMPXX + +if(GMP_FOUND) + find_package(GMP QUIET) +else() + find_package(GMP) +endif() + +if(GMP_FOUND) + if(GMPXX_INCLUDE_DIRS AND GMPXX_LIBRARIES) + # Already in cache, be silent + set(GMPXX_FIND_QUIETLY TRUE) + endif() + + find_path(GMPXX_INCLUDE_DIRS NAMES gmpxx.h + PATHS ${GMP_INCLUDE_DIRS_SEARCH} + DOC "The directory containing the GMPXX include files") + + find_library(GMPXX_LIBRARIES NAMES gmpxx + PATHS ${GMP_LIBRARIES_DIR_SEARCH} + DOC "Path to the GMPXX library") + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(GMPXX "DEFAULT_MSG" GMPXX_LIBRARIES GMPXX_INCLUDE_DIRS) +endif() diff --git a/cmake/packages/FindMPC.cmake b/cmake/packages/FindMPC.cmake new file mode 100644 index 000000000..39140814d --- /dev/null +++ b/cmake/packages/FindMPC.cmake @@ -0,0 +1,75 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# Copyright (c) 2018-2020 Alexey Moskvin +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# +# +# Try to find the MPC library +# See http://www.multiprecision.org/index.php?prog=mpc&page=home +# +# This module supports requiring a minimum version, e.g. you can do +# find_package(MPC 1.0.3) +# to require version 1.0.3 to newer of MPC. +# +# Once done this will define +# +# MPC_FOUND - system has MPC lib with correct version +# MPC_INCLUDE_DIRS - the MPC include directory +# MPC_LIBRARIES - the MPC library +# MPC_VERSION - MPC version + +find_path(MPC_INCLUDE_DIRS NAMES mpc.h PATHS $ENV{GMPDIR} $ENV{MPFRDIR} $ENV{MPCDIR} + ${INCLUDE_INSTALL_DIR}) + +# Set MPC_FIND_VERSION to 1.0.0 if no minimum version is specified +if(NOT MPC_FIND_VERSION) + if(NOT MPC_FIND_VERSION_MAJOR) + set(MPC_FIND_VERSION_MAJOR 1) + endif() + if(NOT MPC_FIND_VERSION_MINOR) + set(MPC_FIND_VERSION_MINOR 0) + endif() + if(NOT MPC_FIND_VERSION_PATCH) + set(MPC_FIND_VERSION_PATCH 0) + endif() + set(MPC_FIND_VERSION + "${MPC_FIND_VERSION_MAJOR}.${MPC_FIND_VERSION_MINOR}.${MPC_FIND_VERSION_PATCH}") +endif() + +if(MPC_INCLUDE_DIRS) + # Query MPC_VERSION + file(READ "${MPC_INCLUDE_DIRS}/mpc.h" _mpc_version_header) + + string(REGEX MATCH "define[ \t]+MPC_VERSION_MAJOR[ \t]+([0-9]+)" + _mpc_major_version_match "${_mpc_version_header}") + set(MPC_MAJOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+MPC_VERSION_MINOR[ \t]+([0-9]+)" + _mpc_minor_version_match "${_mpc_version_header}") + set(MPC_MINOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+MPC_VERSION_PATCHLEVEL[ \t]+([0-9]+)" + _mpc_patchlevel_version_match "${_mpc_version_header}") + set(MPC_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") + + set(MPC_VERSION + ${MPC_MAJOR_VERSION}.${MPC_MINOR_VERSION}.${MPC_PATCHLEVEL_VERSION}) + + # Check whether found version exceeds minimum required + if(${MPC_VERSION} VERSION_LESS ${MPC_FIND_VERSION}) + set(MPC_VERSION_OK FALSE) + message(STATUS "MPC version ${MPC_VERSION} found in ${MPC_INCLUDE_DIRS}, " + "but at least version ${MPC_FIND_VERSION} is required") + else() + set(MPC_VERSION_OK TRUE) + endif() +endif(MPC_INCLUDE_DIRS) + +find_library(MPC_LIBRARIES mpc + PATHS $ENV{GMPDIR} $ENV{MPFRDIR} $ENV{MPCDIR} ${LIB_INSTALL_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MPC DEFAULT_MSG + MPC_INCLUDE_DIRS MPC_LIBRARIES MPC_VERSION_OK) +mark_as_advanced(MPC_INCLUDE_DIRS MPC_LIBRARIES) diff --git a/cmake/packages/FindMPFI.cmake b/cmake/packages/FindMPFI.cmake new file mode 100644 index 000000000..87e3f9a32 --- /dev/null +++ b/cmake/packages/FindMPFI.cmake @@ -0,0 +1,102 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# Copyright (c) 2018-2020 Alexey Moskvin +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +if(GMP_FOUND) + find_package(GMP QUIET) +else() + find_package(GMP) +endif() + +if(MPFR_FOUND) + find_package(MPFR QUIET) +else() + find_package(MPFR) +endif() + +if(GMP_FOUND AND MPFR_FOUND) + if(MPFI_INCLUDE_DIRS AND MPFI_LIBRARIES) + set(MPFI_FOUND TRUE) + endif(MPFI_INCLUDE_DIRS AND MPFI_LIBRARIES) + + find_path(MPFI_INCLUDE_DIRS NAMES mpfi.h + HINTS ENV MPFI_INC_DIR + ENV MPFI_DIR + PATHS ${GMP_INCLUDE_DIR_SEARCH} + PATH_SUFFIXES include + DOC "The directory containing the MPFI header files" + ) + if(MPFI_INCLUDE_DIRS) + file(READ "${MPFI_INCLUDE_DIRS}/mpfi.h" _mpfr_version_header) + + string(REGEX MATCH "define[ \t]+MPFI_VERSION_MAJOR[ \t]+([0-9]+)" + _mpfr_major_version_match "${_mpfr_version_header}") + set(MPFI_MAJOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+MPFI_VERSION_MINOR[ \t]+([0-9]+)" + _mpfr_minor_version_match "${_mpfr_version_header}") + set(MPFI_MINOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+MPFI_VERSION_PATCHLEVEL[ \t]+([0-9]+)" + _mpfr_patchlevel_version_match "${_mpfr_version_header}") + set(MPFI_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") + + set(MPFI_VERSION + ${MPFI_MAJOR_VERSION}.${MPFI_MINOR_VERSION}.${MPFI_PATCHLEVEL_VERSION}) + endif() + + + find_library(MPFI_LIBRARIES NAMES mpfi + HINTS ENV MPFI_LIB_DIR + ENV MPFI_DIR + PATHS ${GMP_LIBRARIES_DIR_SEARCH} + PATH_SUFFIXES lib + DOC "Directory containing the MPFI library" + ) + + if(MPFI_LIBRARIES) + get_filename_component(MPFI_LIBRARIES_DIR ${MPFI_LIBRARIES} PATH CACHE) + endif(MPFI_LIBRARIES) + + if(NOT MPFI_INCLUDE_DIRS OR NOT MPFI_LIBRARIES_DIR) + include(MPFIConfig OPTIONAL) + endif(NOT MPFI_INCLUDE_DIRS OR NOT MPFI_LIBRARIES_DIR) + + include(FindPackageHandleStandardArgs) + + find_package_handle_standard_args(MPFI + "DEFAULT_MSG" + MPFI_LIBRARIES + MPFI_INCLUDE_DIRS) + +else(GMP_FOUND AND MPFR_FOUND) + + message(STATUS "MPFI needs GMP and MPFR") + +endif(GMP_FOUND AND MPFR_FOUND) + +if(MPFI_FOUND) + if("${MPFR_VERSION}" VERSION_LESS "4.0.0") + set(_MPFR_OLD TRUE) + endif() + + if("${MPFI_VERSION}" VERSION_LESS "1.5.2") + set(_MPFI_OLD TRUE) + endif() + + if((_MPFR_OLD AND NOT _MPFI_OLD) OR (NOT _MPFR_OLD AND _MPFI_OLD)) + + message(STATUS "MPFI<1.5.2 requires MPFR<4.0.0; MPFI>=1.5.2 requires MPFR>=4.0.0") + + set(MPFI_FOUND FALSE) + + else((_MPFR_OLD AND NOT _MPFI_OLD) OR (NOT _MPFR_OLD AND _MPFI_OLD)) + + set(MPFI_USE_FILE "CGAL_UseMPFI") + + endif((_MPFR_OLD AND NOT _MPFI_OLD) OR (NOT _MPFR_OLD AND _MPFI_OLD)) + +endif(MPFI_FOUND) \ No newline at end of file diff --git a/cmake/packages/FindMPFR.cmake b/cmake/packages/FindMPFR.cmake new file mode 100644 index 000000000..475c4f36c --- /dev/null +++ b/cmake/packages/FindMPFR.cmake @@ -0,0 +1,75 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# Copyright (c) 2018-2020 Alexey Moskvin +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# +# +# Try to find the MPFR library +# See http://www.mpfr.org/ +# +# This module supports requiring a minimum version, e.g. you can do +# find_package(MPFR 2.3.0) +# to require version 2.3.0 to newer of MPFR. +# +# Once done this will define +# +# MPFR_FOUND - system has MPFR lib with correct version +# MPFR_INCLUDE_DIRS - the MPFR include directory +# MPFR_LIBRARIES - the MPFR library +# MPFR_VERSION - MPFR version + +find_path(MPFR_INCLUDE_DIRS NAMES mpfr.h PATHS $ENV{GMPDIR} $ENV{MPFRDIR} + ${INCLUDE_INSTALL_DIR}) + +# Set MPFR_FIND_VERSION to 1.0.0 if no minimum version is specified +if(NOT MPFR_FIND_VERSION) + if(NOT MPFR_FIND_VERSION_MAJOR) + set(MPFR_FIND_VERSION_MAJOR 1) + endif() + if(NOT MPFR_FIND_VERSION_MINOR) + set(MPFR_FIND_VERSION_MINOR 0) + endif() + if(NOT MPFR_FIND_VERSION_PATCH) + set(MPFR_FIND_VERSION_PATCH 0) + endif() + set(MPFR_FIND_VERSION + "${MPFR_FIND_VERSION_MAJOR}.${MPFR_FIND_VERSION_MINOR}.${MPFR_FIND_VERSION_PATCH}") +endif() + +if(MPFR_INCLUDE_DIRS) + # Query MPFR_VERSION + file(READ "${MPFR_INCLUDE_DIRS}/mpfr.h" _mpfr_version_header) + + string(REGEX MATCH "define[ \t]+MPFR_VERSION_MAJOR[ \t]+([0-9]+)" + _mpfr_major_version_match "${_mpfr_version_header}") + set(MPFR_MAJOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+MPFR_VERSION_MINOR[ \t]+([0-9]+)" + _mpfr_minor_version_match "${_mpfr_version_header}") + set(MPFR_MINOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+MPFR_VERSION_PATCHLEVEL[ \t]+([0-9]+)" + _mpfr_patchlevel_version_match "${_mpfr_version_header}") + set(MPFR_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") + + set(MPFR_VERSION + ${MPFR_MAJOR_VERSION}.${MPFR_MINOR_VERSION}.${MPFR_PATCHLEVEL_VERSION}) + + # Check whether found version exceeds minimum required + if(${MPFR_VERSION} VERSION_LESS ${MPFR_FIND_VERSION}) + set(MPFR_VERSION_OK FALSE) + message(STATUS "MPFR version ${MPFR_VERSION} found in ${MPFR_INCLUDE_DIRS}, " + "but at least version ${MPFR_FIND_VERSION} is required") + else() + set(MPFR_VERSION_OK TRUE) + endif() +endif() + +find_library(MPFR_LIBRARIES mpfr + PATHS $ENV{GMPDIR} $ENV{MPFRDIR} ${LIB_INSTALL_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MPFR DEFAULT_MSG + MPFR_INCLUDE_DIRS MPFR_LIBRARIES MPFR_VERSION_OK) +mark_as_advanced(MPFR_INCLUDE_DIRS MPFR_LIBRARIES) \ No newline at end of file diff --git a/cmake/packages/FindMPIR.cmake b/cmake/packages/FindMPIR.cmake new file mode 100644 index 000000000..cc81a53ae --- /dev/null +++ b/cmake/packages/FindMPIR.cmake @@ -0,0 +1,84 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# +# +# Try to find the MPIR library +# https://mpir.org/ +# +# This module supports requiring a minimum version, e.g. you can do +# find_package(MPIR 6.0.0) +# to require version 6.0.0 to newer of MPIR. +# +# Once done this will define +# +# MPIR_FOUND - system has MPIR lib with correct version +# MPIR_INCLUDE_DIRS - the MPIR include directory +# MPIR_LIBRARIES - the MPIR library +# MPIR_VERSION - MPIR version + +find_path(MPIR_INCLUDE_DIRS NAMES gmp.h PATHS $ENV{MPIRDIR} ${INCLUDE_INSTALL_DIR}) + +# Set MPIR_FIND_VERSION to 5.1.0 if no minimum version is specified +if(NOT MPIR_FIND_VERSION) + if(NOT MPIR_FIND_VERSION_MAJOR) + set(MPIR_FIND_VERSION_MAJOR 5) + endif() + if(NOT MPIR_FIND_VERSION_MINOR) + set(MPIR_FIND_VERSION_MINOR 1) + endif() + if(NOT MPIR_FIND_VERSION_PATCH) + set(MPIR_FIND_VERSION_PATCH 0) + endif() + set(MPIR_FIND_VERSION + "${MPIR_FIND_VERSION_MAJOR}.${MPIR_FIND_VERSION_MINOR}.${MPIR_FIND_VERSION_PATCH}") +endif() + +if(MPIR_INCLUDE_DIRS) + # Since the MPIR version macros may be in a file included by gmp.h of the form + # gmp-.*[_]?.*.h (e.g., gmp-x86_64.h), we search each of them. + file(GLOB MPIR_HEADERS "${MPIR_INCLUDE_DIRS}/gmp.h" "${MPIR_INCLUDE_DIRS}/gmp-*.h") + foreach(gmp_header_filename ${MPIR_HEADERS}) + file(READ "${gmp_header_filename}" _gmp_version_header) + string(REGEX MATCH + "define[ \t]+__GNU_MP_VERSION[ \t]+([0-9]+)" _gmp_major_version_match + "${_gmp_version_header}") + if(_gmp_major_version_match) + set(MPIR_MAJOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_MINOR[ \t]+([0-9]+)" + _gmp_minor_version_match "${_gmp_version_header}") + set(MPIR_MINOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_PATCHLEVEL[ \t]+([0-9]+)" + _gmp_patchlevel_version_match "${_gmp_version_header}") + set(MPIR_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") + set(MPIR_VERSION + ${MPIR_MAJOR_VERSION}.${MPIR_MINOR_VERSION}.${MPIR_PATCHLEVEL_VERSION}) + endif() + endforeach() + + # Check whether found version exists and exceeds the minimum requirement + if(NOT MPIR_VERSION) + set(MPIR_VERSION_OK FALSE) + message(STATUS "MPIR version was not detected") + elseif(${MPIR_VERSION} VERSION_LESS ${MPIR_FIND_VERSION}) + set(MPIR_VERSION_OK FALSE) + message(STATUS "MPIR version ${MPIR_VERSION} found in ${MPIR_INCLUDE_DIRS}, " + "but at least version ${MPIR_FIND_VERSION} is required") + else() + set(MPIR_VERSION_OK TRUE) + endif() +endif() + +find_library(MPIR_LIBRARIES gmp PATHS $ENV{MPIRDIR} ${LIB_INSTALL_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MPIR DEFAULT_MSG + MPIR_INCLUDE_DIRS MPIR_LIBRARIES MPIR_VERSION_OK) +if(MPIR_FOUND) + set(HAVE_MPIR "${MPIR_FOUND}") +endif() + +mark_as_advanced(MPIR_INCLUDE_DIRS MPIR_LIBRARIES) \ No newline at end of file diff --git a/cmake/packages/FindMPIRXX.cmake b/cmake/packages/FindMPIRXX.cmake new file mode 100644 index 000000000..3b414694d --- /dev/null +++ b/cmake/packages/FindMPIRXX.cmake @@ -0,0 +1,36 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# Copyright (c) 2018-2020 Alexey Moskvin +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# +# +# Try to find the MPIRXX libraries +# MPIRXX_FOUND - system has MPIRXX lib +# MPIRXX_INCLUDE_DIRS - the MPIRXX include directory +# MPIRXX_LIBRARIES - Libraries needed to use MPIRXX + +# MPIRXX needs MPIR +find_package(MPIR QUIET) + +if(MPIR_FOUND) + if(MPIRXX_INCLUDE_DIRS AND MPIRXX_LIBRARIES) + # Already in cache, be silent + set(MPIRXX_FIND_QUIETLY TRUE) + endif() + + find_path(MPIRXX_INCLUDE_DIRS NAMES mpirxx.h + PATHS ${MPIR_INCLUDE_DIR_SEARCH} + DOC "The directory containing the MPIRXX include files" + ) + + find_library(MPIRXX_LIBRARIES NAMES mpirxx + PATHS ${MPIR_LIBRARIES_DIR_SEARCH} + DOC "Path to the MPIRXX library" + ) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(MPIRXX "DEFAULT_MSG" MPIRXX_LIBRARIES MPIRXX_INCLUDE_DIRS) +endif() diff --git a/cmake/packages/FindQuadmath.cmake b/cmake/packages/FindQuadmath.cmake new file mode 100644 index 000000000..80d68bb65 --- /dev/null +++ b/cmake/packages/FindQuadmath.cmake @@ -0,0 +1,59 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# +# +# Once done this will define +# QUADMATH_FOUND - system has Quadmath lib +# QUADMATH_INCLUDE_DIRS - the Quadmath include directory +# QUADMATH_LIBRARIES - Libraries needed to use Quadmath + +include(FindPackageHandleStandardArgs) +include(CMakePushCheckState) +include(CheckCXXSourceCompiles) + +if(QUADMATH_FOUND) + find_path(QUADMATH_INCLUDE_DIRS NAMES quadmath.h PATHS /usr/local/lib /usr/local/include /usr/include + /opt/loca/include) + find_library(QUADMATH_LIBRARY NAMES libquadmath.a PATHS /usr/local/lib/gcc/8/ /opt/local/lib /usr/local/lib/) +else() + find_path(QUADMATH_INCLUDE_DIRS NAMES quadmath.h PATHS /usr/local/lib /usr/local/include /usr/include + /opt/loca/include) + find_library(QUADMATH_LIBRARY NAMES libquadmath.a PATHS /usr/local/lib/gcc/8/ /opt/local/lib /usr/local/lib/) +endif() + +if(NOT QUADMATH_INCLUDE_DIRS OR NOT QUADMATH_LIBRARY) + cmake_push_check_state(RESET) + list(APPEND CMAKE_REQUIRED_LIBRARIES "quadmath") + check_cxx_source_compiles(" + #include + int main(void){ + _float128 foo = ::sqrtq(123.456); + }" + QUADMATH_USE_DIRECTLY) + cmake_pop_check_state() + if(QUADMATH_USE_DIRECTLY) + set(QUADMATH_INCLUDE_DIRS "unused" CACHE PATH "" FORCE) + set(QUADMATH_LIBRARY "quadmath" CACHE FILEPATH "" FORCE) + endif() +endif() + +find_package_handle_standard_args(Quadmath DEFAULT_MSG QUADMATH_LIBRARY QUADMATH_INCLUDE_DIRS) + +mark_as_advanced(QUADMATH_INCLUDE_DIRS QUADMATH_LIBRARY) + +if(QUADMATH_FOUND AND NOT TARGET Quadmath::quadmath) + if(QUADMATH_USE_DIRECTLY) + message(STATUS "libquadmath will be included and linked directly.") + add_library(Quadmath::quadmath INTERFACE IMPORTED) + set_target_properties(Quadmath::quadmath PROPERTIES INTERFACE_LINK_LIBRARIES "${QUADMATH_LIBRARY}") + else() + add_library(Quadmath::quadmath UNKNOWN IMPORTED) + set_target_properties(Quadmath::quadmath PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${QUADMATH_INCLUDE_DIRS}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${QUADMATH_LIBRARY}") + endif() +endif() diff --git a/cmake/packages/FindTomMath.cmake b/cmake/packages/FindTomMath.cmake new file mode 100644 index 000000000..b3010d8fc --- /dev/null +++ b/cmake/packages/FindTomMath.cmake @@ -0,0 +1,30 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# Copyright (c) 2018-2020 Alexey Moskvin +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# +# +# TomMath_FOUND - system has TomMath +# TomMath_INCLUDE_DIRS - the TomMath include directories +# TomMath_LIBRARY - link these to use TomMath + +find_path(TomMath_INCLUDE_DIRS tommath.h) + +set(TomMath_NAMES ${TomMath_NAMES} tommath libtommath) +find_library(TomMath_LIBRARY NAMES ${TomMath_NAMES}) + +# handle the QUIETLY and REQUIRED arguments and set TIFF_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(TomMath DEFAULT_MSG TomMath_LIBRARY TomMath_INCLUDE_DIRS) + +if(TOMMATH_FOUND) + set(TomMath_FOUND true) + set(TomMath_LIBRARIES ${TomMath_LIBRARY}) + set(TomMath_INCLUDE_DIRS ${TomMath_INCLUDE_DIRS}) +endif(TOMMATH_FOUND) + +mark_as_advanced(TomMath_INCLUDE_DIRS TomMath_LIBRARY TomMath_FOUND) diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk index 65c56326d..d57ca086a 100644 --- a/doc/tutorial.qbk +++ b/doc/tutorial.qbk @@ -36,6 +36,7 @@ In order to use this library you need to make two choices: [include tutorial_hash.qbk] [include tutorial_eigen.qbk] [include tutorial_new_backend.qbk] +[include tutorial_ressol.qbk] [endsect] [/section:tut Tutorial] diff --git a/doc/tutorial_ressol.qbk b/doc/tutorial_ressol.qbk new file mode 100644 index 000000000..86a3d9d3c --- /dev/null +++ b/doc/tutorial_ressol.qbk @@ -0,0 +1,29 @@ +[/ + Copyright 2020 Ilia Shirobokov. + Copyright 2020 Alisa Cherniaeva. + + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +] + +[section:ressol Tonelli–Shanks algorithm] + +[pre +[*Table of Contents] + [link boost_multiprecision.tut.ressol.api Tonelli–Shanks algorithm API] + [link ressol `ressol(const number& a, const number& p)`] + [link ressol_modular `ressol(const number, ExpressionTemplates>& modular)`] +] + +[h2:api Tonelli–Shanks algorithm API] + +[#ressol] [role blue `template inline number ressol(const number& a, const number& p)`] + +Compute the square root of `a` modulo `p` prime using the [@https://en.wikipedia.org/wiki/Tonelli-Shanks_algorithm Tonelli–Shanks algorithm]. + +[#ressol_modular] [role blue `template inline number, ExpressionTemplates> ressol(const number, ExpressionTemplates>& modular)`] + +Compute the square root of `modular` base data [] modulo `modular` mod data [] prime using the [@https://en.wikipedia.org/wiki/Tonelli-Shanks_algorithm Tonelli–Shanks algorithm]. + +[endsect] [/section:ressol] \ No newline at end of file diff --git a/example/modular_examples.cpp b/example/modular_examples.cpp new file mode 100644 index 000000000..61e67773a --- /dev/null +++ b/example/modular_examples.cpp @@ -0,0 +1,46 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2020 Mikhail Komarov +// Copyright (c) 2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#include +#include + +template +void modular_number_examples() +{ + std::cout << "Pre-calculation parameters for module: " << std::endl; + Params mod(7); + std::cout << "Value mod: " << mod << std::endl; + Modular a(4, 7), b(4, mod), c(9, mod), d(3, 4); + std::cout << "Initialization a equal b: " << (a == b) << std::endl; + std::cout << "Value a: " << a << std::endl; + std::cout << "Value b: " << b << std::endl; + std::cout << "Value c: " << c << std::endl; + + std::cout << "Some base function: " << std::endl; + std::cout << "Add a and b: " << a + b << std::endl; + std::cout << "Sub a and b: " << a - b << std::endl; + std::cout << "Sub c and a ((-y mod x) equal ((x-y) mod x): " << c - a << std::endl; + std::cout << "Multiply a and b: " << a * b << std::endl; + std::cout << "Divide a and b: " << a / b << std::endl; + std::cout << "Module a % b: " << a % b << std::endl; + + std::cout << "Some bitwise function: " << std::endl; + std::cout << "a and b: " << (a & b) << std::endl; + std::cout << "a xor b: " << (a ^ b) << std::endl; + std::cout << "a or b: " << (a | b) << std::endl; + + std::cout << "Pow function: " << std::endl; + std::cout << "Pow a^b: " << pow(a, b) << std::endl; +} + +int main() +{ + modular_number_examples(); + return 0; +} diff --git a/include/boost/multiprecision/cpp_modular.hpp b/include/boost/multiprecision/cpp_modular.hpp new file mode 100644 index 000000000..488998b07 --- /dev/null +++ b/include/boost/multiprecision/cpp_modular.hpp @@ -0,0 +1,83 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2020 Mikhail Komarov +// Copyright (c) 2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef BOOST_MP_CPP_MODULAR_HPP +#define BOOST_MP_CPP_MODULAR_HPP + +#include +#include +#include + +namespace boost { +namespace multiprecision { + +//mnt params +typedef modular_params > cpp_mod_params; + +// Fixed precision unsigned types: +typedef modular_params > umod_params_params128_t; +typedef modular_params > umod_params256_t; +typedef modular_params > umod_params512_t; +typedef modular_params > umod_params1024_t; + +// Fixed precision signed types: +typedef modular_params > mod_params128_t; +typedef modular_params > mod_params256_t; +typedef modular_params > mod_params512_t; +typedef modular_params > mod_params1024_t; + +// Over again, but with checking enabled this time: +typedef modular_params > checked_cpp_mod_params; + +// Fixed precision unsigned types: +typedef modular_params > checked_umod_params128_t; +typedef modular_params > checked_umod_params256_t; +typedef modular_params > checked_umod_params512_t; +typedef modular_params > checked_umod_params1024_t; + +// Fixed precision signed types: +typedef modular_params > checked_mod_params128_t; +typedef modular_params > checked_mod_params256_t; +typedef modular_params > checked_mod_params512_t; +typedef modular_params > checked_mod_params1024_t; + +//mod_paramsular_adapter +typedef number > > cpp_mod; + +// Fixed precision unsigned types: +typedef number > > umod128_t; +typedef number > > umod256_t; +typedef number > > umod512_t; +typedef number > > umod1024_t; + +// Fixed precision signed types: +typedef number > > mod128_t; +typedef number > > mod256_t; +typedef number > > mod512_t; +typedef number > > mod1024_t; + +// Over again, but with checking enabled this time: +typedef number > > checked_cpp_mod; + +// Fixed precision unsigned types: +typedef number > > checked_umod128_t; +typedef number > > checked_umod256_t; +typedef number > > checked_umod512_t; +typedef number > > checked_umod1024_t; + +// Fixed precision signed types: +typedef number > > checked_mod128_t; +typedef number > > checked_mod256_t; +typedef number > > checked_mod512_t; +typedef number > > checked_mod1024_t; + +} +} // namespace boost::multiprecision + +#endif diff --git a/include/boost/multiprecision/detail/default_ops.hpp b/include/boost/multiprecision/detail/default_ops.hpp index 853a34535..fef8fb04c 100644 --- a/include/boost/multiprecision/detail/default_ops.hpp +++ b/include/boost/multiprecision/detail/default_ops.hpp @@ -47,6 +47,8 @@ template void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/); template void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/); +template +void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/); } // namespace detail @@ -3613,6 +3615,11 @@ BINARY_OP_FUNCTOR(gcd, number_kind_integer) BINARY_OP_FUNCTOR(lcm, number_kind_integer) HETERO_BINARY_OP_FUNCTOR(pow, unsigned, number_kind_integer) +// +// Modular functions: +// +BINARY_OP_FUNCTOR(pow, number_kind_modular) + #undef BINARY_OP_FUNCTOR #undef UNARY_OP_FUNCTOR diff --git a/include/boost/multiprecision/detail/et_ops.hpp b/include/boost/multiprecision/detail/et_ops.hpp index 86b1cc1b7..acaf9bf4b 100644 --- a/include/boost/multiprecision/detail/et_ops.hpp +++ b/include/boost/multiprecision/detail/et_ops.hpp @@ -1,7 +1,11 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright 2011 John Maddock. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// Copyright 2011 John Maddock. +// Copyright (c) 2019 Mikhail Komarov . +// Copyright (c) 2019 Alexey Moskvin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_MP_ET_OPS_HPP #define BOOST_MP_ET_OPS_HPP @@ -45,7 +49,7 @@ inline BOOST_MP_CXX14_CONSTEXPR detail::expression >(v); } template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, detail::expression > >::type operator~(const number& v) { return detail::expression >(v); } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES @@ -992,7 +996,7 @@ operator/(number&& a, const detail::expression -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, detail::expression, number > >::type operator%(const number& a, const number& b) { @@ -1022,7 +1026,7 @@ operator%(number&& a, number&& b) } #endif template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), detail::expression, V> >::type operator%(const number& a, const V& b) { @@ -1038,7 +1042,7 @@ operator%(number&& a, const V& b) } #endif template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), detail::expression > >::type operator%(const V& a, const number& b) { @@ -1054,7 +1058,7 @@ operator%(const V& a, number&& b) } #endif template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, detail::expression, detail::expression > >::type operator%(const number& a, const detail::expression& b) { @@ -1070,7 +1074,7 @@ operator%(number&& a, const detail::expression -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, detail::expression, number > >::type operator%(const detail::expression& a, const number& b) { @@ -1110,7 +1114,7 @@ operator%(const V& a, const detail::expression& b) // Left shift: // template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value && (number_category::value == number_kind_integer), detail::expression, I> >::type +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), detail::expression, I> >::type operator<<(const number& a, const I& b) { return detail::expression, I>(a, b); @@ -1134,7 +1138,7 @@ operator<<(const detail::expression& a, const I& b) // Right shift: // template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value && (number_category::value == number_kind_integer), +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), detail::expression, I> >::type operator>>(const number& a, const I& b) { @@ -1160,7 +1164,7 @@ operator>>(const detail::expression& a, const I& b) // Bitwise AND: // template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular || number_category::value == number_kind_modular, detail::expression, number > >::type operator&(const number& a, const number& b) { @@ -1190,7 +1194,7 @@ operator&(number&& a, number&& b) } #endif template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), detail::expression, V> >::type operator&(const number& a, const V& b) { @@ -1206,7 +1210,7 @@ operator&(number&& a, const V& b) } #endif template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), detail::expression > >::type operator&(const V& a, const number& b) { @@ -1222,7 +1226,7 @@ operator&(const V& a, number&& b) } #endif template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, detail::expression, detail::expression > >::type operator&(const number& a, const detail::expression& b) { @@ -1238,7 +1242,7 @@ operator&(number&& a, const detail::expression -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, detail::expression, number > >::type operator&(const detail::expression& a, const number& b) { @@ -1278,7 +1282,7 @@ operator&(const V& a, const detail::expression& b) // Bitwise OR: // template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, detail::expression, number > >::type operator|(const number& a, const number& b) { @@ -1308,7 +1312,7 @@ operator|(number&& a, number&& b) } #endif template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), detail::expression, V> >::type operator|(const number& a, const V& b) { @@ -1324,7 +1328,7 @@ operator|(number&& a, const V& b) } #endif template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), detail::expression > >::type operator|(const V& a, const number& b) { @@ -1340,7 +1344,7 @@ operator|(const V& a, number&& b) } #endif template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, detail::expression, detail::expression > >::type operator|(const number& a, const detail::expression& b) { @@ -1356,7 +1360,7 @@ operator|(number&& a, const detail::expression -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, detail::expression, number > >::type operator|(const detail::expression& a, const number& b) { @@ -1396,7 +1400,7 @@ operator|(const V& a, const detail::expression& b) // Bitwise XOR: // template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, detail::expression, number > >::type operator^(const number& a, const number& b) { @@ -1426,7 +1430,7 @@ operator^(number&& a, number&& b) } #endif template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), detail::expression, V> >::type operator^(const number& a, const V& b) { @@ -1442,7 +1446,7 @@ operator^(number&& a, const V& b) } #endif template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), detail::expression > >::type operator^(const V& a, const number& b) { @@ -1458,7 +1462,7 @@ operator^(const V& a, number&& b) } #endif template -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, detail::expression, detail::expression > >::type operator^(const number& a, const detail::expression& b) { @@ -1474,7 +1478,7 @@ operator^(number&& a, const detail::expression -inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, +inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, detail::expression, number > >::type operator^(const detail::expression& a, const number& b) { diff --git a/include/boost/multiprecision/detail/generic_interconvert.hpp b/include/boost/multiprecision/detail/generic_interconvert.hpp index 31fc6e067..f58467b47 100644 --- a/include/boost/multiprecision/detail/generic_interconvert.hpp +++ b/include/boost/multiprecision/detail/generic_interconvert.hpp @@ -1,7 +1,11 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright 2011 John Maddock. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// Copyright 2011 John Maddock +// Copyright (c) 2019 Mikhail Komarov +// Copyright (c) 2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_MP_GENERIC_INTERCONVERT_HPP #define BOOST_MP_GENERIC_INTERCONVERT_HPP @@ -587,6 +591,12 @@ void generic_interconvert(To& to, const From& from, const mpl::int_::value>(), mpl::bool_::value>()); } +template +void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/) +{ + from.mod_data().adjust_regular(to, from.base_data()); +} + } } diff --git a/include/boost/multiprecision/detail/no_et_ops.hpp b/include/boost/multiprecision/detail/no_et_ops.hpp index 61d5249ed..0fcb360aa 100644 --- a/include/boost/multiprecision/detail/no_et_ops.hpp +++ b/include/boost/multiprecision/detail/no_et_ops.hpp @@ -1,7 +1,11 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright 2012 John Maddock. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// Copyright 2012 John Maddock +// Copyright (c) 2020 Mikhail Komarov +// Copyright (c) 2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_MP_NO_ET_OPS_HPP #define BOOST_MP_NO_ET_OPS_HPP @@ -12,647 +16,646 @@ #endif namespace boost { - namespace multiprecision { +namespace multiprecision { - // - // Operators for non-expression template enabled number. - // NOTE: this is not a complete header - really just a suffix to default_ops.hpp. - // NOTE: these operators have to be defined after the methods in default_ops.hpp. - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator-(const number& v) - { - BOOST_STATIC_ASSERT_MSG(is_signed_number::value, "Negating an unsigned type results in ill-defined behavior."); - detail::scoped_default_precision > precision_guard(v); - number result(v); - result.backend().negate(); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator~(const number& v) - { - detail::scoped_default_precision > precision_guard(v); - number result; - eval_complement(result.backend(), v.backend()); - return result; - } - // - // Addition: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator+(const number& a, const number& b) - { - detail::scoped_default_precision > precision_guard(a, b); - number result; - using default_ops::eval_add; - eval_add(result.backend(), a.backend(), b.backend()); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type - operator+(const number& a, const V& b) - { - detail::scoped_default_precision > precision_guard(a); - number result; - using default_ops::eval_add; - eval_add(result.backend(), a.backend(), number::canonical_value(b)); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type - operator+(const V& a, const number& b) - { - detail::scoped_default_precision > precision_guard(b); - number result; - using default_ops::eval_add; - eval_add(result.backend(), b.backend(), number::canonical_value(a)); - return result; - } - // - // Subtraction: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator-(const number& a, const number& b) - { - detail::scoped_default_precision > precision_guard(a, b); - number result; - using default_ops::eval_subtract; - eval_subtract(result.backend(), a.backend(), b.backend()); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type - operator-(const number& a, const V& b) - { - detail::scoped_default_precision > precision_guard(a); - number result; - using default_ops::eval_subtract; - eval_subtract(result.backend(), a.backend(), number::canonical_value(b)); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type - operator-(const V& a, const number& b) - { - detail::scoped_default_precision > precision_guard(b); - number result; - using default_ops::eval_subtract; - eval_subtract(result.backend(), number::canonical_value(a), b.backend()); - return result; - } - // - // Multiply: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator*(const number& a, const number& b) - { - detail::scoped_default_precision > precision_guard(a, b); - number result; - using default_ops::eval_multiply; - eval_multiply(result.backend(), a.backend(), b.backend()); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type - operator*(const number& a, const V& b) - { - detail::scoped_default_precision > precision_guard(a); - number result; - using default_ops::eval_multiply; - eval_multiply(result.backend(), a.backend(), number::canonical_value(b)); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type - operator*(const V& a, const number& b) - { - detail::scoped_default_precision > precision_guard(b); - number result; - using default_ops::eval_multiply; - eval_multiply(result.backend(), b.backend(), number::canonical_value(a)); - return result; - } - // - // divide: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator/(const number& a, const number& b) - { - detail::scoped_default_precision > precision_guard(a, b); - number result; - using default_ops::eval_divide; - eval_divide(result.backend(), a.backend(), b.backend()); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type - operator/(const number& a, const V& b) - { - detail::scoped_default_precision > precision_guard(a); - number result; - using default_ops::eval_divide; - eval_divide(result.backend(), a.backend(), number::canonical_value(b)); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type - operator/(const V& a, const number& b) - { - detail::scoped_default_precision > precision_guard(b); - number result; - using default_ops::eval_divide; - eval_divide(result.backend(), number::canonical_value(a), b.backend()); - return result; - } - // - // modulus: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, number >::type operator%(const number& a, const number& b) - { - detail::scoped_default_precision > precision_guard(a, b); - number result; - using default_ops::eval_modulus; - eval_modulus(result.backend(), a.backend(), b.backend()); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), number >::type - operator%(const number& a, const V& b) - { - detail::scoped_default_precision > precision_guard(a); - number result; - using default_ops::eval_modulus; - eval_modulus(result.backend(), a.backend(), number::canonical_value(b)); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), number >::type - operator%(const V& a, const number& b) - { - detail::scoped_default_precision > precision_guard(b); - number result; - using default_ops::eval_modulus; - eval_modulus(result.backend(), number::canonical_value(a), b.backend()); - return result; - } - // - // Bitwise or: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, number >::type operator|(const number& a, const number& b) - { - number result; - using default_ops::eval_bitwise_or; - eval_bitwise_or(result.backend(), a.backend(), b.backend()); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), number >::type - operator|(const number& a, const V& b) - { - number result; - using default_ops::eval_bitwise_or; - eval_bitwise_or(result.backend(), a.backend(), number::canonical_value(b)); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), number >::type - operator|(const V& a, const number& b) - { - number result; - using default_ops::eval_bitwise_or; - eval_bitwise_or(result.backend(), b.backend(), number::canonical_value(a)); - return result; - } - // - // Bitwise xor: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, number >::type operator^(const number& a, const number& b) - { - number result; - using default_ops::eval_bitwise_xor; - eval_bitwise_xor(result.backend(), a.backend(), b.backend()); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), number >::type - operator^(const number& a, const V& b) - { - number result; - using default_ops::eval_bitwise_xor; - eval_bitwise_xor(result.backend(), a.backend(), number::canonical_value(b)); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), number >::type - operator^(const V& a, const number& b) - { - number result; - using default_ops::eval_bitwise_xor; - eval_bitwise_xor(result.backend(), b.backend(), number::canonical_value(a)); - return result; - } - // - // Bitwise and: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, number >::type operator&(const number& a, const number& b) - { - number result; - using default_ops::eval_bitwise_and; - eval_bitwise_and(result.backend(), a.backend(), b.backend()); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), number >::type - operator&(const number& a, const V& b) - { - number result; - using default_ops::eval_bitwise_and; - eval_bitwise_and(result.backend(), a.backend(), number::canonical_value(b)); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), number >::type - operator&(const V& a, const number& b) - { - number result; - using default_ops::eval_bitwise_and; - eval_bitwise_and(result.backend(), b.backend(), number::canonical_value(a)); - return result; - } - // - // shifts: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value && (number_category::value == number_kind_integer), number >::type - operator<<(const number& a, const I& b) - { - number result(a); - using default_ops::eval_left_shift; - detail::check_shift_range(b, mpl::bool_<(sizeof(I) > sizeof(std::size_t))>(), mpl::bool_::value>()); - eval_left_shift(result.backend(), b); - return result; - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value && (number_category::value == number_kind_integer), number >::type - operator>>(const number& a, const I& b) - { - number result(a); - using default_ops::eval_right_shift; - detail::check_shift_range(b, mpl::bool_<(sizeof(I) > sizeof(std::size_t))>(), mpl::bool_::value>()); - eval_right_shift(result.backend(), b); - return result; - } +// +// Operators for non-expression template enabled number. +// NOTE: this is not a complete header - really just a suffix to default_ops.hpp. +// NOTE: these operators have to be defined after the methods in default_ops.hpp. +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator-(const number& v) +{ + BOOST_STATIC_ASSERT_MSG(is_signed_number::value, "Negating an unsigned type results in ill-defined behavior."); + detail::scoped_default_precision > precision_guard(v); + number result(v); + result.backend().negate(); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator~(const number& v) +{ + detail::scoped_default_precision > precision_guard(v); + number result; + eval_complement(result.backend(), v.backend()); + return result; +} +// +// Addition: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator+(const number& a, const number& b) +{ + detail::scoped_default_precision > precision_guard(a, b); + number result; + using default_ops::eval_add; + eval_add(result.backend(), a.backend(), b.backend()); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type +operator+(const number& a, const V& b) +{ + detail::scoped_default_precision > precision_guard(a); + number result; + using default_ops::eval_add; + eval_add(result.backend(), a.backend(), number::canonical_value(b)); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type +operator+(const V& a, const number& b) +{ + detail::scoped_default_precision > precision_guard(b); + number result; + using default_ops::eval_add; + eval_add(result.backend(), b.backend(), number::canonical_value(a)); + return result; +} +// +// Subtraction: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator-(const number& a, const number& b) +{ + detail::scoped_default_precision > precision_guard(a, b); + number result; + using default_ops::eval_subtract; + eval_subtract(result.backend(), a.backend(), b.backend()); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type +operator-(const number& a, const V& b) +{ + detail::scoped_default_precision > precision_guard(a); + number result; + using default_ops::eval_subtract; + eval_subtract(result.backend(), a.backend(), number::canonical_value(b)); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type +operator-(const V& a, const number& b) +{ + detail::scoped_default_precision > precision_guard(b); + number result; + using default_ops::eval_subtract; + eval_subtract(result.backend(), number::canonical_value(a), b.backend()); + return result; +} +// +// Multiply: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator*(const number& a, const number& b) +{ + detail::scoped_default_precision > precision_guard(a, b); + number result; + using default_ops::eval_multiply; + eval_multiply(result.backend(), a.backend(), b.backend()); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type +operator*(const number& a, const V& b) +{ + detail::scoped_default_precision > precision_guard(a); + number result; + using default_ops::eval_multiply; + eval_multiply(result.backend(), a.backend(), number::canonical_value(b)); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type +operator*(const V& a, const number& b) +{ + detail::scoped_default_precision > precision_guard(b); + number result; + using default_ops::eval_multiply; + eval_multiply(result.backend(), b.backend(), number::canonical_value(a)); + return result; +} +// +// divide: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator/(const number& a, const number& b) +{ + detail::scoped_default_precision > precision_guard(a, b); + number result; + using default_ops::eval_divide; + eval_divide(result.backend(), a.backend(), b.backend()); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type +operator/(const number& a, const V& b) +{ + detail::scoped_default_precision > precision_guard(a); + number result; + using default_ops::eval_divide; + eval_divide(result.backend(), a.backend(), number::canonical_value(b)); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type +operator/(const V& a, const number& b) +{ + detail::scoped_default_precision > precision_guard(b); + number result; + using default_ops::eval_divide; + eval_divide(result.backend(), number::canonical_value(a), b.backend()); + return result; +} +// +// modulus: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, number >::type operator%(const number& a, const number& b) +{ + detail::scoped_default_precision > precision_guard(a, b); + number result; + using default_ops::eval_modulus; + eval_modulus(result.backend(), a.backend(), b.backend()); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator%(const number& a, const V& b) +{ + detail::scoped_default_precision > precision_guard(a); + number result; + using default_ops::eval_modulus; + eval_modulus(result.backend(), a.backend(), number::canonical_value(b)); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator%(const V& a, const number& b) +{ + detail::scoped_default_precision > precision_guard(b); + number result; + using default_ops::eval_modulus; + eval_modulus(result.backend(), number::canonical_value(a), b.backend()); + return result; +} +// +// Bitwise or: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, number >::type operator|(const number& a, const number& b) +{ + number result; + using default_ops::eval_bitwise_or; + eval_bitwise_or(result.backend(), a.backend(), b.backend()); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator|(const number& a, const V& b) +{ + number result; + using default_ops::eval_bitwise_or; + eval_bitwise_or(result.backend(), a.backend(), number::canonical_value(b)); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator|(const V& a, const number& b) +{ + number result; + using default_ops::eval_bitwise_or; + eval_bitwise_or(result.backend(), b.backend(), number::canonical_value(a)); + return result; +} +// +// Bitwise xor: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, number >::type operator^(const number& a, const number& b) +{ + number result; + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(result.backend(), a.backend(), b.backend()); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator^(const number& a, const V& b) +{ + number result; + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(result.backend(), a.backend(), number::canonical_value(b)); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator^(const V& a, const number& b) +{ + number result; + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(result.backend(), b.backend(), number::canonical_value(a)); + return result; +} +// +// Bitwise and: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, number >::type operator&(const number& a, const number& b) +{ + number result; + using default_ops::eval_bitwise_and; + eval_bitwise_and(result.backend(), a.backend(), b.backend()); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator&(const number& a, const V& b) +{ + number result; + using default_ops::eval_bitwise_and; + eval_bitwise_and(result.backend(), a.backend(), number::canonical_value(b)); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator&(const V& a, const number& b) +{ + number result; + using default_ops::eval_bitwise_and; + eval_bitwise_and(result.backend(), b.backend(), number::canonical_value(a)); + return result; +} +// +// shifts: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator<<(const number& a, const I& b) +{ + number result(a); + using default_ops::eval_left_shift; + detail::check_shift_range(b, mpl::bool_<(sizeof(I) > sizeof(std::size_t))>(), mpl::bool_::value>()); + eval_left_shift(result.backend(), b); + return result; +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator>>(const number& a, const I& b) +{ + number result(a); + using default_ops::eval_right_shift; + detail::check_shift_range(b, mpl::bool_<(sizeof(I) > sizeof(std::size_t))>(), mpl::bool_::value>()); + eval_right_shift(result.backend(), b); + return result; +} #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !(defined(__GNUC__) && ((__GNUC__ == 4) && (__GNUC_MINOR__ < 5))) - // - // If we have rvalue references go all over again with rvalue ref overloads and move semantics. - // Note that while it would be tempting to implement these so they return an rvalue reference - // (and indeed this would be optimally efficient), this is unsafe due to users propensity to - // write: - // - // const T& t = a * b; - // - // which would lead to a dangling reference if we didn't return by value. Of course move - // semantics help a great deal in return by value, so performance is still pretty good... - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator-(number&& v) - { - BOOST_STATIC_ASSERT_MSG(is_signed_number::value, "Negating an unsigned type results in ill-defined behavior."); - v.backend().negate(); - return static_cast&&>(v); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, number >::type operator~(number&& v) - { - eval_complement(v.backend(), v.backend()); - return static_cast&&>(v); - } - // - // Addition: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator+(number&& a, const number& b) - { - using default_ops::eval_add; - detail::scoped_default_precision > precision_guard(a, b); - eval_add(a.backend(), b.backend()); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator+(const number& a, number&& b) - { - using default_ops::eval_add; - detail::scoped_default_precision > precision_guard(a, b); - eval_add(b.backend(), a.backend()); - return static_cast&&>(b); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator+(number&& a, number&& b) - { - using default_ops::eval_add; - detail::scoped_default_precision > precision_guard(a, b); - eval_add(a.backend(), b.backend()); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type - operator+(number&& a, const V& b) - { - using default_ops::eval_add; - detail::scoped_default_precision > precision_guard(a, b); - eval_add(a.backend(), number::canonical_value(b)); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type - operator+(const V& a, number&& b) - { - using default_ops::eval_add; - detail::scoped_default_precision > precision_guard(a, b); - eval_add(b.backend(), number::canonical_value(a)); - return static_cast&&>(b); - } - // - // Subtraction: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator-(number&& a, const number& b) - { - using default_ops::eval_subtract; - detail::scoped_default_precision > precision_guard(a, b); - eval_subtract(a.backend(), b.backend()); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if, number >::type operator-(const number& a, number&& b) - { - using default_ops::eval_subtract; - detail::scoped_default_precision > precision_guard(a, b); - eval_subtract(b.backend(), a.backend()); - b.backend().negate(); - return static_cast&&>(b); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator-(number&& a, number&& b) - { - using default_ops::eval_subtract; - detail::scoped_default_precision > precision_guard(a, b); - eval_subtract(a.backend(), b.backend()); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type - operator-(number&& a, const V& b) - { - using default_ops::eval_subtract; - detail::scoped_default_precision > precision_guard(a, b); - eval_subtract(a.backend(), number::canonical_value(b)); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(is_compatible_arithmetic_type >::value && is_signed_number::value), number >::type - operator-(const V& a, number&& b) - { - using default_ops::eval_subtract; - detail::scoped_default_precision > precision_guard(a, b); - eval_subtract(b.backend(), number::canonical_value(a)); - b.backend().negate(); - return static_cast&&>(b); - } - // - // Multiply: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator*(number&& a, const number& b) - { - using default_ops::eval_multiply; - detail::scoped_default_precision > precision_guard(a, b); - eval_multiply(a.backend(), b.backend()); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator*(const number& a, number&& b) - { - using default_ops::eval_multiply; - detail::scoped_default_precision > precision_guard(a, b); - eval_multiply(b.backend(), a.backend()); - return static_cast&&>(b); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator*(number&& a, number&& b) - { - using default_ops::eval_multiply; - detail::scoped_default_precision > precision_guard(a, b); - eval_multiply(a.backend(), b.backend()); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type - operator*(number&& a, const V& b) - { - using default_ops::eval_multiply; - detail::scoped_default_precision > precision_guard(a, b); - eval_multiply(a.backend(), number::canonical_value(b)); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type - operator*(const V& a, number&& b) - { - using default_ops::eval_multiply; - detail::scoped_default_precision > precision_guard(a, b); - eval_multiply(b.backend(), number::canonical_value(a)); - return static_cast&&>(b); - } - // - // divide: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator/(number&& a, const number& b) - { - using default_ops::eval_divide; - detail::scoped_default_precision > precision_guard(a, b); - eval_divide(a.backend(), b.backend()); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type - operator/(number&& a, const V& b) - { - using default_ops::eval_divide; - detail::scoped_default_precision > precision_guard(a, b); - eval_divide(a.backend(), number::canonical_value(b)); - return static_cast&&>(a); - } - // - // modulus: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, number >::type operator%(number&& a, const number& b) - { - using default_ops::eval_modulus; - detail::scoped_default_precision > precision_guard(a, b); - eval_modulus(a.backend(), b.backend()); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), number >::type - operator%(number&& a, const V& b) - { - using default_ops::eval_modulus; - detail::scoped_default_precision > precision_guard(a, b); - eval_modulus(a.backend(), number::canonical_value(b)); - return static_cast&&>(a); - } - // - // Bitwise or: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, number >::type operator|(number&& a, const number& b) - { - using default_ops::eval_bitwise_or; - eval_bitwise_or(a.backend(), b.backend()); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, number >::type operator|(const number& a, number&& b) - { - using default_ops::eval_bitwise_or; - eval_bitwise_or(b.backend(), a.backend()); - return static_cast&&>(b); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, number >::type operator|(number&& a, number&& b) - { - using default_ops::eval_bitwise_or; - eval_bitwise_or(a.backend(), b.backend()); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), number >::type - operator|(number&& a, const V& b) - { - using default_ops::eval_bitwise_or; - eval_bitwise_or(a.backend(), number::canonical_value(b)); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), number >::type - operator|(const V& a, number&& b) - { - using default_ops::eval_bitwise_or; - eval_bitwise_or(b.backend(), number::canonical_value(a)); - return static_cast&&>(b); - } - // - // Bitwise xor: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, number >::type operator^(number&& a, const number& b) - { - using default_ops::eval_bitwise_xor; - eval_bitwise_xor(a.backend(), b.backend()); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, number >::type operator^(const number& a, number&& b) - { - using default_ops::eval_bitwise_xor; - eval_bitwise_xor(b.backend(), a.backend()); - return static_cast&&>(b); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, number >::type operator^(number&& a, number&& b) - { - using default_ops::eval_bitwise_xor; - eval_bitwise_xor(a.backend(), b.backend()); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), number >::type - operator^(number&& a, const V& b) - { - using default_ops::eval_bitwise_xor; - eval_bitwise_xor(a.backend(), number::canonical_value(b)); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), number >::type - operator^(const V& a, number&& b) - { - using default_ops::eval_bitwise_xor; - eval_bitwise_xor(b.backend(), number::canonical_value(a)); - return static_cast&&>(b); - } - // - // Bitwise and: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, number >::type operator&(number&& a, const number& b) - { - using default_ops::eval_bitwise_and; - eval_bitwise_and(a.backend(), b.backend()); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, number >::type operator&(const number& a, number&& b) - { - using default_ops::eval_bitwise_and; - eval_bitwise_and(b.backend(), a.backend()); - return static_cast&&>(b); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer, number >::type operator&(number&& a, number&& b) - { - using default_ops::eval_bitwise_and; - eval_bitwise_and(a.backend(), b.backend()); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), number >::type - operator&(number&& a, const V& b) - { - using default_ops::eval_bitwise_and; - eval_bitwise_and(a.backend(), number::canonical_value(b)); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer), number >::type - operator&(const V& a, number&& b) - { - using default_ops::eval_bitwise_and; - eval_bitwise_and(b.backend(), number::canonical_value(a)); - return static_cast&&>(b); - } - // - // shifts: - // - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value && (number_category::value == number_kind_integer), number >::type - operator<<(number&& a, const I& b) - { - using default_ops::eval_left_shift; - eval_left_shift(a.backend(), b); - return static_cast&&>(a); - } - template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value && (number_category::value == number_kind_integer), number >::type - operator>>(number&& a, const I& b) - { - using default_ops::eval_right_shift; - eval_right_shift(a.backend(), b); - return static_cast&&>(a); - } +// +// If we have rvalue references go all over again with rvalue ref overloads and move semantics. +// Note that while it would be tempting to implement these so they return an rvalue reference +// (and indeed this would be optimally efficient), this is unsafe due to users propensity to +// write: +// +// const T& t = a * b; +// +// which would lead to a dangling reference if we didn't return by value. Of course move +// semantics help a great deal in return by value, so performance is still pretty good... +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator-(number&& v) +{ + BOOST_STATIC_ASSERT_MSG(is_signed_number::value, "Negating an unsigned type results in ill-defined behavior."); + v.backend().negate(); + return static_cast&&>(v); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, number >::type operator~(number&& v) +{ + eval_complement(v.backend(), v.backend()); + return static_cast&&>(v); +} +// +// Addition: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator+(number&& a, const number& b) +{ + using default_ops::eval_add; + detail::scoped_default_precision > precision_guard(a, b); + eval_add(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator+(const number& a, number&& b) +{ + using default_ops::eval_add; + detail::scoped_default_precision > precision_guard(a, b); + eval_add(b.backend(), a.backend()); + return static_cast&&>(b); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator+(number&& a, number&& b) +{ + using default_ops::eval_add; + detail::scoped_default_precision > precision_guard(a, b); + eval_add(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type +operator+(number&& a, const V& b) +{ + using default_ops::eval_add; + detail::scoped_default_precision > precision_guard(a, b); + eval_add(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type +operator+(const V& a, number&& b) +{ + using default_ops::eval_add; + detail::scoped_default_precision > precision_guard(a, b); + eval_add(b.backend(), number::canonical_value(a)); + return static_cast&&>(b); +} +// +// Subtraction: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator-(number&& a, const number& b) +{ + using default_ops::eval_subtract; + detail::scoped_default_precision > precision_guard(a, b); + eval_subtract(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if, number >::type operator-(const number& a, number&& b) +{ + using default_ops::eval_subtract; + detail::scoped_default_precision > precision_guard(a, b); + eval_subtract(b.backend(), a.backend()); + b.backend().negate(); + return static_cast&&>(b); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator-(number&& a, number&& b) +{ + using default_ops::eval_subtract; + detail::scoped_default_precision > precision_guard(a, b); + eval_subtract(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type +operator-(number&& a, const V& b) +{ + using default_ops::eval_subtract; + detail::scoped_default_precision > precision_guard(a, b); + eval_subtract(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(is_compatible_arithmetic_type >::value && is_signed_number::value), number >::type +operator-(const V& a, number&& b) +{ + using default_ops::eval_subtract; + detail::scoped_default_precision > precision_guard(a, b); + eval_subtract(b.backend(), number::canonical_value(a)); + b.backend().negate(); + return static_cast&&>(b); +} +// +// Multiply: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator*(number&& a, const number& b) +{ + using default_ops::eval_multiply; + detail::scoped_default_precision > precision_guard(a, b); + eval_multiply(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator*(const number& a, number&& b) +{ + using default_ops::eval_multiply; + detail::scoped_default_precision > precision_guard(a, b); + eval_multiply(b.backend(), a.backend()); + return static_cast&&>(b); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator*(number&& a, number&& b) +{ + using default_ops::eval_multiply; + detail::scoped_default_precision > precision_guard(a, b); + eval_multiply(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type +operator*(number&& a, const V& b) +{ + using default_ops::eval_multiply; + detail::scoped_default_precision > precision_guard(a, b); + eval_multiply(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type +operator*(const V& a, number&& b) +{ + using default_ops::eval_multiply; + detail::scoped_default_precision > precision_guard(a, b); + eval_multiply(b.backend(), number::canonical_value(a)); + return static_cast&&>(b); +} +// +// divide: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number operator/(number&& a, const number& b) +{ + using default_ops::eval_divide; + detail::scoped_default_precision > precision_guard(a, b); + eval_divide(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if >, number >::type +operator/(number&& a, const V& b) +{ + using default_ops::eval_divide; + detail::scoped_default_precision > precision_guard(a, b); + eval_divide(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +// +// modulus: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, number >::type operator%(number&& a, const number& b) +{ + using default_ops::eval_modulus; + detail::scoped_default_precision > precision_guard(a, b); + eval_modulus(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator%(number&& a, const V& b) +{ + using default_ops::eval_modulus; + detail::scoped_default_precision > precision_guard(a, b); + eval_modulus(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +// +// Bitwise or: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, number >::type operator|(number&& a, const number& b) +{ + using default_ops::eval_bitwise_or; + eval_bitwise_or(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, number >::type operator|(const number& a, number&& b) +{ + using default_ops::eval_bitwise_or; + eval_bitwise_or(b.backend(), a.backend()); + return static_cast&&>(b); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, number >::type operator|(number&& a, number&& b) +{ + using default_ops::eval_bitwise_or; + eval_bitwise_or(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator|(number&& a, const V& b) +{ + using default_ops::eval_bitwise_or; + eval_bitwise_or(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator|(const V& a, number&& b) +{ + using default_ops::eval_bitwise_or; + eval_bitwise_or(b.backend(), number::canonical_value(a)); + return static_cast&&>(b); +} +// +// Bitwise xor: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, number >::type operator^(number&& a, const number& b) +{ + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, number >::type operator^(const number& a, number&& b) +{ + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(b.backend(), a.backend()); + return static_cast&&>(b); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, number >::type operator^(number&& a, number&& b) +{ + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator^(number&& a, const V& b) +{ + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator^(const V& a, number&& b) +{ + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(b.backend(), number::canonical_value(a)); + return static_cast&&>(b); +} +// +// Bitwise and: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, number >::type operator&(number&& a, const number& b) +{ + using default_ops::eval_bitwise_and; + eval_bitwise_and(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, number >::type operator&(const number& a, number&& b) +{ + using default_ops::eval_bitwise_and; + eval_bitwise_and(b.backend(), a.backend()); + return static_cast&&>(b); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value == number_kind_integer || number_category::value == number_kind_modular, number >::type operator&(number&& a, number&& b) +{ + using default_ops::eval_bitwise_and; + eval_bitwise_and(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator&(number&& a, const V& b) +{ + using default_ops::eval_bitwise_and; + eval_bitwise_and(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c >::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator&(const V& a, number&& b) +{ + using default_ops::eval_bitwise_and; + eval_bitwise_and(b.backend(), number::canonical_value(a)); + return static_cast&&>(b); +} +// +// shifts: +// +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator<<(number&& a, const I& b) +{ + using default_ops::eval_left_shift; + eval_left_shift(a.backend(), b); + return static_cast&&>(a); +} +template +BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c::value && (number_category::value == number_kind_integer || number_category::value == number_kind_modular), number >::type +operator>>(number&& a, const I& b) +{ + using default_ops::eval_right_shift; + eval_right_shift(a.backend(), b); + return static_cast&&>(a); +} #endif - } -} // namespace boost::multiprecision +}} // namespace boost::multiprecision #ifdef BOOST_MSVC #pragma warning(pop) diff --git a/include/boost/multiprecision/detail/number_base.hpp b/include/boost/multiprecision/detail/number_base.hpp index c7875d104..e6940295b 100644 --- a/include/boost/multiprecision/detail/number_base.hpp +++ b/include/boost/multiprecision/detail/number_base.hpp @@ -299,6 +299,7 @@ struct canonical_imp, Backend, mpl::int_<3> > typedef B type; }; #endif + template struct canonical_imp > { @@ -1682,7 +1683,8 @@ enum number_category_type number_kind_floating_point = 1, number_kind_rational = 2, number_kind_fixed_point = 3, - number_kind_complex = 4 + number_kind_complex = 4, + number_kind_modular = 5 }; template diff --git a/include/boost/multiprecision/gmp.hpp b/include/boost/multiprecision/gmp.hpp index 22463d635..41fc2f2e6 100644 --- a/include/boost/multiprecision/gmp.hpp +++ b/include/boost/multiprecision/gmp.hpp @@ -1881,6 +1881,12 @@ inline void eval_lcm(gmp_int& result, const gmp_int& a, const gmp_int& b) { mpz_lcm(result.data(), a.data(), b.data()); } + +inline int eval_jacobi(const gmp_int& a, const gmp_int& n) +{ + return mpz_jacobi(a.data(), n.data()); +} + template inline typename enable_if_c<(is_unsigned::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b) { diff --git a/include/boost/multiprecision/gmp_modular.hpp b/include/boost/multiprecision/gmp_modular.hpp new file mode 100644 index 000000000..9051949e6 --- /dev/null +++ b/include/boost/multiprecision/gmp_modular.hpp @@ -0,0 +1,23 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2020 Mikhail Komarov +// Copyright (c) 2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef _MULTIPRECISION_GMP_MODULAR_HPP +#define _MULTIPRECISION_GMP_MODULAR_HPP + +#include +#include +#include + +namespace boost { +namespace multiprecision { +typedef modular_params mpz_int_mod_params; +typedef number > mpz_int_mod; +} +} // namespace boost::multiprecision +#endif //_MULTIPRECISION_GMP_MODULAR_HPP diff --git a/include/boost/multiprecision/inverse.hpp b/include/boost/multiprecision/inverse.hpp new file mode 100644 index 000000000..f6542c7f4 --- /dev/null +++ b/include/boost/multiprecision/inverse.hpp @@ -0,0 +1,77 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2020 Mikhail Komarov +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef BOOST_MULTIPRECISION_INVERSE_HPP +#define BOOST_MULTIPRECISION_INVERSE_HPP + +#include + +#include + +#include +#include +#include +#include + +namespace boost { +namespace multiprecision { + +template +number inverse_extended_euclidean_algorithm( + const number& n, const number& mod) +{ + return number(backends::eval_inverse_extended_euclidean_algorithm(n.backend(), mod.backend())); +} + +template +number, ExpressionTemplates> inverse_extended_euclidean_algorithm( + const number, ExpressionTemplates>& modular) +{ + number new_base, res; + number, ExpressionTemplates> res_mod; + + modular.backend().mod_data().adjust_regular(new_base.backend(), modular.backend().base_data()); + res = backends::eval_inverse_extended_euclidean_algorithm(new_base.backend(), modular.backend().mod_data().get_mod().backend()); + assign_components(res_mod.backend(), res.backend(), modular.backend().mod_data().get_mod().backend()); + + return res_mod; +} + +template +number monty_inverse(const number& a, + const number& p, + const number& k) +{ + number res; + backends::eval_monty_inverse(res.backend(), a.backend(), p.backend(), k.backend()); + return res; +} + +/* +template ::value>::type> +IntegerType monty_inverse(const IntegerType& a) +{ + return eval_monty_inverse(a); +} + */ + +/* +template ::value>::type> +IntegerType monty_inverse(const IntegerType& a) +{ + IntegerType res; + eval_monty_inverse(res.backend(), a.backend()); + return res; +} + */ + +} +} // namespace boost::multiprecision + +#endif + diff --git a/include/boost/multiprecision/jacobi.hpp b/include/boost/multiprecision/jacobi.hpp new file mode 100644 index 000000000..9ae6f08f6 --- /dev/null +++ b/include/boost/multiprecision/jacobi.hpp @@ -0,0 +1,101 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2018-2020 Mikhail Komarov +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef BOOST_MULTIPRECISION_JACOBI_HPP +#define BOOST_MULTIPRECISION_JACOBI_HPP + +#include + +namespace boost { +namespace multiprecision { + +template +inline int eval_jacobi(const Backend& a, const Backend& n) +{ + using default_ops::eval_divide; + using default_ops::eval_get_sign; + using default_ops::eval_gt; + using default_ops::eval_integer_modulus; + using default_ops::eval_is_zero; + using default_ops::eval_lsb; + using default_ops::eval_lt; + using default_ops::eval_modulus; + using default_ops::eval_right_shift; + + if (eval_get_sign(a) < 0) + { + BOOST_THROW_EXCEPTION(std::invalid_argument("jacobi: first argument must be non-negative")); + } + if (!eval_integer_modulus(n, 2) || eval_lt(n, 2)) + { + BOOST_THROW_EXCEPTION(std::invalid_argument("jacobi: second argument must be odd and > 1")); + } + + Backend x = a, y = n; + int J = 1; + + while (eval_gt(y, 1)) + { + eval_modulus(x, y); + + Backend yd2 = y; + eval_right_shift(yd2, 1); + + if (eval_gt(x, yd2)) + { + eval_subtract(x, y, x); + if (eval_integer_modulus(y, 4) == 3) + { + J = -J; + } + } + if (eval_is_zero(x)) + { + return 0; + } + + size_t shifts = eval_lsb(x); + eval_right_shift(x, shifts); + if (shifts & 1) + { + std::size_t y_mod_8 = eval_integer_modulus(y, 8); + if (y_mod_8 == 3 || y_mod_8 == 5) + { + J = -J; + } + } + + if (eval_integer_modulus(x, 4) == 3 && eval_integer_modulus(y, 4) == 3) + { + J = -J; + } + + std::swap(x, y); + } + return J; +} + +/** + * Compute the Jacobi symbol. If n is prime, this is equivalent + * to the Legendre symbol. + * @see http://mathworld.wolfram.com/JacobiSymbol.html + * + * @param a is a non-negative integer + * @param n is an odd integer > 1 + * @return (n / m) + */ +template +inline typename enable_if_c::value == number_kind_integer, int>::type jacobi( + const number& a, const number& n) +{ + return eval_jacobi(a.backend(), n.backend()); +} +} +} // namespace boost::multiprecision + +#endif //BOOST_MULTIPRECISION_JACOBI_HPP diff --git a/include/boost/multiprecision/modular/barrett_params.hpp b/include/boost/multiprecision/modular/barrett_params.hpp new file mode 100644 index 000000000..fe053baad --- /dev/null +++ b/include/boost/multiprecision/modular/barrett_params.hpp @@ -0,0 +1,216 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2020 Mikhail Komarov +// Copyright (c) 2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef BOOST_MULTIPRECISION_BARRETT_PARAMS_HPP +#define BOOST_MULTIPRECISION_BARRETT_PARAMS_HPP + +#include +#include + +namespace boost { +namespace multiprecision { +namespace backends { +/** + * Parameters for Montgomery Reduction + */ +template +class barrett_params : public base_params +{ + typedef number number_type; + + protected: + template + inline void initialize_barrett_params(const Number& p) + { + using default_ops::eval_bit_set; + using default_ops::eval_divide; + + this->initialize_base_params(p); + + m_mu = 0; + + eval_bit_set(m_mu.backend(), 2 * (1 + msb(p))); + eval_divide(m_mu.backend(), this->m_mod.backend()); + } + + public: + barrett_params() : base_params() {} + + template + explicit barrett_params(const Number& p) : base_params(p) + { + initialize_barrett_params(p); + } + + inline const number_type& mu() const { return m_mu; } + + template + barrett_params& operator=(const V& v) + { + initialize_barrett_params(v); + return *this; + } + + inline void eval_barret_reduce(Backend& result) const + { + using default_ops::eval_add; + using default_ops::eval_bit_set; + using default_ops::eval_decrement; + using default_ops::eval_lt; + using default_ops::eval_multiply; + using default_ops::eval_subtract; + using default_ops::eval_msb; + + if (eval_lt(result, this->m_mod.backend())) + { + if (eval_lt(result, 0)) + { + eval_add(result, this->m_mod.backend()); + return; + } + return; + } + else if (eval_msb(result) < 2 * msb(this->m_mod)) + { + Backend t1(result); + + eval_multiply(t1, m_mu.backend()); + eval_right_shift(t1, 2 * (1 + msb(this->mod()))); + eval_multiply(t1, this->m_mod.backend()); + eval_subtract(result, result, t1); + + if (eval_lt(this->m_mod.backend(), result) || (result.compare(this->m_mod.backend()) == 0)) + { + eval_subtract(result, result, this->m_mod.backend()); + } + + return; + } + else + { + eval_modulus(result, this->m_mod.backend()); + return; + } + } + + protected: + number_type m_mu; +}; + +//template +//class barrett_params : public base_params +//{ +// typedef number number_type; +// +// protected: +// template +// void initialize_barrett_params(const Number& p) +// { +// using default_ops::eval_bit_set; +// using default_ops::eval_divide; +// +// this->initialize_base_params(p); +// +// m_mu = 0; +// +// eval_bit_set(m_mu.backend(), 2 * sizeof(limb_type) * CHAR_BIT * p.backend().size()); +// eval_divide(m_mu.backend(), this->m_mod.backend()); +// } +// +// public: +// barrett_params() : base_params() {} +// +// template +// explicit barrett_params(const Number& p) : base_params(p) +// { +// initialize_barrett_params(p); +// } +// +// const number_type& mu() const { return m_mu; } +// +// template +// barrett_params& operator=(const V& v) +// { +// initialize_barrett_params(v); +// return *this; +// } +// +// inline void eval_barret_reduce(Backend& result) const +// { +// using default_ops::eval_add; +// using default_ops::eval_bit_set; +// using default_ops::eval_lt; +// using default_ops::eval_multiply; +// using default_ops::eval_decrement; +// using default_ops::eval_subtract; +// +// if (result.size() < this->m_mod.backend().size() || eval_lt(result, this->m_mod.backend())) +// { +// if (eval_lt(result, 0)) +// { +// eval_add(result, this->m_mod.backend()); +// return; +// } +// return; +// } +// else if (result.size() < 2 * this->m_mod.backend().size()) +// { +// Backend t1(result); +// +// eval_multiply(t1, m_mu.backend()); +// eval_right_shift(t1, (2 * sizeof(limb_type) * CHAR_BIT * (this->m_mod.backend().size()))); +// +// eval_multiply(t1, this->m_mod.backend()); +// +// { +// Backend tmp; +// eval_bit_set(tmp, sizeof(limb_type) * CHAR_BIT * (this->m_mod.backend().size() + 1)); +// eval_decrement(tmp); +// eval_bitwise_and(t1, tmp); +// } +// //eval_mask_bits(t1, Backend::limb_bits * (this->m_mod.backend().size() + 1)); +// +// eval_subtract(t1, result, t1); +// +// if (eval_lt(t1, 0)) +// { +// Backend p2; +// eval_bit_set(p2, sizeof(limb_type) * CHAR_BIT * (this->m_mod.backend().size() + 1)); +// eval_add(t1, p2); +// } +// +// while (eval_lt(this->m_mod.backend(), t1) || (t1.compare(this->m_mod.backend()) == 0)) +// { +// eval_subtract(t1, this->m_mod.backend()); +// } +// +// if (eval_lt(result, 0)) +// { +// eval_add(t1, this->m_mod.backend()); +// } +// +// result = t1; +// return; +// } +// else +// { +// eval_modulus(result, this->m_mod.backend()); +// return; +// } +// } +// +// protected: +// cpp_int m_mu; //number_type m_mu; +//}; + +} +} +} // namespace boost::multiprecision::backends + +#endif //_MULTIPRECISION_BARRETT_PARAMS_HPP diff --git a/include/boost/multiprecision/modular/base_params.hpp b/include/boost/multiprecision/modular/base_params.hpp new file mode 100644 index 000000000..3f3a24884 --- /dev/null +++ b/include/boost/multiprecision/modular/base_params.hpp @@ -0,0 +1,46 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2020 Mikhail Komarov +// Copyright (c) 2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef BOOST_MULTIPRECISION_BASE_PARAMS_HPP +#define BOOST_MULTIPRECISION_BASE_PARAMS_HPP + +namespace boost { +namespace multiprecision { +namespace backends { + +template +class base_params +{ + typedef number number_type; + + protected: + template + inline void initialize_base_params(const Number& mod) + { + m_mod = mod; + } + + public: + base_params() {} + + template + explicit base_params(const Number& p) + { + initialize_base_params(p); + } + + inline const number_type& mod() const { return m_mod; } + + protected: + number_type m_mod; +}; +} +} +} // namespace boost::multiprecision::backends +#endif //BOOST_MULTIPRECISION_BASE_PARAMS_HPP diff --git a/include/boost/multiprecision/modular/inverse.hpp b/include/boost/multiprecision/modular/inverse.hpp new file mode 100644 index 000000000..c8192a226 --- /dev/null +++ b/include/boost/multiprecision/modular/inverse.hpp @@ -0,0 +1,690 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2020 Mikhail Komarov +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef BOOST_MULTIPRECISION_MODULAR_BACKENDS_INVERSE_HPP +#define BOOST_MULTIPRECISION_MODULAR_BACKENDS_INVERSE_HPP + +#include + +#include +#include + +#include +#include + +namespace boost { +namespace multiprecision { +namespace backends { + +template +Backend eval_extended_euclidean_algorithm(Backend& a, Backend& b, Backend& x, Backend& y) +{ + if (eval_is_zero(a)) + { + typedef typename mpl::front::type ui_type; + x = ui_type(0u); + y = ui_type(1u); + return b; + } + Backend x1, y1, tmp = b; + eval_modulus(tmp, a); + Backend d = eval_extended_euclidean_algorithm(tmp, a, x1, y1); + tmp = b; + eval_divide(tmp, a); + eval_multiply(tmp, x1); + x = y1; + eval_subtract(x, tmp); + y = x1; + return d; +} + +template +Backend eval_inverse_extended_euclidean_algorithm(const Backend& a, const Backend& m) +{ + Backend aa = a, mm = m, x, y, g; + typedef typename mpl::front::type ui_type; + g = eval_extended_euclidean_algorithm(aa, mm, x, y); + if (!eval_eq(g, ui_type(1u))) + { + //BOOST_THROW_EXCEPTION(std::invalid_argument("eval_inverse_with_gcd: no inverse element")); + return ui_type(0u); + } + else + { + eval_modulus(x, m); + eval_add(x, m); + eval_modulus(x, m); + return x; + } +} + +template +typename mpl::front::type eval_monty_inverse(typename mpl::front::type a) +{ + typedef typename mpl::front::type si_type; + + if (a % 2 == 0) + { + throw std::invalid_argument("monty_inverse only valid for odd integers"); + } + + /* + * From "A New Algorithm for Inversion mod p^k" by Çetin Kaya Koç + * https://eprint.iacr.org/2017/411.pdf sections 5 and 7. + */ + + si_type b = 1; + si_type r = 0; + + for (size_t i = 0; i != sizeof(si_type) * CHAR_BIT; ++i) + { + const si_type bi = b % 2; + r >>= 1; + r += bi << (sizeof(si_type) * CHAR_BIT - 1); + + b -= a * bi; + b >>= 1; + } + + // Now invert in addition space + r = (~static_cast(0) - r) + 1; + + return r; +} + +template +void eval_monty_inverse(Backend& res, const Backend& a, const Backend& p, const Backend& k) +{ + + using default_ops::eval_modulus; + using default_ops::eval_subtract; + using default_ops::eval_abs; + using default_ops::eval_gt; + + typedef typename mpl::front::type ui_type; + Backend zero = ui_type(0u); + Backend one = ui_type(1u); + Backend two = ui_type(2u); + + /* + * From "A New Algorithm for Inversion mod p^k" by Çetin Kaya Koç + * https://eprint.iacr.org/2017/411.pdf sections 5 and 7. + */ + Backend c, tmp; + + //a^(-1) mod p: + c = eval_inverse_extended_euclidean_algorithm(a, p); + + Backend bi = one, bt, i = zero, k_negone = k, xi, nextp = one; + eval_subtract(k_negone, one); + res = zero; + + ui_type kn = cpp_int(k_negone); + + while (!eval_eq(i, k)) + { + //xi: + xi = bi; + eval_multiply(xi, c); + eval_modulus(xi, p); + + if (eval_get_sign(xi) < 0) + { + tmp = xi; + eval_abs(tmp, tmp); + eval_modulus(tmp, p); + xi = p; + eval_subtract(xi, tmp); + } + + //bi: + tmp = a; + eval_multiply(tmp, xi); + eval_subtract(bi, tmp); + eval_divide(bi, p); + + //res: + tmp = xi; + eval_multiply(tmp, nextp); + eval_multiply(nextp, p); + eval_add(res, tmp); + eval_add(i, one); + } +} + +/* +template +inline void bigint_shr1(typename mpl::front::type x[], size_t x_size, + size_t word_shift, size_t bit_shift) +{ + typedef typename mpl::front::type ui_type; + + const size_t top = x_size >= word_shift ? (x_size - word_shift) : 0; + + if (top > 0) + copy_mem(x, x + word_shift, top); + clear_mem(x + top, std::min(word_shift, x_size)); + + const auto carry_mask = CT::Mask::expand(bit_shift); + const size_t carry_shift = carry_mask.if_set_return(BOTAN_MP_WORD_BITS - bit_shift); + + ui_type carry = 0; + + for (size_t i = 0; i != top; ++i) + { + const ui_type w = x[top - i - 1]; + x[top - i - 1] = (w >> bit_shift) | carry; + carry = carry_mask.if_set_return(w << carry_shift); + } +} + +template +inline typename mpl::front::type bigint_add2_nc( + typename mpl::front::type x[], size_t x_size, + const typename mpl::front::type y[], size_t y_size) +{ + typedef typename mpl::front::type ui_type; + + ui_type carry = 0; + + BOOST_ASSERT_MSG(x_size >= y_size, "Expected sizes"); + + const size_t blocks = y_size - (y_size % 8); + + for (size_t i = 0; i != blocks; i += 8) + carry = word8_add2(x + i, y + i, carry); + + for (size_t i = blocks; i != y_size; ++i) + x[i] = word_add(x[i], y[i], &carry); + + for (size_t i = y_size; i != x_size; ++i) + x[i] = word_add(x[i], 0, &carry); + + return carry; +} + +template +inline typename mpl::front::type bigint_cnd_sub( + typename mpl::front::type cnd, + typename mpl::front::type x[], size_t x_size, + const typename mpl::front::type y[], size_t y_size) +{ + BOOST_ASSERT_MSG(x_size >= y_size, "Expected sizes"); + + typedef typename mpl::front::type ui_type; + + const auto mask = CT::Mask::expand(cnd); + + ui_type carry = 0; + + const size_t blocks = y_size - (y_size % 8); + ui_type z[8] = {0}; + + for (size_t i = 0; i != blocks; i += 8) + { + carry = word8_sub3(z, x + i, y + i, carry); + mask.select_n(x + i, z, x + i, 8); + } + + for (size_t i = blocks; i != y_size; ++i) + { + z[0] = word_sub(x[i], y[i], &carry); + x[i] = mask.select(z[0], x[i]); + } + + for (size_t i = y_size; i != x_size; ++i) + { + z[0] = word_sub(x[i], 0, &carry); + x[i] = mask.select(z[0], x[i]); + } + + return mask.if_set_return(carry); +} + +template +inline typename mpl::front::type bigint_cnd_add( + typename mpl::front::type cnd, + typename mpl::front::type x[], + typename mpl::front::type x_size, + const typename mpl::front::type y[], size_t y_size) +{ + BOTAN_ASSERT(x_size >= y_size, "Expected sizes"); + + typedef typename mpl::front::type ui_type; + + const auto mask = CT::Mask::expand(cnd); + + ui_type carry = 0; + + const size_t blocks = y_size - (y_size % 8); + ui_type z[8] = {0}; + + for (size_t i = 0; i != blocks; i += 8) + { + carry = word8_add3(z, x + i, y + i, carry); + mask.select_n(x + i, z, x + i, 8); + } + + for (size_t i = blocks; i != y_size; ++i) + { + z[0] = word_add(x[i], y[i], &carry); + x[i] = mask.select(z[0], x[i]); + } + + for (size_t i = y_size; i != x_size; ++i) + { + z[0] = word_add(x[i], 0, &carry); + x[i] = mask.select(z[0], x[i]); + } + + return mask.if_set_return(carry); +} + +template +inline void bigint_cnd_abs(typename mpl::front::type cnd, + typename mpl::front::type x[], size_t size) +{ + typedef typename mpl::front::type ui_type; + const auto mask = CT::Mask::expand(cnd); + + ui_type carry = mask.if_set_return(1); + for (size_t i = 0; i != size; ++i) + { + const ui_type z = word_add(~x[i], 0, &carry); + x[i] = mask.select(z, x[i]); + } +} + +template +inline void bigint_cnd_swap(typename mpl::front::type cnd, + typename mpl::front::type x[], + typename mpl::front::type y[], size_t size) +{ + typedef typename mpl::front::type ui_type; + const auto mask = CT::Mask::expand(cnd); + + for (size_t i = 0; i != size; ++i) + { + const ui_type a = x[i]; + const ui_type b = y[i]; + x[i] = mask.select(b, a); + y[i] = mask.select(a, b); + } +} + + +template +void eval_inverse_mod_odd_modulus(Backend& res, const Backend& n, const Backend& mod) +{ + typedef typename mpl::front::type si_type; + typedef typename mpl::front::type ui_type; + + // Caller should assure these preconditions: + BOOST_ASSERT(eval_gt(n, 0)); + BOOST_ASSERT(eval_gt(mod, 0)); + BOOST_ASSERT(eval_lt(n, mod)); + BOOST_ASSERT(eval_ge(mod, 3) && eval_modulus(mod, 2) == 1); + + /* + This uses a modular inversion algorithm designed by Niels Möller + and implemented in Nettle. The same algorithm was later also + adapted to GMP in mpn_sec_invert. + It can be easily implemented in a way that does not depend on + secret branches or memory lookups, providing resistance against + some forms of side channel attack. + There is also a description of the algorithm in Appendix 5 of "Fast + Software Polynomial Multiplication on ARM Processors using the NEON Engine" + by Danilo Câmara, Conrado P. L. Gouvêa, Julio López, and Ricardo + Dahab in LNCS 8182 + https://conradoplg.cryptoland.net/files/2010/12/mocrysen13.pdf + Thanks to Niels for creating the algorithm, explaining some things + about it, and the reference to the paper. + */ +/* + const size_t mod_words = mod.size(); + BOOST_ASSERT_MSG(mod_words > 0, "Not empty"); + + std::vector tmp_mem(5 * mod_words); + + ui_type* v_w = &tmp_mem[0]; + ui_type* u_w = &tmp_mem[1 * mod_words]; + ui_type* b_w = &tmp_mem[2 * mod_words]; + ui_type* a_w = &tmp_mem[3 * mod_words]; + ui_type* mp1o2 = &tmp_mem[4 * mod_words]; + + // ct::poison(tmp_mem.data(), tmp_mem.size()); + + copy_mem(a_w, n.data(), std::min(n.size(), mod_words)); + copy_mem(b_w, mod.data(), std::min(mod.size(), mod_words)); + u_w[0] = 1; + // v_w = 0 + + // compute (mod + 1) / 2 which [because mod is odd] is equal to + // (mod / 2) + 1 + copy_mem(mp1o2, mod.data(), std::min(mod.size(), mod_words)); + bigint_shr1(mp1o2, mod_words, 0, 1); + ui_type carry = bigint_add2_nc(mp1o2, mod_words, u_w, 1); + BOOST_ASSERT(carry == 0); + + // Only n.bits() + mod.bits() iterations are required, but avoid leaking the size of n + const size_t execs = 2 * eval_msb(mod); + + for (size_t i = 0; i != execs; ++i) + { + const ui_type odd_a = a_w[0] & 1; + + //if(odd_a) a -= b + ui_type underflow = bigint_cnd_sub(odd_a, a_w, b_w, mod_words); + + //if(underflow) { b -= a; a = abs(a); swap(u, v); } + bigint_cnd_add(underflow, b_w, a_w, mod_words); + bigint_cnd_abs(underflow, a_w, mod_words); + bigint_cnd_swap(underflow, u_w, v_w, mod_words); + + // a >>= 1 + bigint_shr1(a_w, mod_words, 0, 1); + + //if(odd_a) u -= v; + ui_type borrow = bigint_cnd_sub(odd_a, u_w, v_w, mod_words); + + // if(borrow) u += p + bigint_cnd_add(borrow, u_w, mod.data(), mod_words); + + const ui_type odd_u = u_w[0] & 1; + + // u >>= 1 + bigint_shr1(u_w, mod_words, 0, 1); + + //if(odd_u) u += mp1o2; + bigint_cnd_add(odd_u, u_w, mp1o2, mod_words); + } + + auto a_is_0 = CT::Mask::set(); + for (size_t i = 0; i != mod_words; ++i) + a_is_0 &= CT::Mask::is_zero(a_w[i]); + + auto b_is_1 = CT::Mask::is_equal(b_w[0], 1); + for (size_t i = 1; i != mod_words; ++i) + b_is_1 &= CT::Mask::is_zero(b_w[i]); + + BOOST_ASSERT_MSG(a_is_0.is_set(), "A is zero"); + + // if b != 1 then gcd(n,mod) > 1 and inverse does not exist + // in which case zero out the result to indicate this + (~b_is_1).if_set_zero_out(v_w, mod_words); + + /* + * We've placed the result in the lowest words of the temp buffer. + * So just clear out the other values and then give that buffer to a + * BigInt. + */ +/* + clear_mem(&tmp_mem[mod_words], 4 * mod_words); + + CT::unpoison(tmp_mem.data(), tmp_mem.size()); + + Backend r; + r.swap_reg(tmp_mem); + return r; +} + +/* +template +void inverse_mod_odd_modulus(number& res, + const number& n, + const number& mod) +{ + eval_inverse_mod_odd_modulus(res.backend(), n.backend(), mod.backend()); +} + */ + +/* +template +std::size_t eval_almost_montgomery_inverse(Backend& result, const Backend& a, + const Backend& p) +{ + size_t k = 0; + + Backend u = p, v = a, r = 0, s = 1; + + while (eval_gt(v, 0)) + { + if (eval_integer_modulus(u, 2) == 0) + { + eval_right_shift(u, 1); + eval_left_shift(s, 1); + } + else if (eval_integer_modulus(v, 2) == 0) + { + eval_right_shift(v, 1); + eval_left_shift(r, 1); + } + else if (eval_gt(u, v)) + { + eval_subtract(u, v); + eval_right_shift(u, 1); + eval_add(r, s); + eval_left_shift(s, 1); + } + else + { + eval_subtract(v, u); + eval_right_shift(v, 1); + eval_add(s, r); + eval_left_shift(r, 1); + } + + k++; + } + + if (!eval_gt(p, r)) + { + eval_subtract(r, p); + } + + result = p; + + eval_subtract(result, r); + + return k; +} +*/ + +/* +template +std::size_t almost_montgomery_inverse(number& result, + const number& a, + const number& p) +{ + return eval_almost_montgomery_inverse(result.backend(), a.backend(), p.backend()); +} +*/ + +/* +template +Backend eval_normalized_montgomery_inverse(const Backend& a, const Backend& p) +{ + Backend r; + std::size_t k = eval_almost_montgomery_inverse(r, a, p); + + for (std::size_t i = 0; i != k; ++i) + { + if (eval_integer_modulus(p, 2) == 1) + { + eval_add(r, p); + } + eval_right_shift(r, 1); + } + + return r; +} +*/ + +/* +template +number normalized_montgomery_inverse( + const number& a, + const number& p) +{ + return number( + evaL_normalized_montgomery_inverse(a.backned(), p.backend())); +} + */ + +/* +template +Backend eval_inverse_mod_pow2(Backend& a1, size_t k) +{ + typedef typename mpl::front::type ui_type; + /* + * From "A New Algorithm for Inversion mod p^k" by Çetin Kaya Koç + * https://eprint.iacr.org/2017/411.pdf sections 5 and 7. + */ +/* + if (eval_integer_modulus(a1, 2) == 0) + return 0; + + Backend a = a1; + eval_bit_set(a, k); + + Backend b = 1, X = 0, newb; + + const std::size_t a_words = a.sig_words(); + + X.grow_to(round_up(k, sizeof(ui_type) * CHAR_BIT) / sizeof(ui_type) * CHAR_BIT); + b.grow_to(a_words); + + /* + Hide the exact value of k. k is anyway known to word length + granularity because of the length of a, so no point in doing more + than this. + */ +/* + + const std::size_t iter = round_up(k, sizeof(ui_type) * CHAR_BIT); + + for (std::size_t i = 0; i != iter; ++i) + { + const bool b0 = eval_bit_test(b, 0); + X.conditionally_set_bit(i, b0); + newb = b; + eval_subtract(newb, a); + b.ct_cond_assign(b0, newb); + eval_right_shift(b, 1); + } + eval_bit_set(X, k); + X.const_time_unpoison(); + return X; +} +*/ + +/* +template +number inverse_mod_pow2( + const number& a1, size_t k) +{ + return number( + eval_inverse_mod_pow2(a1.backend(), k.backend())); +} +*/ + +/* +template +Backend eval_inverse_mod(Backend& res, const Backend& n, const Backend& mod) +{ + if (eval_is_zero(mod)) + { + BOOST_THROW_EXCEPTION( + std::invalid_argument("eval_inverse_mod: mod must be non zero")); + } + if ((eval_get_sign(mod) < 0) || (eval_get_sign(n) < 0)) + { + BOOST_THROW_EXCEPTION( + std::invalid_argument("eval_inverse_mod: arguments must be non-negative")); + } + if (eval_is_zero(n) || (eval_integer_modulus(n, 2) == 0 && eval_integer_modulus(mod, 2) == 0)) + { + return 0; + } + if (eval_integer_modulus(n, 2) == 1) + { + /* + Fastpath for common case. This leaks information if n > mod + but we don't guarantee const time behavior in that case. + */ +/* + if (eval_gt(mod, n)) + return eval_inverse_mod_odd_modulus(n, mod); + else + return eval_inverse_mod_odd_modulus(ct_modulo(n, mod), mod); + } + + const std::size_t mod_lz = eval_lsb(mod); + BOOST_ASSERT(mod_lz > 0); + const std::size_t mod_bits = eval_msb(mod); + BOOST_ASSERT(mod_bits > mod_lz); + + if (mod_lz == mod_bits - 1) + { + // In this case we are performing an inversion modulo 2^k + return eval_inverse_mod_pow2(n, mod_lz); + } + + /* + * In this case we are performing an inversion modulo 2^k*o for + * some k > 1 and some odd (not necessarily prime) integer. + * Compute the inversions modulo 2^k and modulo o, then combine them + * using CRT, which is possible because 2^k and o are relatively prime. + */ +/* + Backend o = mod; + + eval_right_shift(mod, mod_lz); + + Backend n_redc = ct_modulo(n, o); + Backend inv_o = eval_inverse_mod_odd_modulus(n_redc, o); + Backend inv_2k = eval_inverse_mod_pow2(n, mod_lz); + + // No modular inverse in this case: + if (eval_is_zero(o) || eval_is_zero(inv_2k)) + return 0; + + Backend m2k = mod_lz; + eval_multiply(m2k, m2k); + // Compute the CRT parameter + Backend c = inverse_mod_pow2(o, mod_lz); + + // Compute h = c*(inv_2k-inv_o) mod 2^k + Backend h = inv_2k; + + eval_subtract(h, inv_o); + eval_multiply(h, c); + + const bool h_neg = (eval_get_sign(h) < 0); + + eval_abs(h); // h.set_sign(BigInt::Positive); + eval_bit_set(h, mod_lz); + + const bool h_nonzero = !eval_is_zero(h); + + eval_subtracr(m2k, h); + h.ct_cond_assign(h_nonzero && h_neg, m2k); + + // Return result inv_o + h * o + eval_multiply(h, o); + eval_add(h, inv_o); + + return h; +} +*/ +} +} +} // namespace boost::multiprecision::backends + +#endif + diff --git a/include/boost/multiprecision/modular/modular_adaptor.hpp b/include/boost/multiprecision/modular/modular_adaptor.hpp new file mode 100644 index 000000000..34d45b539 --- /dev/null +++ b/include/boost/multiprecision/modular/modular_adaptor.hpp @@ -0,0 +1,539 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2020 Mikhail Komarov +// Copyright (c) 2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef BOOST_MULTIPRECISION_MODULAR_ADAPTOR_HPP +#define BOOST_MULTIPRECISION_MODULAR_ADAPTOR_HPP + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace boost { +namespace multiprecision { +namespace backends { + +template +class modular_adaptor +{ + protected: + Backend m_base; + modular_params m_mod; + + public: + inline Backend& base_data() { return m_base; } + + inline Backend const& base_data() const { return m_base; } + + inline modular_params& mod_data() { return m_mod; } + + inline const modular_params& mod_data() const { return m_mod; } + + typedef typename Backend::signed_types signed_types; + typedef typename Backend::unsigned_types unsigned_types; + + modular_adaptor() {} + + modular_adaptor(const modular_adaptor& o) : m_base(o.base_data()), m_mod(o.mod_data()) + { + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + modular_adaptor(modular_adaptor&& o) + : m_base(std::move(o.base_data())), m_mod(std::move(o.mod_data())) + {} + +#endif + modular_adaptor(const Backend& val, const modular_params& mod) : m_mod(mod), m_base(mod.create_internal_representation(val)) + { + + } + + modular_adaptor(const Backend& val, const Backend& mod) + : m_base(val), m_mod(mod) + { + } + + modular_adaptor(Backend& val, Backend& mod) + : m_base(val), m_mod(mod) {} + + modular_adaptor(const Backend& val) : m_base(val), m_mod(typename mpl::front::type(0u)) + { + } + + modular_adaptor(const modular_params& mod) : m_base(typename mpl::front::type(0u)), m_mod(mod) + { + } + + modular_adaptor& operator=(const modular_adaptor& o) + { + m_base = o.base_data(); + m_mod = o.mod_data(); + return *this; + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + modular_adaptor& operator=(modular_adaptor&& o) + + BOOST_NOEXCEPT + { + m_base = std::move(o.base_data()); + m_mod = std::move(o.mod_data()); + return *this; + } +#endif + + modular_adaptor& operator=(const char* s) + { + typedef typename mpl::front::type ui_type; + ui_type zero = 0u; + + using default_ops::eval_fpclassify; + + if (s && (*s == '(')) + { + std::string part; + const char* p = ++s; + while (*p && (*p != ',') && (*p != ')')) + ++p; + part.assign(s, p); + if (!part.empty()) + m_base() = part.c_str(); + else + m_base() = zero; + s = p; + if (*p && (*p != ')')) + { + ++p; + while (*p && (*p != ')')) + ++p; + part.assign(s + 1, p); + } + else + part.erase(); + if (!part.empty()) + m_mod() = part.c_str(); + else + m_mod() = zero; + } + else + { + base_data() = s; + m_mod() = zero; + } + return *this; + } + + int compare(const modular_adaptor& o) const + { + // They are either equal or not:< + if (m_mod.compare(o.mod_data()) != 0) + { + BOOST_THROW_EXCEPTION(std::runtime_error("Could not compare modular number with different mod.")); + } + Backend tmp1, tmp2; + mod_data().adjust_regular(tmp1, base_data()); + mod_data().adjust_regular(tmp2, o.base_data()); + return tmp1.compare(tmp2); + } + + template + int compare(const T& val) const + { + using default_ops::eval_lt; + if (!eval_lt(m_mod, val)) + { + BOOST_THROW_EXCEPTION(std::runtime_error("Could not compare modular number with mod bigger than compared number.")); + } + Backend tmp; + mod_data().adjust_regular(tmp, base_data()); + return tmp.compare(val); + } + + inline void swap(modular_adaptor& o) + { + base_data().swap(o.base_data()); + std::swap(mod_data(), o.mod_data()); + } + + inline std::string str(std::streamsize dig, std::ios_base::fmtflags f) const + { + Backend tmp; + mod_data().adjust_regular(tmp, base_data()); + return tmp.str(dig, f); + } + + inline void negate() + { + base_data().negate(); + eval_add(base_data(), mod_data().get_mod().backend()); + } + + template + operator number() + { + return base_data(); + }; +}; + +template +inline void eval_convert_to(Result* result, const modular_adaptor& val) +{ + using default_ops::eval_convert_to; + eval_convert_to(result, val.base_data()); +} + +template +inline typename enable_if, bool> + + ::type eval_eq(const modular_adaptor& a, + const T& b) + + BOOST_NOEXCEPT +{ + return a.compare(b) == 0; +} + +template +inline void eval_redc(Backend& result, const modular_params& mod) +{ + mod.reduce(result); +} + +template +inline void eval_add(modular_adaptor& result, + const modular_adaptor& o) +{ + BOOST_ASSERT(result.mod_data().get_mod() == o.mod_data().get_mod()); + using default_ops::eval_gt; + eval_add(result.base_data(), o.base_data()); + if (eval_gt(result.base_data(), result.mod_data().get_mod().backend())) + { + eval_subtract(result.base_data(), result.mod_data().get_mod().backend()); + } +} + +template +inline void eval_subtract(modular_adaptor& result, const modular_adaptor& o) +{ + BOOST_ASSERT(result.mod_data().get_mod() == o.mod_data().get_mod()); + typedef typename mpl::front::type ui_type; + using default_ops::eval_lt; + eval_subtract(result.base_data(), o.base_data()); + if (eval_lt(result.base_data(), ui_type(0u))) + { + eval_add(result.base_data(), result.mod_data().get_mod().backend()); + } +} + +template +inline void eval_multiply(modular_adaptor& result, const modular_adaptor& o) +{ + BOOST_ASSERT(result.mod_data().get_mod() == o.mod_data().get_mod()); + eval_multiply(result.base_data(), o.base_data()); + eval_redc(result.base_data(), result.mod_data()); +} + +template +inline void eval_divide(modular_adaptor& result, const modular_adaptor& o) +{ + BOOST_ASSERT(result.mod_data().get_mod() == o.mod_data().get_mod()); + Backend tmp1, tmp2; + result.mod_data().adjust_regular(tmp1, result.base_data()); + result.mod_data().adjust_regular(tmp2, o.base_data()); + eval_divide(tmp1, tmp2); + result.base_data() = tmp1; + result.mod_data().adjust_modular(result.base_data()); + result.mod_data().adjust_regular(tmp2, result.base_data()); +} + +template +inline void eval_modulus(modular_adaptor& result, const modular_adaptor& o) +{ + BOOST_ASSERT(result.mod_data().get_mod() == o.mod_data().get_mod()); + Backend tmp1, tmp2; + result.mod_data().adjust_regular(tmp1, result.base_data()); + result.mod_data().adjust_regular(tmp2, o.base_data()); + eval_modulus(tmp1, tmp2); + result.base_data() = tmp1; + result.mod_data().adjust_modular(result.base_data()); + result.mod_data().adjust_regular(tmp2, result.base_data()); +} + +template +inline bool eval_is_zero(const modular_adaptor& val) + + BOOST_NOEXCEPT +{ + using default_ops::eval_is_zero; + return eval_is_zero(val.base_data()); +} + +template +inline int eval_get_sign(const modular_adaptor&) +{ + return 1; +} + +template +inline typename disable_if_c::value>::type +eval_convert_to(Result* result, const modular_adaptor& val) +{ + using default_ops::eval_convert_to; + eval_convert_to(result, val.base_data()); +} + +template +inline void assign_components(modular_adaptor& result, + const T& a, const V& b) +{ + result.base_data() = a; + result.mod_data() = b; + result.mod_data().adjust_modular(result.base_data()); +} + +template +inline void eval_sqrt(modular_adaptor& result, + const modular_adaptor& val) +{ + eval_sqrt(result.base_data(), val.base_data()); +} + +template +inline void eval_abs(modular_adaptor& result, const modular_adaptor& val) +{ + result = val; +} + +size_t window_bits(size_t exp_bits) +{ + BOOST_STATIC_CONSTEXPR size_t wsize_count = 6; + BOOST_STATIC_CONSTEXPR size_t wsize[wsize_count][2] = { + {1434, 7}, + {539, 6}, + {197, 4}, + {70, 3}, + {17, 2}, + {0, 0}}; + + size_t window_bits = 1; + + size_t j = wsize_count - 1; + while (wsize[j][0] > exp_bits) + { + --j; + } + window_bits += wsize[j][1]; + + return window_bits; +}; + +template +inline void find_modular_pow(modular_adaptor& result, + const modular_adaptor& b, + Backend& exp) +{ + // using default_ops::eval_bit_test; + // using default_ops::eval_gt; + // typedef typename boost::multiprecision::detail::canonical::type ui_type; + // typedef number > modular_type; + // modular_params mod = b.mod_data(); + // modular_type x(1, mod); + // modular_type y = b; + // while (eval_gt(exp, ui_type(0u))) + // { + // if (eval_bit_test(exp, ui_type(0u))) + // { + // x = x * y; + // } + // y = y * y; + // eval_right_shift(exp, ui_type(1u)); + // } + // result = x.backend(); + + using default_ops::eval_bit_set; + using default_ops::eval_decrement; + using default_ops::eval_multiply; + using default_ops::eval_convert_to; + + typedef number > modular_type; + modular_params mod = b.mod_data(); + size_t m_window_bits; + unsigned long cur_exp_index; + size_t exp_bits = eval_msb(exp); + m_window_bits = window_bits(exp_bits + 1); + + std::vector m_g(1U << m_window_bits); + modular_type* p_g = m_g.data(); + modular_type x(1, mod); + Backend nibble = exp; + Backend mask; + eval_bit_set(mask, m_window_bits); + eval_decrement(mask); + *p_g = x; + ++p_g; + *p_g = b; + ++p_g; + for (size_t i = 2; i < (1U << m_window_bits); i++) + { + eval_multiply((*p_g).backend(), m_g[i - 1].backend(), b); + ++p_g; + } + size_t exp_nibbles = (exp_bits + 1 + m_window_bits - 1) / m_window_bits; + std::vector exp_index; + + for (size_t i = 0; i < exp_nibbles; ++i) + { + Backend tmp = nibble; + eval_bitwise_and(tmp, mask); + eval_convert_to(&cur_exp_index, tmp); + eval_right_shift(nibble, m_window_bits); + exp_index.push_back(cur_exp_index); + } + + x = x * m_g[exp_index[exp_nibbles - 1]]; + for (size_t i = exp_nibbles - 1; i > 0; --i) + { + + for (size_t j = 0; j != m_window_bits; ++j) + { + x = x * x; + } + + x = x * m_g[exp_index[i - 1]]; + } + result = x.backend(); +} + +template +inline void eval_pow(modular_adaptor& result, + const modular_adaptor& b, + const modular_adaptor& e) +{ + Backend exp; + e.mod_data().adjust_regular(exp, e.base_data()); + find_modular_pow(result, b, exp); +} + +template +inline void eval_pow(modular_adaptor& result, + const modular_adaptor& b, + const Backend& e) +{ + Backend exp = e; + find_modular_pow(result, b, exp); +} + +template +inline void eval_left_shift(modular_adaptor& t, UI i) +{ + using default_ops::eval_left_shift; + Backend tmp; + t.mod_data().adjust_regular(tmp, t.base_data()); + eval_left_shift(tmp, i); + t.base_data() = tmp; + t.mod_data().adjust_modular(t.base_data()); +} +template +inline void eval_right_shift(modular_adaptor& t, UI i) +{ + using default_ops::eval_right_shift; + Backend tmp; + t.mod_data().adjust_regular(tmp, t.base_data()); + eval_right_shift(tmp, i); + t.base_data() = tmp; + t.mod_data().adjust_modular(t.base_data()); +} +template +inline void eval_left_shift(modular_adaptor& t, const modular_adaptor& v, UI i) +{ + using default_ops::eval_left_shift; + Backend tmp1, tmp2; + t.mod_data().adjust_regular(tmp1, t.base_data()); + t.mod_data().adjust_regular(tmp2, v.base_data()); + eval_left_shift(tmp1, tmp2, static_cast(i)); + t.base_data() = tmp1; + t.mod_data().adjust_modular(t.base_data()); +} +template +inline void eval_right_shift(modular_adaptor& t, const modular_adaptor& v, UI i) +{ + using default_ops::eval_right_shift; + Backend tmp1, tmp2; + t.mod_data().adjust_regular(tmp1, t.base_data()); + t.mod_data().adjust_regular(tmp2, v.base_data()); + eval_right_shift(tmp1, tmp2, static_cast(i)); + t.base_data() = tmp1; + t.mod_data().adjust_modular(t.base_data()); +} + +template +inline void eval_bitwise_and(modular_adaptor& result, const modular_adaptor& v) +{ + using default_ops::eval_bitwise_and; + Backend tmp1, tmp2; + result.mod_data().adjust_regular(tmp1, result.base_data()); + result.mod_data().adjust_regular(tmp2, v.base_data()); + eval_bitwise_and(tmp1, tmp1, tmp2); + result.base_data() = tmp1; + result.mod_data().adjust_modular(result.base_data()); +} + +template +inline void eval_bitwise_or(modular_adaptor& result, const modular_adaptor& v) +{ + using default_ops::eval_bitwise_or; + Backend tmp1, tmp2; + result.mod_data().adjust_regular(tmp1, result.base_data()); + result.mod_data().adjust_regular(tmp2, v.base_data()); + eval_bitwise_or(tmp1, tmp1, tmp2); + result.base_data() = tmp1; + result.mod_data().adjust_modular(result.base_data()); +} + +template +inline void eval_bitwise_xor(modular_adaptor& result, const modular_adaptor& v) +{ + using default_ops::eval_bitwise_xor; + Backend tmp1, tmp2; + result.mod_data().adjust_regular(tmp1, result.base_data()); + result.mod_data().adjust_regular(tmp2, v.base_data()); + eval_bitwise_xor(tmp1, tmp1, tmp2); + result.base_data() = tmp1; + result.mod_data().adjust_modular(result.base_data()); +} + +} // namespace backends + +using boost::multiprecision::backends::modular_adaptor; + +template +struct number_category > : public boost::mpl::int_ +{}; + +template +struct component_type, ExpressionTemplates> > +{ + typedef number type; +}; + +} + +} // namespace boost::multiprecision + +#endif diff --git a/include/boost/multiprecision/modular/modular_params.hpp b/include/boost/multiprecision/modular/modular_params.hpp new file mode 100644 index 000000000..ea5f1b9ad --- /dev/null +++ b/include/boost/multiprecision/modular/modular_params.hpp @@ -0,0 +1,111 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2020 Mikhail Komarov +// Copyright (c) 2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef BOOST_MULTIPRECISION_MODULAR_PARAMS_HPP +#define BOOST_MULTIPRECISION_MODULAR_PARAMS_HPP + +#include +#include + +namespace boost { +namespace multiprecision { + +template +class modular_params : public backends::montgomery_params, public backends::barrett_params +{ + typedef number number_type; + + public: + modular_params() : backends::montgomery_params(), backends::barrett_params() {} + + template + explicit modular_params(const Number& p) : backends::montgomery_params(number_type(p)), backends::barrett_params(number_type(p)) + { + } + + modular_params& operator=(const modular_params& v) + { + backends::montgomery_params::m_mod = v.get_mod(); + backends::barrett_params::m_mod = v.get_mod(); + + this->m_mu = v.mu(); + + this->m_r2 = v.r2(); + this->m_p_dash = v.p_dash(); + this->m_p_words = v.p_words(); + + return *this; + } + + template + modular_params& operator=(const Number& v) + { + number_type tmp(v); + this->initialize_barrett_params(tmp); + this->initialize_montgomery_params(tmp); + return *this; + } + + void reduce(Backend& result) const + { + if (get_mod() % 2 == 0) + { + this->eval_barret_reduce(result); + } + else + { + this->eval_montgomery_reduce(result); + } + } + + void adjust_modular(Backend& result) + { + this->eval_barret_reduce(result); + if (get_mod() % 2 != 0) + { + eval_multiply(result, this->r2().backend()); + this->eval_montgomery_reduce(result); + } + } + + void adjust_regular(Backend& result, const Backend& input) const + { + result = input; + if (get_mod() % 2 != 0) + { + this->eval_montgomery_reduce(result); + } + } + + number_type get_mod() const + { + return backends::montgomery_params::mod() | backends::barrett_params::mod(); + } + + template + operator number() + { + return get_mod(); + }; + + int compare(const modular_params& o) const + { + // They are either equal or not: + return (get_mod().compare(o.get_mod())); + } + + friend std::ostream& operator<<(std::ostream& o, modular_params const& a) + { + o << a.get_mod(); + return o; + } +}; +} +} // namespace boost::multiprecision +#endif //_MULTIPRECISION_MODULAR_PARAMS_HPP diff --git a/include/boost/multiprecision/modular/modular_params_gmp.hpp b/include/boost/multiprecision/modular/modular_params_gmp.hpp new file mode 100644 index 000000000..1ed457a54 --- /dev/null +++ b/include/boost/multiprecision/modular/modular_params_gmp.hpp @@ -0,0 +1,89 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2020 Mikhail Komarov +// Copyright (c) 2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef BOOST_MULTIPRECISION_MODULAR_ADAPTOR_GMP_HPP +#define BOOST_MULTIPRECISION_MODULAR_ADAPTOR_GMP_HPP + +#include +#include +#include + +namespace boost { +namespace multiprecision { + +template +class modular_params; + +template <> +class modular_params : public backends::base_params +{ + typedef number number_type; + + public: + modular_params() : backends::base_params(){}; + + template + explicit modular_params(const Number& p) : backends::base_params(number_type(p)) + { + } + + modular_params& operator=(const modular_params& v) { + backends::base_params::m_mod = v.get_mod(); + return *this; + } + + template + modular_params& operator=(const Number& v) + { + number_type tmp(v); + this->initialize_base_params(tmp); + return *this; + } + + inline void reduce(gmp_int& result) const + { + mpz_mod(result.data(), result.data(), get_mod().backend().data()); + } + + inline void adjust_modular(gmp_int& result) + { + mpz_mod(result.data(), result.data(), get_mod().backend().data()); + } + + inline void adjust_regular(gmp_int& result, const gmp_int& input) const + { + result = input; + } + + inline number_type get_mod() const + { + return base_params::mod(); + } + + template + inline operator number() + { + return this->m_mod; + }; + + inline int compare(const modular_params& o) const + { + // They are either equal or not: + return (get_mod().compare(o.mod())); + } + + friend std::ostream& operator<<(std::ostream& o, modular_params const& a) + { + o << a.get_mod(); + return o; + } +}; +} +} // namespace boost::multiprecision +#endif //BOOST_MULTIPRECISION_MODULAR_ADAPTOR_GMP_HPP diff --git a/include/boost/multiprecision/modular/modular_params_tommath.hpp b/include/boost/multiprecision/modular/modular_params_tommath.hpp new file mode 100644 index 000000000..3a7d99f92 --- /dev/null +++ b/include/boost/multiprecision/modular/modular_params_tommath.hpp @@ -0,0 +1,89 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2020 Mikhail Komarov +// Copyright (c) 2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef BOOST_MULTIPRECISION_MODULAR_ADAPTOR_TOMMATH_HPP +#define BOOST_MULTIPRECISION_MODULAR_ADAPTOR_TOMMATH_HPP + +#include +#include +#include + +namespace boost { +namespace multiprecision { + +template +class modular_params; + +template <> +class modular_params : public backends::base_params +{ + typedef number number_type; + + public: + modular_params() : backends::base_params(){}; + + template + explicit modular_params(const Number& p) : backends::base_params(number_type(p)) + { + } + + modular_params& operator=(const modular_params& v) { + backends::base_params::m_mod = v.get_mod(); + return *this; + } + + template + modular_params& operator=(const Number& v) + { + number_type tmp(v); + this->initialize_base_params(tmp); + return *this; + } + + inline void reduce(tommath_int& result) const + { + backends::detail::check_tommath_result(mp_mod(const_cast< ::mp_int*>(&result.data()), const_cast< ::mp_int*>(&get_mod().backend().data()), &result.data())); + } + + inline void adjust_modular(tommath_int& result) + { + backends::detail::check_tommath_result(mp_mod(const_cast< ::mp_int*>(&result.data()), const_cast< ::mp_int*>(&get_mod().backend().data()), &result.data())); + } + + inline void adjust_regular(tommath_int& result, const tommath_int& input) const + { + result = input; + } + + inline number_type get_mod() const + { + return base_params::mod(); + } + + template + operator number() + { + return this->m_mod; + }; + + inline int compare(const modular_params& o) const + { + // They are either equal or not: + return (get_mod().compare(o.mod())); + } + + friend std::ostream& operator<<(std::ostream& o, modular_params const& a) + { + o << a.get_mod(); + return o; + } +}; +} +} // namespace boost::multiprecision +#endif //_MULTIPRECISION_MODULAR_ADAPTOR_TOMMATH_HPP diff --git a/include/boost/multiprecision/modular/montgomery_params.hpp b/include/boost/multiprecision/modular/montgomery_params.hpp new file mode 100644 index 000000000..96ce29787 --- /dev/null +++ b/include/boost/multiprecision/modular/montgomery_params.hpp @@ -0,0 +1,175 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2020 Mikhail Komarov +// Copyright (c) 2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef BOOST_MULTIPRECISION_MONTGOMERY_PARAMS_HPP +#define BOOST_MULTIPRECISION_MONTGOMERY_PARAMS_HPP + +#include + +#include + +#include +#include +#include +#include +#include + +namespace boost { +namespace multiprecision { +namespace backends { +/** + * Parameters for Montgomery Reduction + */ +template +class montgomery_params : public base_params +{ + typedef number number_type; + + typedef typename mpl::front::type ui_type; + + protected: + template + inline void initialize_montgomery_params(const Number& p) + { + this->initialize_base_params(p); + find_const_variables(p); + } + + inline void initialize_montgomery_params(const montgomery_params& p) + { + this->initialize_base_params(p); + find_const_variables(p); + } + + template + void find_const_variables(const T& pp) + { + number_type p = pp; + if (p <= 0 || !(p % 2)) + { + return; + } + + m_p_words = this->m_mod.backend().size(); + + m_p_dash = monty_inverse(this->m_mod.backend().limbs()[0]); + + number_type r; + + default_ops::eval_bit_set(r.backend(), m_p_words * sizeof(limb_type) * CHAR_BIT); + + m_r2 = r * r; + barrett_params barrettParams(this->m_mod); + barrettParams.eval_barret_reduce(m_r2.backend()); + } + + public: + montgomery_params() : base_params() {} + + template + explicit montgomery_params(const Number& p) : base_params(p) + { + initialize_montgomery_params(p); + } + + inline const number_type& r2() const { return m_r2; } + + inline limb_type p_dash() const { return m_p_dash; } + + inline size_t p_words() const { return m_p_words; } + + template + montgomery_params& operator=(const V& v) + { + initialize_montgomery_params(v); + return *this; + } + + inline void eval_montgomery_reduce(Backend& result) const + { + using default_ops::eval_lt; + using default_ops::eval_multiply_add; + + typedef cpp_int_backend cpp_three_int_backend; + + const size_t p_size = m_p_words; + const limb_type p_dash = m_p_dash; + const size_t z_size = 2 * (p_words() + 1); + + container::vector z(result.size(), 0); //container::vector z(result.size(), 0); + for (size_t i = 0; i < result.size(); ++i) + { + z[i] = result.limbs()[i]; + } + + if (result.size() < z_size) + { + result.resize(z_size, z_size); + z.resize(z_size, 0); + } + + cpp_three_int_backend w(z[0]); + + result.limbs()[0] = w.limbs()[0] * p_dash; + + eval_multiply_add(w, result.limbs()[0], this->m_mod.backend().limbs()[0]); + eval_right_shift(w, sizeof(limb_type) * CHAR_BIT); + + for (size_t i = 1; i != p_size; ++i) + { + for (size_t j = 0; j < i; ++j) + { + eval_multiply_add(w, result.limbs()[j], this->m_mod.backend().limbs()[i - j]); + } + + eval_add(w, z[i]); + + result.limbs()[i] = w.limbs()[0] * p_dash; + + eval_multiply_add(w, result.limbs()[i], this->m_mod.backend().limbs()[0]); + + eval_right_shift(w, sizeof(limb_type) * CHAR_BIT); + } + + for (size_t i = 0; i != p_size; ++i) + { + for (size_t j = i + 1; j != p_size; ++j) + { + eval_multiply_add(w, result.limbs()[j], this->m_mod.backend().limbs()[p_size + i - j]); + } + + eval_add(w, z[p_size + i]); + + result.limbs()[i] = w.limbs()[0]; + + eval_right_shift(w, sizeof(limb_type) * CHAR_BIT); + } + + eval_add(w, z[z_size - 1]); + + result.limbs()[p_size] = w.limbs()[0]; + result.limbs()[p_size + 1] = w.limbs()[1]; + + if (result.size() != p_size + 1) + { + result.resize(p_size + 1, p_size + 1); + } + result.normalize(); + } + + protected: + number_type m_r2; + limb_type m_p_dash; + size_t m_p_words; +}; +} +} +} // namespace boost::multiprecision::backends + +#endif diff --git a/include/boost/multiprecision/number.hpp b/include/boost/multiprecision/number.hpp index e1272e5c8..dd642ee4e 100644 --- a/include/boost/multiprecision/number.hpp +++ b/include/boost/multiprecision/number.hpp @@ -1,7 +1,11 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright 2011 John Maddock. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// Copyright 2011 John Maddock +// Copyright (c) 2019 Mikhail Komarov +// Copyright (c) 2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_MATH_EXTENDED_REAL_HPP #define BOOST_MATH_EXTENDED_REAL_HPP @@ -56,11 +60,11 @@ class number BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number& e) BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval()))) : m_backend(e.m_backend) {} template BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v, typename boost::enable_if_c< - (boost::is_arithmetic::value || is_same::value || is_convertible::value) && !is_convertible::type, Backend>::value && !detail::is_restricted_conversion::type, Backend>::value + (boost::is_arithmetic::value || is_same::value || is_convertible::value) && !is_convertible::type, Backend>::value && !detail::is_restricted_conversion::type, Backend>::value #ifdef BOOST_HAS_FLOAT128 - && !boost::is_same::value + && !boost::is_same::value #endif - >::type* = 0) + >::type* = 0) { m_backend = canonical_value(v); } @@ -85,7 +89,7 @@ class number : m_backend(e.m_backend, digits10) {} template explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v, typename boost::enable_if_c< - (boost::is_arithmetic::value || is_same::value || is_convertible::value) && !detail::is_explicitly_convertible::type, Backend>::value && detail::is_restricted_conversion::type, Backend>::value>::type* = 0) + (boost::is_arithmetic::value || is_same::value || is_convertible::value) && !detail::is_explicitly_convertible::type, Backend>::value && detail::is_restricted_conversion::type, Backend>::value>::type* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval() = std::declval::type const&>())) { m_backend = canonical_value(v); @@ -105,13 +109,13 @@ class number template BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number& val, - typename boost::enable_if_c<(boost::is_convertible::value && !detail::is_restricted_conversion::value)>::type* = 0) + typename boost::enable_if_c<(boost::is_convertible::value && !detail::is_restricted_conversion::value)>::type* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval()))) : m_backend(val.backend()) {} template explicit BOOST_MP_CXX14_CONSTEXPR number(const number& val, typename boost::enable_if_c< - (!detail::is_explicitly_convertible::value)>::type* = 0) + (!detail::is_explicitly_convertible::value)>::type* = 0) { // // Attempt a generic interconvertion: @@ -123,12 +127,12 @@ class number } template explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number& val, typename boost::enable_if_c< - (detail::is_explicitly_convertible::value && (detail::is_restricted_conversion::value || !boost::is_convertible::value))>::type* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval()))) + (detail::is_explicitly_convertible::value && (detail::is_restricted_conversion::value || !boost::is_convertible::value))>::type* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval()))) : m_backend(val.backend()) {} template BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, - typename boost::enable_if_c<(is_convertible::value && is_convertible::value && !is_same::type, self_type>::value)>::type* = 0) + typename boost::enable_if_c<(is_convertible::value && is_convertible::value && !is_same::type, self_type>::value)>::type* = 0) { using default_ops::assign_components; detail::scoped_default_precision > precision_guard(v1, v2); @@ -136,8 +140,8 @@ class number } template BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, - typename boost::enable_if_c< - (is_constructible::value || is_convertible::value) && (is_constructible::value || is_convertible::value) && !is_same::type, self_type>::value && !is_same::value && !(is_convertible::value && is_convertible::value)>::type* = 0) + typename boost::enable_if_c< + (is_constructible::value || is_convertible::value) && (is_constructible::value || is_convertible::value) && !is_same::type, self_type>::value && !is_same::value && !(is_convertible::value && is_convertible::value)>::type* = 0) //(is_constructible::value || is_convertible::value) && (is_constructible::value || is_convertible::value) && !is_same::type, self_type>::value && !is_same::value && !(is_convertible::value && is_convertible::value)>::type* = 0) { using default_ops::assign_components; detail::scoped_default_precision > precision_guard(v1, v2); @@ -173,12 +177,12 @@ class number template BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10, - typename boost::enable_if_c<(is_convertible::value && is_convertible::value && !is_same::type, self_type>::value)>::type* = 0) + typename boost::enable_if_c<(is_convertible::value && is_convertible::value && !is_same::type, self_type>::value)>::type* = 0) : m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)), digits10) {} template BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10, - typename boost::enable_if_c<((is_constructible::value || is_convertible::value) && (is_constructible::value || is_convertible::value) && !is_same::type, self_type>::value) && !(is_convertible::value && is_convertible::value)>::type* = 0) + typename boost::enable_if_c<((is_constructible::value || is_convertible::value) && (is_constructible::value || is_convertible::value) && !is_same::type, self_type>::value) && !(is_convertible::value && is_convertible::value)>::type* = 0) : m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)), digits10) {} template @@ -193,7 +197,7 @@ class number BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::result_type, self_type>::value, number&>::type operator=(const detail::expression& e) { typedef mpl::bool_::result_type>::value> tag_type; - detail::scoped_default_precision > precision_guard(e); + detail::scoped_default_precision > precision_guard(e); // // If the current precision of *this differs from that of expression e, then we // create a temporary (which will have the correct precision thanks to precision_guard) @@ -216,7 +220,7 @@ class number BOOST_MP_CXX14_CONSTEXPR number& assign(const detail::expression& e) { typedef mpl::bool_::result_type>::value> tag_type; - detail::scoped_default_precision > precision_guard(e); + detail::scoped_default_precision > precision_guard(e); // // If the current precision of *this differs from that of expression e, then we // create a temporary (which will have the correct precision thanks to precision_guard) @@ -305,7 +309,7 @@ class number } template explicit BOOST_MP_CXX14_CONSTEXPR number(const detail::expression& e, - typename boost::enable_if_c::result_type, self_type>::value && boost::multiprecision::detail::is_explicitly_convertible::result_type, self_type>::value>::type* = 0) + typename boost::enable_if_c::result_type, self_type>::value && boost::multiprecision::detail::is_explicitly_convertible::result_type, self_type>::value>::type* = 0) { // // No precision guard as assign has one already: @@ -394,7 +398,8 @@ class number template typename boost::enable_if_c::value, number&>::type - BOOST_MP_CXX14_CONSTEXPR operator+=(const V& v) + BOOST_MP_CXX14_CONSTEXPR + operator+=(const V& v) { using default_ops::eval_add; eval_add(m_backend, canonical_value(v)); @@ -527,7 +532,7 @@ class number BOOST_MP_CXX14_CONSTEXPR number& operator%=(const self_type& e) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The modulus operation is only valid for integer and modular types"); detail::scoped_default_precision > precision_guard(*this, e); // // If the current precision of *this differs from that of expression e, then we @@ -550,7 +555,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::result_type, self_type>::value, number&>::type operator%=(const detail::expression& e) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The modulus operation is only valid for integer and modular types"); detail::scoped_default_precision > precision_guard(*this, e); // Create a temporary if the RHS references *this: if (contains_self(e)) @@ -568,7 +573,7 @@ class number BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value, number&>::type operator%=(const V& v) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The modulus operation is only valid for integer and modular types"); using default_ops::eval_modulus; eval_modulus(m_backend, canonical_value(v)); return *this; @@ -615,7 +620,7 @@ class number template BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value, number&>::type operator<<=(V val) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The left-shift operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The left-shift operation is only valid for integer and modular types"); detail::check_shift_range(val, mpl::bool_<(sizeof(V) > sizeof(std::size_t))>(), mpl::bool_::value>()); eval_left_shift(m_backend, static_cast(canonical_value(val))); return *this; @@ -624,7 +629,7 @@ class number template BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value, number&>::type operator>>=(V val) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The right-shift operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The right-shift operation is only valid for integer and modular types"); detail::check_shift_range(val, mpl::bool_<(sizeof(V) > sizeof(std::size_t))>(), mpl::bool_::value>()); eval_right_shift(m_backend, static_cast(canonical_value(val))); return *this; @@ -680,7 +685,7 @@ class number BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator&=(const self_type& e) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise & operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise & operation is only valid for integer and modular types"); do_bitwise_and(detail::expression(e), detail::terminal()); return *this; } @@ -688,7 +693,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::result_type, self_type>::value, number&>::type operator&=(const detail::expression& e) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise & operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise & operation is only valid for integer and modular types"); // Create a temporary if the RHS references *this, but not // if we're just doing an x &= x; if (contains_self(e) && !is_self(e)) @@ -707,7 +712,7 @@ class number BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value, number&>::type operator&=(const V& v) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise & operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise & operation is only valid for integer and modular types"); using default_ops::eval_bitwise_and; eval_bitwise_and(m_backend, canonical_value(v)); return *this; @@ -715,7 +720,7 @@ class number BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator|=(const self_type& e) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise | operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise | operation is only valid for integer and modular types"); do_bitwise_or(detail::expression(e), detail::terminal()); return *this; } @@ -723,7 +728,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::result_type, self_type>::value, number&>::type operator|=(const detail::expression& e) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise | operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise | operation is only valid for integer and modular types"); // Create a temporary if the RHS references *this, but not // if we're just doing an x |= x; if (contains_self(e) && !is_self(e)) @@ -742,7 +747,7 @@ class number BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value, number&>::type operator|=(const V& v) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise | operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise | operation is only valid for integer and modular types"); using default_ops::eval_bitwise_or; eval_bitwise_or(m_backend, canonical_value(v)); return *this; @@ -750,7 +755,7 @@ class number BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator^=(const self_type& e) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise ^ operation is only valid for integer and modular types"); do_bitwise_xor(detail::expression(e), detail::terminal()); return *this; } @@ -758,7 +763,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::result_type, self_type>::value, number&>::type operator^=(const detail::expression& e) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise ^ operation is only valid for integer and modular types"); if (contains_self(e)) { self_type temp(e); @@ -775,7 +780,7 @@ class number BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value, number&>::type operator^=(const V& v) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise ^ operation is only valid for integer and modular types"); using default_ops::eval_bitwise_xor; eval_bitwise_xor(m_backend, canonical_value(v)); return *this; @@ -914,7 +919,7 @@ class number return m_backend.compare(o.m_backend); } template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value && (number_category::value != number_kind_complex), int>::type compare(const V& o) const + BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value && (number_category::value != number_kind_complex && number_category::value != number_kind_modular), int>::type compare(const V& o) const { using default_ops::eval_get_sign; if (o == 0) @@ -922,11 +927,12 @@ class number return m_backend.compare(canonical_value(o)); } template - BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value && (number_category::value == number_kind_complex), int>::type compare(const V& o) const + BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value && (number_category::value == number_kind_complex || number_category::value == number_kind_modular), int>::type compare(const V& o) const { using default_ops::eval_get_sign; return m_backend.compare(canonical_value(o)); } + // // Direct access to the underlying backend: // @@ -1195,7 +1201,7 @@ class number // // This operation is only valid for integer backends: // - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The modulus operation is only valid for integer and modular types"); typedef typename Exp::left_type left_type; typedef typename Exp::right_type right_type; @@ -1222,7 +1228,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::modulus_immediates&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The modulus operation is only valid for integer and modular types"); using default_ops::eval_modulus; boost::multiprecision::detail::maybe_promote_precision(this); eval_modulus(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value())); @@ -1268,7 +1274,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_and_immediates&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "Bitwise operations are only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "Bitwise operations are only valid for integer and modular types"); using default_ops::eval_bitwise_and; eval_bitwise_and(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value())); } @@ -1279,7 +1285,7 @@ class number // // This operation is only valid for integer backends: // - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "Bitwise operations are only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "Bitwise operations are only valid for integer and modular types"); typedef typename Exp::left_type left_type; typedef typename Exp::right_type right_type; @@ -1313,7 +1319,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_or_immediates&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "Bitwise operations are only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "Bitwise operations are only valid for integer and modular types"); using default_ops::eval_bitwise_or; eval_bitwise_or(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value())); } @@ -1324,7 +1330,7 @@ class number // // This operation is only valid for integer backends: // - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "Bitwise operations are only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "Bitwise operations are only valid for integer and modular types"); typedef typename Exp::left_type left_type; typedef typename Exp::right_type right_type; @@ -1358,7 +1364,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_xor_immediates&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "Bitwise operations are only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "Bitwise operations are only valid for integer and modular types"); using default_ops::eval_bitwise_xor; eval_bitwise_xor(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value())); } @@ -1408,7 +1414,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_complement&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise ~ operation is only valid for integer and modular types"); using default_ops::eval_complement; self_type temp(e.left()); eval_complement(m_backend, temp.backend()); @@ -1417,7 +1423,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::complement_immediates&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise ~ operation is only valid for integer and modular types"); using default_ops::eval_complement; eval_complement(m_backend, canonical_value(e.left().value())); } @@ -1425,7 +1431,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_assign_right_shift(const Exp& e, const Val& val, const detail::terminal&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The right shift operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The right shift operation is only valid for integer and modular types"); using default_ops::eval_right_shift; detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), mpl::bool_::value>()); eval_right_shift(m_backend, canonical_value(e.value()), static_cast(val)); @@ -1434,7 +1440,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_assign_left_shift(const Exp& e, const Val& val, const detail::terminal&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The left shift operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The left shift operation is only valid for integer and modular types"); using default_ops::eval_left_shift; detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), mpl::bool_::value>()); eval_left_shift(m_backend, canonical_value(e.value()), static_cast(val)); @@ -1443,7 +1449,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_assign_right_shift(const Exp& e, const Val& val, const Tag&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The right shift operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The right shift operation is only valid for integer and modular types"); using default_ops::eval_right_shift; self_type temp(e); detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), mpl::bool_::value>()); @@ -1453,7 +1459,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_assign_left_shift(const Exp& e, const Val& val, const Tag&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The left shift operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The left shift operation is only valid for integer and modular types"); using default_ops::eval_left_shift; self_type temp(e); detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), mpl::bool_::value>()); @@ -1825,7 +1831,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_modulus(const Exp& e, const detail::terminal&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The modulus operation is only valid for integer and modular types"); using default_ops::eval_modulus; boost::multiprecision::detail::maybe_promote_precision(this); eval_modulus(m_backend, canonical_value(e.value())); @@ -1834,7 +1840,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_modulus(const Exp& e, const Unknown&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The modulus operation is only valid for integer and modular types"); using default_ops::eval_modulus; boost::multiprecision::detail::maybe_promote_precision(this); self_type temp(e); @@ -1844,14 +1850,14 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const detail::terminal&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise & operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise & operation is only valid for integer and modular types"); using default_ops::eval_bitwise_and; eval_bitwise_and(m_backend, canonical_value(e.value())); } template BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const detail::bitwise_and&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise & operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise & operation is only valid for integer and modular types"); typedef typename Exp::left_type left_type; typedef typename Exp::right_type right_type; do_bitwise_and(e.left(), typename left_type::tag_type()); @@ -1860,7 +1866,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const unknown&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise & operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise & operation is only valid for integer and modular types"); using default_ops::eval_bitwise_and; self_type temp(e); eval_bitwise_and(m_backend, temp.m_backend); @@ -1869,14 +1875,14 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const detail::terminal&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise | operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise | operation is only valid for integer and modular types"); using default_ops::eval_bitwise_or; eval_bitwise_or(m_backend, canonical_value(e.value())); } template BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const detail::bitwise_or&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise | operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise | operation is only valid for integer and modular types"); typedef typename Exp::left_type left_type; typedef typename Exp::right_type right_type; do_bitwise_or(e.left(), typename left_type::tag_type()); @@ -1885,7 +1891,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const unknown&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise | operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise | operation is only valid for integer and modular types"); using default_ops::eval_bitwise_or; self_type temp(e); eval_bitwise_or(m_backend, temp.m_backend); @@ -1894,14 +1900,14 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const detail::terminal&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise ^ operation is only valid for integer and modular types"); using default_ops::eval_bitwise_xor; eval_bitwise_xor(m_backend, canonical_value(e.value())); } template BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const detail::bitwise_xor&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise ^ operation is only valid for integer and modular types"); typedef typename Exp::left_type left_type; typedef typename Exp::right_type right_type; do_bitwise_xor(e.left(), typename left_type::tag_type()); @@ -1910,7 +1916,7 @@ class number template BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const unknown&) { - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types"); + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer || number_category::value == number_kind_modular, "The bitwise ^ operation is only valid for integer and modular types"); using default_ops::eval_bitwise_xor; self_type temp(e); eval_bitwise_xor(m_backend, temp.m_backend); diff --git a/include/boost/multiprecision/ressol.hpp b/include/boost/multiprecision/ressol.hpp new file mode 100644 index 000000000..72ea79359 --- /dev/null +++ b/include/boost/multiprecision/ressol.hpp @@ -0,0 +1,217 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2018-2020 Mikhail Komarov +// Copyright (c) 2018-2020 Pavel Kharitonov +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef BOOST_MULTIPRECISION_RESSOL_HPP +#define BOOST_MULTIPRECISION_RESSOL_HPP + +#include +#include + +#include +#include + +namespace boost { +namespace multiprecision { + +template +inline Backend eval_ressol(const Backend& a, const Backend& p) +{ + + using default_ops::eval_add; + using default_ops::eval_bit_set; + using default_ops::eval_eq; + using default_ops::eval_get_sign; + using default_ops::eval_gt; + using default_ops::eval_integer_modulus; + using default_ops::eval_is_zero; + using default_ops::eval_left_shift; + using default_ops::eval_lsb; + using default_ops::eval_lt; + using default_ops::eval_right_shift; + using default_ops::eval_subtract; + + typedef typename mpl::front::type ui_type; + + Backend zero = ui_type(0u); + Backend posone = ui_type(1u); + Backend two = ui_type(2u); + Backend negone, res; + + eval_subtract(negone, posone); + + if (eval_is_zero(a)) + { + return zero; + } + else if (eval_get_sign(a) < 0) + { + BOOST_THROW_EXCEPTION( + std::invalid_argument("ressol: value to solve for must be positive")); + } + else if (!eval_lt(a, p)) + { + BOOST_THROW_EXCEPTION(std::invalid_argument( + "ressol: value to solve for must be less than p")); + } + + if (eval_eq(p, 2)) + { + return a; + } + else if (!eval_gt(p, 1)) + { + BOOST_THROW_EXCEPTION(std::invalid_argument("ressol: prime must be > 1 a")); + } + else if (eval_integer_modulus(p, 2) == 0) + { + BOOST_THROW_EXCEPTION(std::invalid_argument("ressol: invalid prime")); + } + + if (eval_jacobi(a, p) != 1) + { // not a quadratic residue + return negone; + } + + modular_adaptor a_mod, res_mod; + + assign_components(a_mod, a, p); + + if (eval_integer_modulus(p, 4) == 3) + { + Backend exp = p; + + eval_add(exp, posone); + eval_right_shift(exp, 2); + eval_pow(res_mod, a_mod, exp); + res_mod.mod_data().adjust_regular(res, res_mod.base_data()); + + return res; + } + + Backend p_negone = p, q = p; + + eval_add(p_negone, negone); + + size_t s = eval_lsb(p_negone); + + eval_right_shift(q, s); + eval_subtract(q, posone); + eval_right_shift(q, 1); + + modular_adaptor r_mod, n_mod = a_mod, r_sq_mod; + + eval_pow(r_mod, a_mod, q); + eval_pow(r_sq_mod, r_mod, two); + eval_multiply(n_mod, r_sq_mod); + eval_multiply(r_mod, a_mod); + + Backend n, r; + n_mod.mod_data().adjust_regular(n, n_mod.base_data()); + + if (eval_eq(n, posone)) + { + r_mod.mod_data().adjust_regular(r, r_mod.base_data()); + return r; + } + + // find random non quadratic residue z + Backend z = two; + while (eval_jacobi(z, p) == 1) + { // while z quadratic residue + eval_add(z, posone); + } + + eval_left_shift(q, 1); + eval_add(q, posone); + + modular_adaptor z_mod, c_mod, q_mod; + + assign_components(z_mod, z, p); + eval_pow(c_mod, z_mod, q); + n_mod.mod_data().adjust_regular(n, n_mod.base_data()); + + while (eval_gt(n, 1)) + { + Backend q; + size_t i = 0; + + q_mod = n_mod; + q_mod.mod_data().adjust_regular(q, q_mod.base_data()); + + while (!eval_eq(q, 1)) + { + eval_pow(res_mod, q_mod, two); + q_mod = res_mod; + ++i; + + if (i >= s) + { + return negone; + } + + q_mod.mod_data().adjust_regular(q, q_mod.base_data()); + } + + Backend power_of_2; + + eval_bit_set(power_of_2, s - i - 1); + eval_pow(c_mod, c_mod, power_of_2); + eval_multiply(r_mod, c_mod); + eval_pow(c_mod, c_mod, two); + eval_multiply(n_mod, c_mod); + + n_mod.mod_data().adjust_regular(n, n_mod.base_data()); + s = i; + } + + r_mod.mod_data().adjust_regular(res, r_mod.base_data()); + + return res; +} + +/** + * Compute the square root of x modulo a prime using the + * Shanks-Tonnelli algorithm + * + * @param a the input + * @param p the prime + * @return y such that (y*y)%p == x, or -1 if no such integer + */ +template +inline number +ressol(const number& a, + const number& p) +{ + return number( + eval_ressol(a.backend(), p.backend())); +} + +/** + * Compute the square root of x modulo a prime using the + * Shanks-Tonnelli algorithm + * + * @param a the prime + * @return y such that (y*y)%p == x, or -1 if no such integer + */ + +template +inline number, ExpressionTemplates> +ressol(const number, ExpressionTemplates>& modular) +{ + number mod = modular.backend().mod_data().get_mod(); + number res = eval_ressol(modular.backend().base_data(), mod.backend()); + number, ExpressionTemplates> res_mod; + assign_components(res_mod.backend(), res.backend(), mod.backend()); + return res_mod; +} + +} +} // namespace boost::multiprecision + +#endif // BOOST_MULTIPRECISION_RESSOL_HPP diff --git a/include/boost/multiprecision/tommath.hpp b/include/boost/multiprecision/tommath.hpp index 5b310ea7d..10b67a8b5 100644 --- a/include/boost/multiprecision/tommath.hpp +++ b/include/boost/multiprecision/tommath.hpp @@ -81,9 +81,9 @@ struct tommath_int { if (m_data.dp == 0) detail::check_tommath_result(mp_init(&m_data)); - boost::ulong_long_type mask = ((1uLL << 32) - 1); - unsigned shift = 0; - ::mp_int t; + boost::ulong_long_type mask = ((1uLL << 32) - 1); + unsigned shift = 0; + ::mp_int t; detail::check_tommath_result(mp_init(&t)); mp_zero(&m_data); while (i) @@ -104,14 +104,14 @@ struct tommath_int { if (m_data.dp == 0) detail::check_tommath_result(mp_init(&m_data)); - if(sizeof(boost::ulong_long_type) * CHAR_BIT == 64) + if (sizeof(boost::ulong_long_type) * CHAR_BIT == 64) { mp_set_u64(&m_data, i); return *this; } - boost::ulong_long_type mask = ((1uLL << 64) - 1); - unsigned shift = 0; - ::mp_int t; + boost::ulong_long_type mask = ((1uLL << 64) - 1); + unsigned shift = 0; + ::mp_int t; detail::check_tommath_result(mp_init(&t)); mp_zero(&m_data); while (i) @@ -693,6 +693,12 @@ inline void eval_gcd(tommath_int& result, const tommath_int& a, const tommath_in { detail::check_tommath_result(mp_gcd(const_cast< ::mp_int*>(&a.data()), const_cast< ::mp_int*>(&b.data()), const_cast< ::mp_int*>(&result.data()))); } +inline int eval_jacobi(tommath_int& a, tommath_int& n) +{ + int result = 0; + mp_jacobi(const_cast< ::mp_int*>(&a.data()), const_cast< ::mp_int*>(&n.data()), &result); + return result; +} inline void eval_lcm(tommath_int& result, const tommath_int& a, const tommath_int& b) { detail::check_tommath_result(mp_lcm(const_cast< ::mp_int*>(&a.data()), const_cast< ::mp_int*>(&b.data()), const_cast< ::mp_int*>(&result.data()))); diff --git a/include/boost/multiprecision/tommath_modular.hpp b/include/boost/multiprecision/tommath_modular.hpp new file mode 100644 index 000000000..840977c4c --- /dev/null +++ b/include/boost/multiprecision/tommath_modular.hpp @@ -0,0 +1,23 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2020 Mikhail Komarov +// Copyright (c) 2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef _MULTIPRECISION_TOMMATH_MODULAR_HPP +#define _MULTIPRECISION_TOMMATH_MODULAR_HPP + +#include +#include +#include + +namespace boost { +namespace multiprecision { +typedef modular_params tom_int_mod_params; +typedef number > tom_int_mod; +} +} // namespace boost::multiprecision +#endif //_MULTIPRECISION_TOMMATH_MODULAR_HPP diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 000000000..16a99bda6 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,1601 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# Copyright (c) 2018-2020 Alexey Moskvin +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +include(CMTest) + +find_package(GMP) +find_package(Quadmath) +find_package(TomMath) +find_package(MPFR) +find_package(MPFI) +find_package(MPC) +find_package(Eigen3) + +if(BOOST_CMAKE) + find_package(${CMAKE_WORKSPACE_NAME}_algorithm) + find_package(${CMAKE_WORKSPACE_NAME}_chrono) + find_package(${CMAKE_WORKSPACE_NAME}_exception) + find_package(${CMAKE_WORKSPACE_NAME}_timer) + find_package(${CMAKE_WORKSPACE_NAME}_numeric_ublas) + find_package(${CMAKE_WORKSPACE_NAME}_filesystem) + find_package(${CMAKE_WORKSPACE_NAME}_test) + find_package(${CMAKE_WORKSPACE_NAME}_serialization) + find_package(${CMAKE_WORKSPACE_NAME}_numeric_interval) + find_package(${CMAKE_WORKSPACE_NAME}_detail) + find_package(${CMAKE_WORKSPACE_NAME}_throw_exception) + find_package(${CMAKE_WORKSPACE_NAME}_math) + find_package(${CMAKE_WORKSPACE_NAME}_regexp) + + cm_test_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} + ${CMAKE_WORKSPACE_NAME}::algorithm + ${CMAKE_WORKSPACE_NAME}::chrono + ${CMAKE_WORKSPACE_NAME}::exception + ${CMAKE_WORKSPACE_NAME}::timer + ${CMAKE_WORKSPACE_NAME}::numeric_ublas + ${CMAKE_WORKSPACE_NAME}::filesystem + ${CMAKE_WORKSPACE_NAME}::test + ${CMAKE_WORKSPACE_NAME}::serialization + ${CMAKE_WORKSPACE_NAME}::numeric_interval + ${CMAKE_WORKSPACE_NAME}::detail + ${CMAKE_WORKSPACE_NAME}::throw_exception + ${CMAKE_WORKSPACE_NAME}::math + ${CMAKE_WORKSPACE_NAME}::regexp) +else() + find_package(Boost REQUIRED COMPONENTS chrono filesystem unit_test_framework serialization regex) + list(APPEND ${CURRENT_PROJECT_NAME}_LIBRARIES ${Boost_LIBRARIES}) + find_package(Boost COMPONENTS timer exception) + list(APPEND ${CURRENT_PROJECT_NAME}_LIBRARIES ${Boost_LIBRARIES}) + + cm_test_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} + ${${CURRENT_PROJECT_NAME}_LIBRARIES}) + + include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../include" + "${CMAKE_CURRENT_BINARY_DIR}/include" + + ${Boost_INCLUDE_DIRS}) +endif() + +add_custom_target(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests) +add_custom_target(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits) +add_custom_target(${CURRENT_PROJECT_NAME}_test_suite_conversions) +add_custom_target(${CURRENT_PROJECT_NAME}_test_suite_cpp_int_tests) +add_custom_target(${CURRENT_PROJECT_NAME}_test_suite_misc) +add_custom_target(${CURRENT_PROJECT_NAME}_test_suite_specfun) +add_custom_target(${CURRENT_PROJECT_NAME}_test_suite_concepts) +add_custom_target(${CURRENT_PROJECT_NAME}_test_suite_examples) +add_custom_target(${CURRENT_PROJECT_NAME}_test_suite_compile_fail) + +# copyright John Maddock 2011 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt. + +# HACK: Workaround broken includes +file(GLOB TEST_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/*.ipp) +set(CMAKE_INCLUDE_CURRENT_DIR TRUE) +foreach(HEADER ${TEST_HEADERS}) + configure_file(${HEADER} ${CMAKE_CURRENT_BINARY_DIR}/libs/${CURRENT_PROJECT_NAME}/test/${HEADER} + @ONLY) +endforeach() + +add_library(${CURRENT_PROJECT_NAME}_test_settings INTERFACE) +target_include_directories(${CURRENT_PROJECT_NAME}_test_settings INTERFACE ${CURRENT_TEST_SOURCES_DIR}/include) +cm_test_link_libraries(${CURRENT_PROJECT_NAME}_test_settings) + +# We set these to make it easier to set up and test GMP and MPFR under Win32: +# Speed up compiles: +# We can't yet enable this - it breaks the STL in some tests... +#msvc,off:-RTCc +#msvc,off:_ALLOW_RTCc_IN_STL + +# add_library(no_eh_support STATIC no_eh_support.cpp) +# cm_mark_as_test(no_eh_support) +# target_link_libraries(no_eh_support boost_throw_exception) +# cm_target_link_test_libs(no_eh_support) + +if(GMP_FOUND) + try_compile(GMP_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_gmp.cpp + LINK_LIBRARIES ${GMP_LIBRARIES} + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${GMP_INCLUDE_DIRS};${Boost_INCLUDE_DIRS}" OUTPUT_VARIABLE OUTP) +endif() + +if(MPFR_FOUND) + try_compile(MPFR_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_mpfr.cpp + LINK_LIBRARIES ${MPFR_LIBRARIES} + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${MPFR_INCLUDE_DIRS}") +endif() + +if(TOMMATH_FOUND) + try_compile(TOMMATH_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_tommath.cpp + LINK_LIBRARIES ${TomMath_LIBRARIES} + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${TomMath_INCLUDE_DIRS}") +endif() + +try_compile(FLOAT128_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_float128.cpp) + +if(MPFI_FOUND) + try_compile(MPFI_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_mpfi.cpp + LINK_LIBRARIES ${MPFI_LIBRARIES} + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${MPFI_INCLUDE_DIRS}") +endif() + +if(Quadmath_FOUND) + try_compile(INTEL_QUAD_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_intel_quad.cpp CMAKE_FLAGS + "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'") +endif() + +if(MPC_FOUND) + try_compile(MPC_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_mpc.cpp + LINK_LIBRARIES ${MPC_LIBRARIES} + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${MPC_INCLUDE_DIRS}") +endif() + +if(EIGEN_FOUND) + try_compile(EIGEN_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_eigen.cpp + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${EIGEN3_INCLUDE_DIRS}") +endif() + +#cm_test(NAME GMP_MY SOURCES ${CURRENT_TEST_SOURCES_DIR}/../config/has_float128.cpp) +#target_link_libraries(GMP_MY ${Quadmath_LIBRARY}) +#target_include_directories(GMP_MY PRIVATE ${Quadmath_INCLUDE_DIR}) + +add_library(no_eh_support SHARED ${CURRENT_TEST_SOURCES_DIR}/no_eh_test_support.cpp) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_backend_concept SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_backend_concept.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_backend_concept no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_backend_concept) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_dec_float_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_1.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_dec_float_1 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_dec_float_1) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_dec_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_2.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_dec_float_2 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_dec_float_2) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_dec_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_3.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_dec_float_3 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_dec_float_3) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_dec_float_3m SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_3m.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_dec_float_3m no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_dec_float_3m) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_bin_float_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_1.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_bin_float_1 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_bin_float_1) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_bin_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_2.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_bin_float_2 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_bin_float_2) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_bin_float_2m SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_2m.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_bin_float_2m no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_bin_float_2m) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_bin_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_3.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_bin_float_3 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_bin_float_3) + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpf_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpf_50.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpf_50 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpf_50 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpf_50) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpf SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpf.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpf ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpf PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpf) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpz.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpz ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpz PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpz) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpz_rat SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpz_rat.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpz_rat ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpz_rat PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpz_rat) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpz_br SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpz_br.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpz_br ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpz_br PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpz_br) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpq SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpq.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpq ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpq PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpq) +endif() + +if(MPFR_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfr.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfr ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfr PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfr) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfr_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfr_50.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfr_50 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfr_50 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfr_50) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfr_50_static SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfr_50_static.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfr_50_static ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfr_50_static PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfr_50_static) +endif() + +if(TOMMATH_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_tommath.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_tommath ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_arithmetic_tommath PRIVATE ${TomMath_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_tommath) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_tommath_rat SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_tommath_rat.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_tommath_rat ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_arithmetic_tommath_rat PRIVATE ${TomMath_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_tommath_rat) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_tommath_br SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_tommath_br.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_tommath_br ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_arithmetic_tommath_br PRIVATE ${TomMath_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_tommath_br) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_1.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_1 no_eh_support) +if(MSVC) + target_compile_options(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_1 PRIVATE /bigobj) +endif() +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_1) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_2.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_2 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_2) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_3.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_3 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_3) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_4.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_4 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_4) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_5.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_5 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_5) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_6 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_6.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_6 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_6) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_7 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_7.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_7 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_7) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_8 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_8.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_8 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_8) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_9 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_9.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_9 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_9) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_10 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_10.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_10 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_10) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_11 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_11.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_11 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_11) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_12 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_12.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_12 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_12) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_13 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_13.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_13 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_13) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_14 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_14.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_14 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_14) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_15 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_15.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_15 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_15) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_16 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_16.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_16 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_16) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_17 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_17.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_17 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_17) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_18 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_18.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_18 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_18) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_19 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_19.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_19 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_19) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_br SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_br.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_br no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_cpp_int_br) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_ab_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_ab_1.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_ab_1 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_ab_1) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_ab_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_ab_2.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_ab_2 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_ab_2) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_ab_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_ab_3.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_ab_3 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_ab_3) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_dec_float_round SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_dec_float_round.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_cpp_dec_float_round no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_cpp_dec_float_round) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_logged_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_logged_1.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_logged_1 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_logged_1) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_logged_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_logged_2.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_logged_2 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_logged_2) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_dbg_adptr1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_dbg_adptr1.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_dbg_adptr1 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_dbg_adptr1) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_dbg_adptr1m SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_dbg_adptr1m.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_dbg_adptr1m no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_dbg_adptr1m) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_dbg_adptr2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_dbg_adptr2.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_dbg_adptr2 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_dbg_adptr2) + +if(MPFI_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfi_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfi_50.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfi_50 ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfi_50 PRIVATE ${MPFI_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpfi_50) +endif() + +if(INTEL_QUAD_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_float_128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_float_128.cpp) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_float_128) +endif() + +if(FLOAT128_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_float_128_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_float_128.cpp) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_float_128_quad) +endif() + +if(MPC_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpc SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpc.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpc ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpc PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_mpc) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_mpfr_mpc_precisions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpfr_mpc_precisions.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_mpfr_mpc_precisions ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_mpfr_mpc_precisions PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_mpfr_mpc_precisions) +endif() +if(MPFI_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_mpfi_precisions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpfi_precisions.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_mpfi_precisions ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_mpfi_precisions PRIVATE ${MPFI_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_mpfi_precisions) +endif() + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_mpf_precisions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpf_precisions.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_mpf_precisions ${GMP_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_mpf_precisions PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_mpf_precisions) +endif() + +if((MPC_COMPILED) AND (FLOAT128_COMPILED)) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_complex SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_complex.cpp) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_complex) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_complex_adaptor SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_complex_adaptor.cpp) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_complex_adaptor) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_complex_adaptor_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_complex_adaptor_2.cpp) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_arithmetic_complex_adaptor_2) + +if(FLOAT128_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_arithmetic_complex128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_complex128.cpp) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_arithmetic_tests ${CURRENT_PROJECT_NAME}_test_test_complex128) +endif() + +set(LOCAL_SOURCES + test_exp.cpp + test_log.cpp + test_pow.cpp + test_sinh.cpp + test_sqrt.cpp + test_cosh.cpp + test_tanh.cpp + test_sin.cpp + test_cos.cpp + test_tan.cpp + test_asin.cpp + test_acos.cpp + test_atan.cpp + test_round.cpp + test_fpclassify.cpp + test_sf_import_c99.cpp) +foreach(FILE ${LOCAL_SOURCES}) + get_filename_component(NAME ${FILE} NAME_WE) + if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_${NAME}_mpf50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_${NAME}_mpf50 PUBLIC -DTEST_MPF_50) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_${NAME}_mpf50 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_${NAME}_mpf50 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_${NAME}_mpf50) + endif() + if(MPFR_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_${NAME}_mpfr50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_${NAME}_mpfr50 PUBLIC -DTEST_MPFR_50) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_${NAME}_mpfr50 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_${NAME}_mpfr50 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_${NAME}_mpfr50) + endif() + if(MPFI_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_${NAME}_mpfi50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_${NAME}_mpfi50 PUBLIC -DTEST_MPFI_50) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_${NAME}_mpfi50 ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_${NAME}_mpfi50 PRIVATE ${MPFI_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_${NAME}_mpfi50) + endif() + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_${NAME}_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_${NAME}_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_${NAME}_cpp_dec_float no_eh_support) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_${NAME}_cpp_dec_float) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_${NAME}_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_${NAME}_cpp_bin_float PUBLIC -DTEST_CPP_BIN_FLOAT) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_${NAME}_cpp_bin_float no_eh_support) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_${NAME}_cpp_bin_float) + + if(FLOAT128_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_${NAME}_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_${NAME}_float128 PUBLIC -DTEST_FLOAT128) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_${NAME}_float128 no_eh_support) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_${NAME}_float128) + endif() + + if(INTEL_QUAD_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_${NAME}_intel_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_${NAME}_intel_quad PUBLIC -DTEST_FLOAT128) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_${NAME}_intel_quad no_eh_support) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_${NAME}_intel_quad) + endif() +endforeach() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_backend_concept SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_backend_concept PUBLIC -DTEST_BACKEND) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_backend_concept no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_backend_concept) + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpf50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpf50 PUBLIC -DTEST_MPF_50) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpf50 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpf50 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpf50) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpf SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpf PUBLIC -DTEST_MPF) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpf ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpf PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpf) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpz PUBLIC -DTEST_MPZ) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpz ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpz PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpz) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpq SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpq PUBLIC -DTEST_MPQ) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpq ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpq PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpq) +endif() + +if(MPFR_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpfr PUBLIC -DTEST_MPFR) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpfr ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpfr PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpfr) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpfr_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpfr_50 PUBLIC -DTEST_MPFR_50) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpfr_50 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpfr_50 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpfr_50) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_cpp_dec_float no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_cpp_dec_float) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_cpp_bin_float PUBLIC -DTEST_CPP_BIN_FLOAT) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_cpp_bin_float no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_cpp_bin_float) + +if(TOMMATH_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_tommath PUBLIC -DTEST_TOMMATH) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_tommath ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_tommath PRIVATE ${TomMath_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_tommath) +endif() + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_cpp_int PUBLIC -DTEST_CPP_INT) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_cpp_int no_eh_support) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_cpp_int) +endif() + +if(MPFI_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpfi_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpfi_50 PUBLIC -DTEST_MPFI_50) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpfi_50 ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpfi_50 PRIVATE ${MPFI_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_mpfi_50) +endif() + +if(FLOAT128_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_float128 PUBLIC -DTEST_FLOAT128) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_float128) +endif() + +if((INTEL_QUAD_COMPILED) AND (FLOAT128_COMPILED)) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_intel_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_numeric_limits_intel_quad PUBLIC -DTEST_FLOAT128) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_numeric_limits_intel_quad) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_dec_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_sf_import_c99.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_dec_float_2 PUBLIC -DTEST_CPP_DEC_FLOAT_2) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_dec_float_2) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_dec_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_sf_import_c99.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_dec_float_3 PUBLIC -DTEST_CPP_DEC_FLOAT_3) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_dec_float_3) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_dec_float_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_sf_import_c99.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_dec_float_4 PUBLIC -DTEST_CPP_DEC_FLOAT_4) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_dec_float_4) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_dec_float_5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_sf_import_c99.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_dec_float_5 PUBLIC -DTEST_CPP_DEC_FLOAT_5) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_dec_float_5) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_dec_float_6 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_sf_import_c99.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_dec_float_6 PUBLIC -DTEST_CPP_DEC_FLOAT_6) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_dec_float_6) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_bin_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_sf_import_c99.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_bin_float_2 PUBLIC -DTEST_CPP_BIN_FLOAT_2) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_bin_float_2) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_bin_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_sf_import_c99.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_bin_float_3 PUBLIC -DTEST_CPP_BIN_FLOAT_2) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_sf_import_c99_cpp_bin_float_3) + +if(MPFR_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_move_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_move_mpfr PUBLIC -DTEST_MPFR) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_move_mpfr ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_move_mpfr) +endif() + +if(MPC_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_move_mpc SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_move_mpc PUBLIC -DTEST_MPC) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_move_mpc ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_move_mpc) +endif() + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_move_gmp SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_move_gmp PUBLIC -DTEST_GMP) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_move_gmp ${GMP_LIBRARIES} no_eh_support) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_move_gmp) +endif() + +if(TOMMATH_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_move_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_move_tommath PUBLIC -DTEST_TOMMATH) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_move_tommath ${TomMath_LIBRARIES} no_eh_support) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_move_tommath) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_move_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_move_cpp_int PUBLIC -DTEST_CPP_INT) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_move_cpp_int no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_functions_and_limits ${CURRENT_PROJECT_NAME}_test_test_move_cpp_int) + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_gmp_conversions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_gmp_conversions.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_gmp_conversions ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_gmp_conversions PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_gmp_conversions) +endif() + +if(MPFR_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_mpfr_conversions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpfr_conversions.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_mpfr_conversions ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_mpfr_conversions PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_mpfr_conversions) +endif() + +if(MPC_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_mpc_conversions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpfr_conversions.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_mpc_conversions ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_mpc_conversions PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_mpc_conversions) +endif() + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_constants_mpf50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_constants.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_constants_mpf50 PUBLIC -DTEST_MPF_50) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_constants_mpf50 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_constants_mpf50 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_constants_mpf50) +endif() + +if(MPFR_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_constants_mpfr_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_constants.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_constants_mpfr_50 PUBLIC -DTEST_MPFR_50) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_constants_mpfr_50 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_constants_mpfr_50 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_constants_mpfr_50) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_constants_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_constants.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_constants_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_constants_cpp_dec_float no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_constants_cpp_dec_float) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_test.cpp) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_int_lit SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_lit.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_cpp_int_lit no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_cpp_int_lit) + +if((GMP_COMPILED) AND (MPFR_COMPILED) AND (MPFI_COMPILED) AND (TOMMATH_COMPILED) AND (FLOAT128_COMPILED)) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_convert_from_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_cpp_int.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_convert_from_cpp_int ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_convert_from_cpp_int PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_convert_from_cpp_int) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_convert_from_mpz_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_mpz_int.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_convert_from_mpz_int ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_convert_from_mpz_int PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_convert_from_mpz_int) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_convert_from_tom_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_tom_int.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_convert_from_tom_int ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_convert_from_tom_int PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_convert_from_tom_int) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_convert_from_cpp_rational SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_cpp_rational.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_convert_from_cpp_rational ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_convert_from_cpp_rational PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_convert_from_cpp_rational) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_convert_from_gmp_rational SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_gmp_rational.cpp) + target_link_libraries(test_convert_from_gmp_rational ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_convert_from_gmp_rational PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_convert_from_gmp_rational) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_convert_from_tom_rational SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_tom_rational.cpp) + target_link_libraries(test_convert_from_tom_rational ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_convert_from_tom_rational PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_convert_from_tom_rational) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_convert_from_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_cpp_bin_float.cpp) + target_link_libraries(test_convert_from_cpp_bin_float ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_convert_from_cpp_bin_float PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_convert_from_cpp_bin_float) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_convert_from_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_cpp_dec_float.cpp) + target_link_libraries(test_convert_from_cpp_dec_float ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_convert_from_cpp_dec_float PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_convert_from_cpp_dec_float) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_convert_from_mpf_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_mpf_float.cpp) + target_link_libraries(test_convert_from_mpf_float ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_convert_from_mpf_float PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_convert_from_mpf_float) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_convert_from_mpfr_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_mpfr_float.cpp) + target_link_libraries(test_convert_from_mpfr_float ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_convert_from_mpfr_float PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_convert_from_mpfr_float) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_convert_from_mpfi_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_mpfi_float.cpp) + target_link_libraries(test_convert_from_mpfi_float ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_convert_from_mpfi_float PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_convert_from_mpfi_float) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_convert_from_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_float128.cpp) + target_link_libraries(test_convert_from_float128 ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_convert_from_float128 PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_convert_from_float128) + +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_bin_float_conv SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_conv.cpp) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_cpp_bin_float_conv) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_bin_float_io_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_io.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_cpp_bin_float_io_1 PUBLIC -DTEST1 -DTEST_CPP_BIN_FLOAT) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_cpp_bin_float_io_1) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_bin_float_io_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_io.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_cpp_bin_float_io_2 PUBLIC -DTEST2 -DTEST_CPP_BIN_FLOAT) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_cpp_bin_float_io_2) + +if(MPFR_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_cpp_bin_float PUBLIC -DTEST_MPFR) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_cpp_bin_float ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_cpp_bin_float PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_cpp_bin_float) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_cpp_dec_float no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_cpp_dec_float) + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_float_io_mpf SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_float_io_mpf PUBLIC -DTEST_MPF_50) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_float_io_mpf ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_float_io_mpf PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_float_io_mpf) +endif() + +if(MPFR_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_float_io_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_float_io_mpfr PUBLIC -DTEST_MPFR_50) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_float_io_mpfr ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_float_io_mpfr PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_float_io_mpfr) +endif() + +if(MPFI_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_float_io_mpfi SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_float_io_mpfi PUBLIC -DTEST_MPFI_50) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_float_io_mpfi ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_float_io_mpfi PRIVATE ${GMP_INCLUDE_DIRS} ${MPFI_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_float_io_mpfi) +endif() + +if(FLOAT128_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_float_io_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_float_io_float128 PUBLIC -DTEST_FLOAT128) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_float_io_float128 ${QUADMATH_LIBRARIES} no_eh_support) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_float_io_float128) +endif() + +if((INTEL_QUAD_COMPILED) AND (FLOAT128_COMPILED)) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_float_io_intel_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_float_io_intel_quad PUBLIC -DTEST_FLOAT128) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_float_io_intel_quad no_eh_support) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_float_io_intel_quad) +endif() + +if(TOMMATH_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_int_io_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_int_io_tommath PUBLIC -DTEST_TOMMATH) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_int_io_tommath ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_int_io_tommath PRIVATE ${TomMath_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_int_io_tommath) +endif() + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_int_io_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_int_io_mpz PUBLIC -DTEST_MPZ) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_int_io_mpz ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_int_io_mpz PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_conversions ${CURRENT_PROJECT_NAME}_test_test_int_io_mpz) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_int_io_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_int_io_cpp_int PUBLIC -DTEST_CPP_INT) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_int_io_cpp_int no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_cpp_int_tests ${CURRENT_PROJECT_NAME}_test_test_int_io_cpp_int) + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_int_left_shift SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_left_shift.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_cpp_int_left_shift ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_cpp_int_left_shift PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_cpp_int_tests ${CURRENT_PROJECT_NAME}_test_test_cpp_int_left_shift) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_int_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_cpp_int_1 PUBLIC -DTEST1) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_cpp_int_1 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_cpp_int_1 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_cpp_int_tests ${CURRENT_PROJECT_NAME}_test_test_cpp_int_1) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_int_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_cpp_int_2 PUBLIC -DTEST2) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_cpp_int_2 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_cpp_int_2 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_cpp_int_tests ${CURRENT_PROJECT_NAME}_test_test_cpp_int_2) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_int_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_cpp_int_3 PUBLIC -DTEST3) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_cpp_int_3 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_cpp_int_3 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_cpp_int_tests ${CURRENT_PROJECT_NAME}_test_test_cpp_int_3) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_int_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_cpp_int_4 PUBLIC -DTEST4) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_cpp_int_4 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_cpp_int_4 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_cpp_int_tests ${CURRENT_PROJECT_NAME}_test_test_cpp_int_4) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_int_5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_cpp_int_5 PUBLIC -DTEST5) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_cpp_int_5 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_cpp_int_5 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_cpp_int_tests ${CURRENT_PROJECT_NAME}_test_test_cpp_int_5) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_checked_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_checked_cpp_int.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_checked_cpp_int no_eh_support) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_unchecked_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_unchecked_cpp_int.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_unchecked_cpp_int no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_cpp_int_tests ${CURRENT_PROJECT_NAME}_test_test_unchecked_cpp_int) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_int_serial_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_cpp_int_serial_1 PUBLIC -DTEST1) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_cpp_int_tests ${CURRENT_PROJECT_NAME}_test_test_cpp_int_serial_1) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_int_serial_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_cpp_int_serial_2 PUBLIC -DTEST2) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_cpp_int_tests ${CURRENT_PROJECT_NAME}_test_test_cpp_int_serial_2) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_int_serial_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_cpp_int_serial_3 PUBLIC -DTEST3) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_cpp_int_tests ${CURRENT_PROJECT_NAME}_test_test_cpp_int_serial_3) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_int_serial_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_cpp_int_serial_4 PUBLIC -DTEST4) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_cpp_int_tests ${CURRENT_PROJECT_NAME}_test_test_cpp_int_serial_4) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_int_deserial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_deserial.cpp) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_cpp_int_tests ${CURRENT_PROJECT_NAME}_test_test_cpp_int_deserial) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_rat_serial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_rat_serial.cpp) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_cpp_int_tests ${CURRENT_PROJECT_NAME}_test_test_cpp_rat_serial) + +if((FLOAT128_COMPILED) AND (QUADMATH_COMPILED)) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_constexpr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_constexpr.cpp COMPILE_ONLY) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_constexpr PUBLIC -DHAVE_FLOAT128) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_constexpr) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_nothrow_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_cpp_int.cpp COMPILE_ONLY) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_nothrow_cpp_int) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_nothrow_cpp_rational SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_cpp_rational.cpp COMPILE_ONLY) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_nothrow_cpp_rational) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_nothrow_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_cpp_bin_float.cpp COMPILE_ONLY) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_nothrow_cpp_bin_float) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_nothrow_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_cpp_dec_float.cpp COMPILE_ONLY) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_nothrow_cpp_dec_float) + +if(FLOAT128_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_nothrow_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_float128.cpp COMPILE_ONLY) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_nothrow_float128) +endif() + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_nothrow_gmp SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_gmp.cpp COMPILE_ONLY) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_nothrow_gmp) +endif() + +if(MPFR_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_nothrow_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_mpfr.cpp COMPILE_ONLY) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_nothrow_mpfr) +endif() + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_miller_rabin SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_miller_rabin.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_miller_rabin ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_miller_rabin PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_miller_rabin) +endif() + +if(TOMMATH_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_rational_io_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rational_io.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_rational_io_tommath PUBLIC -DTEST_TOMMATH) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_rational_io_tommath ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_rational_io_tommath PRIVATE ${TomMath_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_rational_io_tommath) +endif() + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_rational_io_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rational_io.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_rational_io_mpz PUBLIC -DTEST_MPQ) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_rational_io_mpz ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_rational_io_mpz PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_rational_io_mpz) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_rational_io_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rational_io.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_rational_io_cpp_int PUBLIC -DTEST_CPP_INT) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_rational_io_cpp_int no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_rational_io_cpp_int) + +if((GMP_COMPILED) AND (TOMMATH_COMPILED) AND (MPFR_COMPILED)) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_generic_conv SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_generic_conv.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_generic_conv PUBLIC -DTEST_GMP -DTEST_TOMMATH -DTEST_MPFR) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_generic_conv ${TomMath_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_generic_conv PRIVATE ${GMP_INCLUDE_DIRS} ${TomMath_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_generic_conv) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_1 PUBLIC -DTEST1) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_1 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_1) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_2 PUBLIC -DTEST2) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_2 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_2) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_3 PUBLIC -DTEST3) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_3 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_3) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_4 PUBLIC -DTEST4) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_4 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_4) + +if(MPFR_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_5 PUBLIC -DTEST5) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_5 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_5 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_5) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_6 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_6 PUBLIC -DTEST6) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_6 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_6 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_6) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_7 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_7 PUBLIC -DTEST7) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_7 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_7 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_7) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_8 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_8 PUBLIC -DTEST8) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_8 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_8 PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_rat_float_interconv_8) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_int_conv SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_conv.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_cpp_int_conv no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_cpp_int_conv) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_int_import_export SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_import_export.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_cpp_int_import_export no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_cpp_int_import_export) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_native_integer SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_native_integer.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_native_integer no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_native_integer) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_mixed_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_cpp_int.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_mixed_cpp_int no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_mixed_cpp_int) + +if((GMP_COMPILED) AND (MPFR_COMPILED)) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_mixed_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_float.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_mixed_float ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_mixed_float) +endif() + +if(MPFR_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_include_test_mpfr_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/mpfr_include_test.cpp COMPILE_ONLY) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_include_test_mpfr_include_test) +endif() + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_include_test_gmp_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/gmp_include_test.cpp COMPILE_ONLY) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_include_test_gmp_include_test) +endif() + +if(TOMMATH_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_include_test_tommath_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/tommath_include_test.cpp COMPILE_ONLY) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_include_test_tommath_include_test) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_include_test_cpp_int_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/cpp_int_include_test.cpp COMPILE_ONLY) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_include_test_cpp_int_include_test) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_include_test_cpp_dec_float_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/cpp_dec_float_include_test.cpp COMPILE_ONLY) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_include_test_cpp_dec_float_include_test) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_ublas_interopinclude_test_cpp_bin_float_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/cpp_bin_float_include_test.cpp COMPILE_ONLY) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_ublas_interopinclude_test_cpp_bin_float_include_test) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_ublas_interop_test1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test1.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test11.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test12.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test13.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_ublas_interop_test1 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_ublas_interop_test1) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_ublas_interop_test2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test2.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test21.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test22.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test23.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_ublas_interop_test2 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_ublas_interop_test2) + +#run ublas_interop/test3.cpp ublas_interop/test31.cpp ublas_interop/test32.cpp ublas_interop/test33.cpp ; +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_ublas_interop_test4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test4.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test42.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test43.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_ublas_interop_test4 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_ublas_interop_test4) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_ublas_interop_test5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test5.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test52.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test53.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_ublas_interop_test5 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_ublas_interop_test5) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_ublas_interop_test6 SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test6.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test62.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test63.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_ublas_interop_test6 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_ublas_interop_test6) + +#run ublas_interop/test7.cpp ublas_interop/test71.cpp ublas_interop/test72.cpp ublas_interop/test73.cpp ; + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_ublas_interop_test1_et SOURCES + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test1.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test11.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test12.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test13.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_ublas_interop_test1_et no_eh_support) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_ublas_interop_test1_et PUBLIC -DTEST_ET=1) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_ublas_interop_test1_et) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_ublas_interop_test2_et SOURCES + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test2.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test21.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test22.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test23.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_ublas_interop_test2_et no_eh_support) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_ublas_interop_test2_et PUBLIC -DTEST_ET=1) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_ublas_interop_test2_et) + +#run ublas_interop/test3.cpp ublas_interop/test31.cpp ublas_interop/test32.cpp ublas_interop/test33.cpp ; +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_ublas_interop_test4_et SOURCES + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test4.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test42.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test43.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_ublas_interop_test4_et no_eh_support) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_ublas_interop_test4_et PUBLIC -DTEST_ET=1) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_ublas_interop_test4_et) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_ublas_interop_test5_et SOURCES + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test5.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test52.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test53.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_ublas_interop_test5_et no_eh_support) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_ublas_interop_test5_et PUBLIC -DTEST_ET=1) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_ublas_interop_test5_et) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_ublas_interop_test6_et SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test6.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test62.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test63.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_ublas_interop_test6_et no_eh_support) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_ublas_interop_test6_et PUBLIC -DTEST_ET=1) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_ublas_interop_test6_et) + +#run ublas_interop/test7.cpp ublas_interop/test71.cpp ublas_interop/test72.cpp ublas_interop/test73.cpp ; + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_adapt_serial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_adapt_serial.cpp) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_adapt_serial) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_dec_float_serial_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_dec_float_serial.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_cpp_dec_float_serial_1 PUBLIC -DTEST1) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_cpp_dec_float_serial_1) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cpp_dec_float_serial_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_dec_float_serial.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_cpp_dec_float_serial_2 PUBLIC -DTEST2) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_cpp_dec_float_serial_2) + +if(QUADMATH_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_float128_serial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float128_serial.cpp) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_float128_serial) +endif() +#TODO: Enable this +#[[ +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_bin_dec_float_serial_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_serial.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_bin_dec_float_serial_1 PUBLIC -DTEST1) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_bin_dec_float_serial_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_serial.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_bin_dec_float_serial_2 PUBLIC -DTEST2) +]] +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_checked_mixed_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_checked_mixed_cpp_int.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_checked_mixed_cpp_int no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_checked_mixed_cpp_int) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_mixed_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_cpp_bin_float.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_mixed_cpp_bin_float no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_checked_mixed_cpp_int) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_mixed_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_cpp_dec_float.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_mixed_cpp_dec_float no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_mixed_cpp_dec_float) + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_mixed_mpf_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_mpf_float.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_mixed_mpf_float ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_mixed_mpf_float PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_mixed_mpf_float) +endif() +if(MPFR_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_mixed_mpfr_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_mpfr_float.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_mixed_mpfr_float ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_mixed_mpfr_float PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_mixed_mpfr_float) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_float_conversions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_conversions.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_float_conversions no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_float_conversions) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_bug11922 SOURCES ${CURRENT_TEST_SOURCES_DIR}/bug11922.cpp COMPILE_ONLY) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_bug11922) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_bug12039 SOURCES ${CURRENT_TEST_SOURCES_DIR}/bug12039.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_bug12039 no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_bug12039) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_git_issue_30 SOURCES ${CURRENT_TEST_SOURCES_DIR}/git_issue_30.cpp COMPILE_ONLY) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_git_issue_30) + +if((GMP_COMPILED) AND (MPFR_COMPILED) AND (MPC_COMPILED) AND (FLOAT128_COMPILED)) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_git_issue_98 ${CURRENT_TEST_SOURCES_DIR}/git_issue_98.cpp COMPILE_ONLY) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_git_issue_98 ${QUADMATH_LIBRARIES} ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_git_issue_98 PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPC -DFLOAT128_COMPILED) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_git_issue_98) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_issue_13301 SOURCES ${CURRENT_TEST_SOURCES_DIR}/issue_13301.cpp) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_issue_13301) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_issue_13148 SOURCES ${CURRENT_TEST_SOURCES_DIR}/issue_13148.cpp) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_issue_13148) + +if((GMP_COMPILED) AND (MPFR_COMPILED) AND (MPFI_COMPILED) AND (TomMath_COMPILED) AND (FLOAT128_COMPILED)) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_hash ${CURRENT_TEST_SOURCES_DIR}/test_hash.cpp COMPILE_ONLY) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_hash ${QUADMATH_LIBRARIES} ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} + ${GMP_LIBRARIES} ${TomMath_LIBRARIES}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_hash PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_hash) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_optional_compat SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_optional_compat.cpp) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_misc ${CURRENT_PROJECT_NAME}_test_test_optional_compat) + +# TODO: Fix this +#[[ +if (EIGEN_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_eigen_interop_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_cpp_int.cpp) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_cpp_int PRIVATE ${EIGEN3_INCLUDE_DIRS}) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_eigen_interop_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_cpp_dec_float.cpp) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_cpp_dec_float PRIVATE ${EIGEN3_INCLUDE_DIRS}) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_eigen_interop_cpp_dec_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_cpp_dec_float_2.cpp) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_cpp_dec_float_2 PRIVATE ${EIGEN3_INCLUDE_DIRS}) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_eigen_interop_cpp_dec_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_cpp_dec_float_3.cpp) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_cpp_dec_float_3 PRIVATE ${EIGEN3_INCLUDE_DIRS}) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_eigen_interop_cpp_bin_float_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_cpp_bin_float_1.cpp) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_cpp_bin_float_1 PRIVATE ${EIGEN3_INCLUDE_DIRS}) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_eigen_interop_cpp_bin_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_cpp_bin_float_2.cpp) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_cpp_bin_float_2 PRIVATE ${EIGEN3_INCLUDE_DIRS}) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_eigen_interop_cpp_bin_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_cpp_bin_float_3.cpp) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_cpp_bin_float_3 PRIVATE ${EIGEN3_INCLUDE_DIRS}) +endif() + +if ((EIGEN_COMPILED) AND (MPFR_COMPILED)) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_eigen_interop_mpfr_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_mpfr_1.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_mpfr_1 ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_mpfr_1 PRIVATE ${EIGEN3_INCLUDE_DIRS} ${GMP_INCLUDE_DIRS}) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_eigen_interop_mpfr_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_mpfr_2.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_mpfr_2 ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_mpfr_2 PRIVATE ${EIGEN3_INCLUDE_DIRS} ${GMP_INCLUDE_DIRS}) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_eigen_interop_mpfr_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_mpfr_3.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_mpfr_3 ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_mpfr_3 PRIVATE ${EIGEN3_INCLUDE_DIRS} ${GMP_INCLUDE_DIRS}) +endif() + +if ((EIGEN_COMPILED) AND (GMP_COMPILED)) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_eigen_interop_gmp SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_gmp.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_gmp ${GMP_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_gmp PRIVATE ${EIGEN3_INCLUDE_DIRS} ${GMP_INCLUDE_DIRS}) +endif() + +if ((EIGEN_COMPILED) AND (MPC_COMPILED)) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_eigen_interop_mpc SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_mpc.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_mpc ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_eigen_interop_mpc PUBLIC ${EIGEN3_INCLUDE_DIRS} ${GMP_INCLUDE_DIRS}) +endif() +#]] + +#TODO: enable it +#[[ +if (BUILD_WITH_SOURCES_DIR) + file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/math/*.cpp) + foreach(FILEB ${TEST_FILES}) + get_filename_component(NAME ${FILEB} NAME_WE) + if(MPFR_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_math_${NAME}_mpfr SOURCES ${FILEB}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_math_${NAME}_mpfr PRIVATE -DTEST_MPFR_50 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(${CURRENT_PROJECT_NAME}_test_math_${NAME}_mpfr PRIVATE ${BUILD_WITH_SOURCES_DIR}/libs/math/include_private ${BUILD_WITH_SOURCES_DIR} ${GMP_INCLUDE_DIRS}) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_math_${NAME}_mpfr ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + endif() + + if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_math_${NAME}_mpf SOURCES ${FILEB}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_math_${NAME}_mpf PRIVATE -DTEST_MPF_50 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(${CURRENT_PROJECT_NAME}_test_math_${NAME}_mpf PRIVATE ${GMP_INCLUDE_DIRS} ${BUILD_WITH_SOURCES_DIR} ${BUILD_WITH_SOURCES_DIR}/libs/math/include_private) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_math_${NAME}_mpf ${GMP_LIBRARIES}) + endif() + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_math_${NAME}_cpp_dec_float SOURCES ${FILEB}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_math_${NAME}_cpp_dec_float PRIVATE -DTEST_CPP_DEC_FLOAT -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(${CURRENT_PROJECT_NAME}_test_math_${NAME}_cpp_dec_float PRIVATE ${BUILD_WITH_SOURCES_DIR} ${BUILD_WITH_SOURCES_DIR}/libs/math/include_private) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_math_${NAME}_cpp_bin_float SOURCES ${FILEB}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_math_${NAME}_cpp_bin_float PRIVATE -DTEST_CPP_BIN_FLOAT -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(${CURRENT_PROJECT_NAME}_test_math_${NAME}_cpp_bin_float PRIVATE ${BUILD_WITH_SOURCES_DIR} ${BUILD_WITH_SOURCES_DIR}/libs/math/include_private) + + if(FLOAT128_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_math_${NAME}_float128 SOURCES ${FILEB}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_math_${NAME}_float128 PRIVATE -DTEST_FLOAT128 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(${CURRENT_PROJECT_NAME}_test_math_${NAME}_float128 PRIVATE ${BUILD_WITH_SOURCES_DIR} ${BUILD_WITH_SOURCES_DIR}/libs/math/include_private) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_math_${NAME}_float128 ${QUADMATH_LIBRARIES}) + endif() + + if((FLOAT128_COMPILED) AND (HAS_INTEL_QUAD)) + #TODO: fix test + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_math_${NAME}_intel_quad SOURCES ${FILEB}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_math_${NAME}_intel_quad PRIVATE -DTEST_FLOAT128 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(${CURRENT_PROJECT_NAME}_test_math_${NAME}_intel_quad PRIVATE ${BUILD_WITH_SOURCES_DIR} ${BUILD_WITH_SOURCES_DIR}/libs/math/include_private) + endif() + endforeach() +endif() +]] + +#TODO: implicit entry/start for main executable +#[[ +if (BUILD_WITH_SOURCES_DIR) + file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/math/high_prec/*.cpp) + foreach(FILEB ${TEST_FILES}) + if(MPFR_COMPILED) + get_filename_component(NAME ${FILEB} NAME_WE) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_math_high_prec_${NAME} SOURCES ${FILEB}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_math_high_prec_${NAME} PRIVATE -DTEST_MPFR -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE -DBOOST_ALL_NO_LIB) + target_include_directories(${CURRENT_PROJECT_NAME}_test_math_high_prec_${NAME} PRIVATE ${GMP_INCLUDE_DIRS} ${BUILD_WITH_SOURCES_DIR} ${BUILD_WITH_SOURCES_DIR}/libs/math/include_private) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_math_high_prec_${NAME} ${GMP_LIBRARIES} ${MPFR_LIBRARIES}) + endif() + endforeach() +endif() +]] +file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/compile_fail/*.cpp) +foreach(FILEB ${TEST_FILES}) + if((GMP_COMPILED) AND (MPFR_COMPILED)) + get_filename_component(NAME ${FILEB} NAME_WE) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_compile_fail_${NAME} SOURCES ${FILEB} COMPILE_ONLY WILL_FAIL) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_compile_fail_${NAME} PRIVATE -DTEST_GMP -DTEST_MPFR) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_compile_fail ${CURRENT_PROJECT_NAME}_test_compile_fail_${NAME}) + endif() +endforeach() + +if(BUILD_WITH_SOURCES_DIR) + file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/concepts/*.cpp) + foreach(FILEB ${TEST_FILES}) + get_filename_component(NAME ${FILEB} NAME_WE) + + if(MPFR_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_50 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_50 PUBLIC -DTEST_MPFR_50) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_50 ${MPFR_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_50 PRIVATE ${BUILD_WITH_SOURCES_DIR}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_concepts ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_50) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_6 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_6 PUBLIC -DTEST_MPFR_6) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_6 ${MPFR_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_6 PRIVATE ${BUILD_WITH_SOURCES_DIR}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_concepts ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_6) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_15 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_15 PUBLIC -DTEST_MPFR_15) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_15 ${MPFR_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_15 PRIVATE ${BUILD_WITH_SOURCES_DIR}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_concepts ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_15) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_17 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_17 PUBLIC -DTEST_MPFR_17) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_17 ${MPFR_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_17 PRIVATE ${BUILD_WITH_SOURCES_DIR}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_concepts ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_17) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_30 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_30 PUBLIC -DTEST_MPFR_30) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_30 ${MPFR_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_30 PRIVATE ${BUILD_WITH_SOURCES_DIR}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_concepts ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpfr_30) + endif() + + if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpf50 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpf50 PUBLIC -DTEST_MPF_50) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpf50 ${GMP_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpf50 PRIVATE ${BUILD_WITH_SOURCES_DIR}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_concepts ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_mpf50) + endif() + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_cpp_dec_float SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) + target_include_directories(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_cpp_dec_float PRIVATE ${BUILD_WITH_SOURCES_DIR}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_concepts ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_cpp_dec_float) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_cpp_bin_float SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_cpp_bin_float PUBLIC -DTEST_CPP_BIN_FLOAT) + target_include_directories(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_cpp_bin_float PRIVATE ${BUILD_WITH_SOURCES_DIR}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_concepts ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_cpp_bin_float) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_cpp_dec_float_no_et SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_cpp_dec_float_no_et PUBLIC -DTEST_CPP_DEC_FLOAT_NO_ET) + target_include_directories(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_cpp_dec_float_no_et PRIVATE ${BUILD_WITH_SOURCES_DIR}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_concepts ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_cpp_dec_float_no_et) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_backend_concept SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_backend_concept PUBLIC -DTEST_BACKEND) + target_include_directories(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_backend_concept PRIVATE ${BUILD_WITH_SOURCES_DIR}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_concepts ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_backend_concept) + + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_logged_adaptor SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_logged_adaptor PUBLIC -DTEST_LOGGED_ADAPTER) + target_include_directories(${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_logged_adaptor PRIVATE ${BUILD_WITH_SOURCES_DIR}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_concepts ${CURRENT_PROJECT_NAME}_test_concepts_${NAME}_logged_adaptor) + endforeach() +endif() + +#test-suite examples + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_cpp_int_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/cpp_int_snips.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_cpp_int_snips no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_cpp_int_snips) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_cpp_int_import_export SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/cpp_int_import_export.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_cpp_int_import_export no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_cpp_int_import_export) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_cpp_bin_float_import_export SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/cpp_bin_float_import_export.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_cpp_bin_float_import_export no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_cpp_bin_float_import_export) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_cpp_dec_float_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/cpp_dec_float_snips.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_cpp_dec_float_snips no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_cpp_dec_float_snips) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_cpp_bin_float_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/cpp_bin_float_snips.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_cpp_bin_float_snips no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_cpp_bin_float_snips) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_debug_adaptor_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/debug_adaptor_snips.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_debug_adaptor_snips no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_debug_adaptor_snips) + +if(FLOAT128_COMPILED) + #TODO: fix this + #[ run float128_snips.cpp quadmath no_eh_eg_support : : : [ check-target-builds ../config//has_float128 : : no ] ] + # cm_test(NAME ${CURRENT_PROJECT_NAME}_test_debug_adaptor_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/debug_adaptor_snips.cpp) + # target_link_libraries(${CURRENT_PROJECT_NAME}_test_debug_adaptor_snips no_eh_support) + # add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_debug_adaptor_snips) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_floating_point_examples SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/floating_point_examples.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_floating_point_examples no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_floating_point_examples) + +#TODO: Enable this +#cm_test(NAME ${CURRENT_PROJECT_NAME}_test_gauss_laguerre_quadrature SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/gauss_laguerre_quadrature.cpp) +#target_link_libraries(${CURRENT_PROJECT_NAME}_test_gauss_laguerre_quadrature no_eh_support) + +#TODO: Fix this +#cm_test(NAME ${CURRENT_PROJECT_NAME}_test_hypergeometric_luke_algorithms SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/hypergeometric_luke_algorithms.cpp) +#target_link_libraries(${CURRENT_PROJECT_NAME}_test_hypergeometric_luke_algorithms no_eh_support) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_integer_examples SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/integer_examples.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_integer_examples no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_integer_examples) + +if(MPFI_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_logged_adaptor SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/logged_adaptor.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_logged_adaptor ${GMP_LIBRARIES} ${MPFR_LIBRARIES} ${MPFI_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_logged_adaptor PRIVATE ${GMP_INCLUDE_DIRS} ${MPFI_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_logged_adaptor) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_mixed_integer_arithmetic SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/mixed_integer_arithmetic.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_mixed_integer_arithmetic no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_mixed_integer_arithmetic) + +if(FLOAT128_COMPILED) + #TODO: fix this + #[ run numeric_limits_snips.cpp no_eh_eg_support /boost//test_exec_monitor : : : [ requires cxx11_numeric_limits ] [ check-target-builds ../config//has_float128 : quadmath ] ] +endif() + +if(GMP_COMPILED) + #TODO: enable this + #cm_test(NAME ${CURRENT_PROJECT_NAME}_test_random_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/random_snips.cpp) + #target_link_libraries(${CURRENT_PROJECT_NAME}_test_random_snips ${GMP_LIBRARIES} no_eh_support) + #target_include_directories(${CURRENT_PROJECT_NAME}_test_random_snips PRIVATE ${GMP_INCLUDE_DIRS}) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_safe_prime SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/safe_prime.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_safe_prime no_eh_support) +add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_safe_prime) + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_gmp_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/gmp_snips.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_gmp_snips ${GMP_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_gmp_snips PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_gmp_snips) +endif() + +if(MPFI_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_mpfi_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/mpfi_snips.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_mpfi_snips ${GMP_LIBRARIES} ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_mpfi_snips PRIVATE ${GMP_INCLUDE_DIRS} ${MPFI_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_mpfi_snips) +endif() + +if(MPFR_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_mpfr_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/mpfr_snips.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_mpfr_snips ${GMP_LIBRARIES} ${MPFR_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_mpfr_snips PRIVATE ${GMP_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_mpfr_snips) +endif() + +if(TOMMATH_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_tommath_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/tommath_snips.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_tommath_snips ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(${CURRENT_PROJECT_NAME}_test_tommath_snips PRIVATE ${TomMath_INCLUDE_DIRS}) + add_dependencies(${CURRENT_PROJECT_NAME}_test_suite_examples ${CURRENT_PROJECT_NAME}_test_tommath_snips) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_modular_examples SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/modular_examples.cpp) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_modular_examples no_eh_support) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_modular_adaptor_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_modular_adaptor.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_modular_adaptor_cpp_int PUBLIC -DTEST_CPP_INT) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_modular_adaptor_cpp_int no_eh_support) + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_modular_adaptor_gmp SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_modular_adaptor.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_modular_adaptor_gmp ${GMP_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_modular_adaptor_gmp PRIVATE ${GMP_INCLUDE_DIRS}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_modular_adaptor_gmp PUBLIC -DTEST_GMP) +endif() + +if(TOMMATH_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_modular_adaptor_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_modular_adaptor.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_modular_adaptor_tommath ${TomMath_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_modular_adaptor_tommath PRIVATE ${TomMath_INCLUDE_DIRS}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_modular_adaptor_tommath PUBLIC -DTEST_TOMMATH) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_jacobi_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_jacobi.cpp) +target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_jacobi_cpp_int PUBLIC -DTEST_CPP_INT) +target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_jacobi_cpp_int no_eh_support) + +if(GMP_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_jacobi_gmp SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_jacobi.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_jacobi_gmp ${GMP_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_jacobi_gmp PRIVATE ${GMP_INCLUDE_DIRS}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_jacobi_gmp PUBLIC -DTEST_GMP) +endif() + +if(TOMMATH_COMPILED) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_jacobi_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_jacobi.cpp) + target_link_libraries(${CURRENT_PROJECT_NAME}_test_test_jacobi_tommath ${TomMath_LIBRARIES}) + target_include_directories(${CURRENT_PROJECT_NAME}_test_test_jacobi_tommath PRIVATE ${TomMath_INCLUDE_DIRS}) + target_compile_definitions(${CURRENT_PROJECT_NAME}_test_test_jacobi_tommath PUBLIC -DTEST_TOMMATH) +endif() + +cm_test(NAME multiprecision_test_test_ressol_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ressol.cpp) +target_compile_definitions(multiprecision_test_test_ressol_cpp_int PUBLIC -DTEST_CPP_INT) +target_link_libraries(multiprecision_test_test_ressol_cpp_int no_eh_support) + +if(GMP_COMPILED) + cm_test(NAME multiprecision_test_test_ressol_gmp SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ressol.cpp) + target_link_libraries(multiprecision_test_test_ressol_gmp ${GMP_LIBRARIES}) + target_include_directories(multiprecision_test_test_ressol_gmp PRIVATE ${GMP_INCLUDE_DIRS}) + target_compile_definitions(multiprecision_test_test_ressol_gmp PUBLIC -DTEST_GMP) +endif() + +if(TOMMATH_COMPILED) + cm_test(NAME multiprecision_test_test_ressol_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ressol.cpp) + target_link_libraries(multiprecision_test_test_ressol_tommath ${TomMath_LIBRARIES}) + target_include_directories(multiprecision_test_test_ressol_tommath PRIVATE ${TomMath_INCLUDE_DIRS}) + target_compile_definitions(multiprecision_test_test_ressol_tommath PUBLIC -DTEST_TOMMATH) +endif() + +cm_test(NAME multiprecision_test_test_inverse_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_inverse.cpp) +target_compile_definitions(multiprecision_test_test_inverse_cpp_int PUBLIC -DTEST_CPP_INT) +target_link_libraries(multiprecision_test_test_inverse_cpp_int no_eh_support) + +include_directories(${CMAKE_WORKSPACE_SOURCES_DIR}) + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 8b4ee429b..b45090e4d 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -183,6 +183,31 @@ test-suite arithmetic_tests : [ run test_arithmetic_complex_adaptor_2.cpp : : : msvc:-bigobj ] [ run test_arithmetic_complex128.cpp : : : [ check-target-builds ../config//has_float128 : quadmath ] ] + [ run test_modular_adaptor.cpp no_eh_support + : # command line + : # input files + : # requirements + TEST_CPP_INT + : test_modular_adaptor_cpp_int ] + + [ run test_modular_adaptor.cpp no_eh_support $(TOMMATH) + : # command line + : # input files + : # requirements + TEST_TOMMATH + release # Otherwise [ runtime is slow + [ check-target-builds ../config//has_tommath : : no ] + : test_modular_adaptor_tommath ] + + [ run test_modular_adaptor.cpp no_eh_support gmp + : # command line + : # input files + : # requirements + TEST_GMP + release # Otherwise [ runtime is slow + [ check-target-builds ../config//has_gmp : : no ] + : test_modular_adaptor_gmp ] + ; rule get_function_tests @@ -398,6 +423,31 @@ test-suite functions_and_limits : TEST_CPP_INT : test_move_cpp_int ] + [ run test_jacobi.cpp no_eh_support + : # command line + : # input files + : # requirements + TEST_CPP_INT + : test_jacobi_cpp_int ] + + [ run test_jacobi.cpp $(TOMMATH) no_eh_support + : # command line + : # input files + : # requirements + TEST_TOMMATH + release # Otherwise [ runtime is slow + [ check-target-builds ../config//has_tommath : : no ] + : test_jacobi_tommath ] + + [ run test_jacobi.cpp gmp no_eh_support + : # command line + : # input files + : # requirements + TEST_MPZ + release # Otherwise [ runtime is slow + [ check-target-builds ../config//has_gmp : : no ] + : test_jacobi_gmp ] + [ run test_sin_near_half_pi.cpp mpfr gmp : : : TEST_CPP_BIN_FLOAT release [ check-target-builds ../config//has_float128 : quadmath : ] [ check-target-builds ../config//has_mpfr : : no ] : test_sin_near_half_pi_cpp_bin_float ] [ run test_sin_near_half_pi.cpp mpfr gmp : : : TEST_CPP_DEC_FLOAT release [ check-target-builds ../config//has_mpfr : : no ] : test_sin_near_half_pi_cpp_dec_float ] [ run test_sin_near_half_pi.cpp mpfr gmp : : : TEST_MPF_50 release [ check-target-builds ../config//has_mpfr : : no ] : test_sin_near_half_pi_mpf_50 ] diff --git a/test/test_inverse.cpp b/test/test_inverse.cpp new file mode 100644 index 000000000..8838678ce --- /dev/null +++ b/test/test_inverse.cpp @@ -0,0 +1,131 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2018-2020 Mikhail Komarov +// Copyright (c) 2018-2020 Pavel Kharitonov +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifdef _MSC_VER +#define _SCL_SECURE_NO_WARNINGS +#endif + +#include "test.hpp" + +#if !defined(TEST_CPP_INT) +#define TEST_CPP_INT +#endif + +#ifdef TEST_CPP_INT +#include +#endif + +#include +#include +#include +#include +#include + +template +void test_cpp_int() +{ + //test for monty_inverse + BOOST_CHECK_EQUAL(monty_inverse(T(12), T(5), T(5)),T(1823)); + BOOST_CHECK_EQUAL(monty_inverse(T(10), T(37), T(1)),T(26)); + BOOST_CHECK_EQUAL(monty_inverse(T(3), T(2), T(3)),T(3)); + BOOST_CHECK_EQUAL(monty_inverse(T(3), T(4), T(2)), T(11)); + BOOST_CHECK_EQUAL(monty_inverse(T(4), T(7), T(2)), T(37)); + BOOST_CHECK_EQUAL(monty_inverse(T(32), T(247), T(1)), T(193)); + BOOST_CHECK_EQUAL(monty_inverse(T(3), T(7), T(7)), T(549029)); + BOOST_CHECK_EQUAL(monty_inverse(T(5317589), T(23), T(8)), T(32104978469)); + + //test for inverse with extended euclidean algorithm + BOOST_CHECK_EQUAL(monty_inverse(T(12), T(5), T(5)),T(1823)); + BOOST_CHECK_EQUAL(monty_inverse(T(10), T(37), T(1)),T(26)); + BOOST_CHECK_EQUAL(monty_inverse(T(3), T(2), T(3)),T(3)); + BOOST_CHECK_EQUAL(monty_inverse(T(3), T(4), T(2)), T(11)); + BOOST_CHECK_EQUAL(monty_inverse(T(4), T(7), T(2)), T(37)); + BOOST_CHECK_EQUAL(monty_inverse(T(32), T(247), T(1)), T(193)); + BOOST_CHECK_EQUAL(monty_inverse(T(3), T(7), T(7)), T(549029)); + BOOST_CHECK_EQUAL(monty_inverse(T(5317589), T(23), T(8)), T(32104978469)); + + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(5), T("0x7fffffffffffffffffffffffffffffff")), T("0x33333333333333333333333333333333")); + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(333), T("0x7fffffffffffffffffffffffffffffff")), T("0x17d4f2ee517d4f2ee517d4f2ee517d4f")); + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T("0x435b21e35ccd62dbdbafa1368cf742f0"), T("0x7fffffffffffffffffffffffffffffff")), T("0x604ddb74e5a55e559a7320e45b06eaf6")); + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(2), T("0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), + T("0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(3), T(8)),T(3)); + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(46), T(207)),T(0)); + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(2), T(2)),T(0)); + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(0), T(2)), T(0)); + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(46), T(46)), T(0)); + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(1), T(7)), T(1)); + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(35), T(118)), T(27)); + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(37), T(37)), T(0)); + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(32), T(247)), T(193)); + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(3), T(232)), T(155)); + + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T("256992387993922882115519242002267204163958280694902854777438773165028812741820300742384101620467227297951260702776745365693102268609333941403372929142489383748076291"), + T("3105560673298506328472089385746585896322911006740772751605160752499227148385424850362140158165019680645739648726058090243814223511639161631852729287604717869259565828")), + T("2322484593360248972803085811686365806060063797313230509497970163285203519904646342173323688226147654544918783691327115436052292182385106099615339567513136063879840431")); + + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T("65790051326444257821572925952580404270899173102825542663868894627884582709571518677209748416019817305674876843604308670298295897660589296995641401495105646770364032950"), + T("1460598742727828605836860681156746006166272494387112693708892744343548055514972863039476201659720247220048664250204314648520085411164461712526657028588699682983099362771")), + T("370134468809235355809931021496418560257927761651782631431723120822241707286126622619231228275210678415132318220494260963802381448709723310690465171935975287188943190781")); + + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(3), T(0x10)), T(11)); + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(43000466091), T(0x10000000000)), T(140404367363)); + + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T("3329223706171052463206866408355190852145308853551222855374206553291583641200362811169867167522066732427259441069045458590915570173077273266668323626418910290729833115917608762612451607036836604560196526748133295229482315432160861956985661720415008502817376589122369169168503051700575534361360734357915507005267791266056164843197115173542457409178397682412186017844044878477733706673665949312479502081417286848135607066940796741261651879705761216547813649105594986990007847567220787224253724912309650653332895570458720843322485065681189768697291752149748575893233520856711838140401691494532333502278879425087656782163494363567584633848194784070822245649557468578497368723157561724530746784741768646102936863260630088882545875047173194357829837349405264332156553159"), + T("5159669275902268897019683770634129859849131442089512209466255369748647885295043458100453095139637532489732379349334183998359005271540851438475735390060160055101459757369025094548935216928274885474920588457238932199212826132848112983030207228729230350143070245214615032330098373606816857555487378911597356175295963296209024100980888874174104384926439773409352855895683162800486061893625461339248419592365333197671396390223849652458316548872173632032072142493359961192701645150390051578875246900773560274606831152842526302321197703270752422496079310760804228859682734104661333367088085354635701827808417686374790164642660390557925243983808216928421220094838103017958334974205040660858707963225716195222460679137994123278276584663712976241848458904056941218720227786752")), + T("1616976508685598612715404615539711729591496303838727278361745768459912744766103110805335531789260471902032668556823877781797119177369744675655036227693862387901335929380526158525335617191171199406261059141492729550964383378755592271377330924178695575317855482198418687207284119472436638891655267287870468947394828003595194476459620373954194618413638984959865778647102302286558592688810633664007264011579909176526804508142200273299822852592676936629738013383103344642638188458260268481981965239756241374381655466503673701310357329513881591759718900992472283603129650577355418728929787837071330285526447596817142247043818915739644061292726006592557005008244120258692943705325131549610392209481948231318177450181776222904306153521050324221361215524333142914455291939319")); + BOOST_CHECK_EQUAL(inverse_extended_euclidean_algorithm(T(65279), T("0x100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")), + T("21361914537342414713552871917029943574709104078599594478169627833328205584507146367057038170698710253677755075362127788711957331760388539866898398399344480664991941861081743615")); +} + +template +void test_cpp_int_backend() +{ + + using namespace boost::multiprecision; + number res; + + number > modular; + + modular = number >(10, 37); + modular.backend().mod_data().adjust_regular(res.backend(), inverse_extended_euclidean_algorithm(modular).backend().base_data()); + BOOST_CHECK_EQUAL(cpp_int(res.backend()), cpp_int(26)); + + modular = number >(3, 8); + modular.backend().mod_data().adjust_regular(res.backend(), inverse_extended_euclidean_algorithm(modular).backend().base_data()); + BOOST_CHECK_EQUAL(cpp_int(res.backend()), cpp_int(3)); + + modular = number >(3, 16); + modular.backend().mod_data().adjust_regular(res.backend(), inverse_extended_euclidean_algorithm(modular).backend().base_data()); + BOOST_CHECK_EQUAL(cpp_int(res.backend()), cpp_int(11)); + + modular = number >(65279, "0x100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + modular.backend().mod_data().adjust_regular(res.backend(), inverse_extended_euclidean_algorithm(modular).backend().base_data()); + BOOST_CHECK_EQUAL(cpp_int(res.backend()), cpp_int("21361914537342414713552871917029943574709104078599594478169627833328205584507146367057038170698710253677755075362127788711957331760388539866898398399344480664991941861081743615")); + + modular = number >("3329223706171052463206866408355190852145308853551222855374206553291583641200362811169867167522066732427259441069045458590915570173077273266668323626418910290729833115917608762612451607036836604560196526748133295229482315432160861956985661720415008502817376589122369169168503051700575534361360734357915507005267791266056164843197115173542457409178397682412186017844044878477733706673665949312479502081417286848135607066940796741261651879705761216547813649105594986990007847567220787224253724912309650653332895570458720843322485065681189768697291752149748575893233520856711838140401691494532333502278879425087656782163494363567584633848194784070822245649557468578497368723157561724530746784741768646102936863260630088882545875047173194357829837349405264332156553159", + "5159669275902268897019683770634129859849131442089512209466255369748647885295043458100453095139637532489732379349334183998359005271540851438475735390060160055101459757369025094548935216928274885474920588457238932199212826132848112983030207228729230350143070245214615032330098373606816857555487378911597356175295963296209024100980888874174104384926439773409352855895683162800486061893625461339248419592365333197671396390223849652458316548872173632032072142493359961192701645150390051578875246900773560274606831152842526302321197703270752422496079310760804228859682734104661333367088085354635701827808417686374790164642660390557925243983808216928421220094838103017958334974205040660858707963225716195222460679137994123278276584663712976241848458904056941218720227786752"); + modular.backend().mod_data().adjust_regular(res.backend(), inverse_extended_euclidean_algorithm(modular).backend().base_data()); + BOOST_CHECK_EQUAL(cpp_int(res.backend()), cpp_int("1616976508685598612715404615539711729591496303838727278361745768459912744766103110805335531789260471902032668556823877781797119177369744675655036227693862387901335929380526158525335617191171199406261059141492729550964383378755592271377330924178695575317855482198418687207284119472436638891655267287870468947394828003595194476459620373954194618413638984959865778647102302286558592688810633664007264011579909176526804508142200273299822852592676936629738013383103344642638188458260268481981965239756241374381655466503673701310357329513881591759718900992472283603129650577355418728929787837071330285526447596817142247043818915739644061292726006592557005008244120258692943705325131549610392209481948231318177450181776222904306153521050324221361215524333142914455291939319")); + + modular = number >(43000466091, 0x10000000000); + modular.backend().mod_data().adjust_regular(res.backend(), inverse_extended_euclidean_algorithm(modular).backend().base_data()); + BOOST_CHECK_EQUAL(cpp_int(res.backend()), cpp_int(140404367363)); +} + +int main() +{ +#ifdef TEST_CPP_INT + test_cpp_int(); + test_cpp_int_backend>(); +#endif + + return boost::report_errors(); +} + diff --git a/test/test_jacobi.cpp b/test/test_jacobi.cpp new file mode 100644 index 000000000..8e01745f4 --- /dev/null +++ b/test/test_jacobi.cpp @@ -0,0 +1,65 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2020 Mikhail Komarov. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt + +#ifdef _MSC_VER +#define _SCL_SECURE_NO_WARNINGS +#endif + +#include "test.hpp" + +#if !defined(TEST_MPZ) && !defined(TEST_TOMMATH) && !defined(TEST_CPP_INT) +#define TEST_TOMMATH +#define TEST_MPZ +#define TEST_CPP_INT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPZ) +#include +#endif +#if defined(TEST_TOMMATH) +#include +#endif +#if defined(TEST_CPP_INT) +#include +#endif + +#include + +template +void test() +{ + using namespace boost::multiprecision; + + BOOST_CHECK_EQUAL(jacobi(T(5), T(9)), 1); + BOOST_CHECK_EQUAL(jacobi(T(1), T(27)), 1); + BOOST_CHECK_EQUAL(jacobi(T(2), T(27)), -1); + BOOST_CHECK_EQUAL(jacobi(T(3), T(27)), 0); + BOOST_CHECK_EQUAL(jacobi(T(4), T(27)), 1); +} + +int main() +{ + using namespace boost::multiprecision; + +#if defined(TEST_CPP_INT) + test(); +#endif +#if defined(TEST_MPZ) + test(); +#endif +#if defined(TEST_TOMMATH) + test(); +#endif + + return boost::report_errors(); +} diff --git a/test/test_modular_adaptor.cpp b/test/test_modular_adaptor.cpp new file mode 100644 index 000000000..f7ea902af --- /dev/null +++ b/test/test_modular_adaptor.cpp @@ -0,0 +1,210 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2020 Mikhail Komarov +// Copyright (c) 2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#include +#include + +#include +#include + +#ifdef TEST_CPP_INT +#include +#include +#endif + +#ifdef TEST_GMP +#include +#include +#endif + +#ifdef TEST_TOMMATH +#include +#include +#endif + +#include "test.hpp" + +static const std::string even_mod[] = {"8", "64", "31232", "3242343244", "32444223445648", "2342345878437578", "39083287423897423784987234876"}; +static const std::string odd_mod[] = {"7", "23", "23133", "384828945", "938423847897893", "58976234672378752477", "345943598934088945908589591"}; + +static const std::string big_numbers[] = {"3777078316807535813265472776245476795571913941214974396352", + "7730650700335662967298805496078834074815880969722197781616", + "76666273003804943755065306388850182474417757120635316375"}; + +static const size_t numbers_size[] = {8, 16, 20, 25, 30, 35, 40}; + +using namespace boost::multiprecision; + +template +void base_operators() +{ + typedef number > modular_number; + typedef modular_params params_number; + typedef number standard_number; + + for (size_t current_number_size = 0; current_number_size < 7; ++current_number_size) + { + for (size_t parity = 0; parity <= 1; ++parity) + { + std::string a_string = big_numbers[0].substr(0, numbers_size[current_number_size]); + std::string b_string = big_numbers[1].substr(0, numbers_size[current_number_size]); + std::string mod_string; + if (parity) + mod_string = odd_mod[current_number_size]; + else + mod_string = even_mod[current_number_size]; + + standard_number a_s(a_string), b_s(b_string), mod_s(mod_string), result_s(0); + + params_number mod(mod_s); + modular_number a(a_s, mod), b(b_s, mod), result(0, mod); + result = a + b; + result_s = result.template convert_to(); + BOOST_CHECK_EQUAL(result_s, (a_s + b_s) % mod_s); + + result = a - b; + result_s = result.template convert_to(); + if (a_s < b_s) + { + BOOST_CHECK_EQUAL(result_s, (a_s - b_s) % mod_s + mod_s); + } + else + { + BOOST_CHECK_EQUAL(result_s, (a_s - b_s) % mod_s); + } + + result = a * b; + result_s = result.template convert_to(); + BOOST_CHECK_EQUAL(result_s, (a_s * b_s) % mod_s); + + result = a / b; + result_s = result.template convert_to(); + BOOST_CHECK_EQUAL(result_s, ((a_s % mod_s) / (b_s % mod_s))); + + result = a % b; + result_s = result.template convert_to(); + BOOST_CHECK_EQUAL(result_s, ((a_s % mod_s) % (b_s % mod_s))); + } + } +} + +template +void comparsion_operators() +{ + typedef number > modular_number; + typedef modular_params params_number; + typedef number standard_number; + + for (size_t current_number_size = 0; current_number_size < 7; ++current_number_size) + { + for (size_t parity = 0; parity <= 1; ++parity) + { + std::string a_string = big_numbers[0].substr(0, numbers_size[current_number_size]); + std::string b_string = big_numbers[1].substr(0, numbers_size[current_number_size]); + std::string mod_string; + if (parity) + mod_string = odd_mod[current_number_size]; + else + mod_string = even_mod[current_number_size]; + + standard_number a_s(a_string), b_s(b_string), mod_s(mod_string), result_s(0); + params_number mod(mod_s); + modular_number a(a_s, mod), b(b_s, mod); + + BOOST_CHECK_EQUAL(a < b, (a_s % mod_s) < (b_s % mod_s)); + BOOST_CHECK_EQUAL(a <= b, (a_s % mod_s) <= (b_s % mod_s)); + BOOST_CHECK_EQUAL(a > b, (a_s % mod_s) > (b_s % mod_s)); + BOOST_CHECK_EQUAL(a >= b, (a_s % mod_s) >= (b_s % mod_s)); + BOOST_CHECK_EQUAL(a == b, (a_s % mod_s) == (b_s % mod_s)); + BOOST_CHECK_EQUAL(a != b, (a_s % mod_s) != (b_s % mod_s)); + } + } +} + +template +void bitwise_operators() +{ + typedef number > modular_number; + typedef modular_params params_number; + typedef number standard_number; + + for (size_t current_number_size = 0; current_number_size < 7; ++current_number_size) + { + for (size_t parity = 0; parity <= 1; ++parity) + { + std::string a_string = big_numbers[0].substr(0, numbers_size[current_number_size]); + std::string b_string = big_numbers[1].substr(0, numbers_size[current_number_size]); + std::string mod_string; + if (parity) + mod_string = odd_mod[current_number_size]; + else + mod_string = even_mod[current_number_size]; + + standard_number a_s(a_string), b_s(b_string), mod_s(mod_string), result_s(0); + params_number mod(mod_s); + modular_number a(a_s, mod), b(b_s, mod), result(0, mod); + + BOOST_CHECK_EQUAL((a & b).template convert_to(), (((a_s % mod_s) & (b_s % mod_s))) % mod_s); + BOOST_CHECK_EQUAL((a | b).template convert_to(), (((a_s % mod_s) | (b_s % mod_s))) % mod_s); + BOOST_CHECK_EQUAL((a ^ b).template convert_to(), (((a_s % mod_s) ^ (b_s % mod_s))) % mod_s); + } + } +} + +template +void pow_test() +{ + typedef number > modular_number; + typedef modular_params params_number; + typedef number standard_number; + + for (size_t current_number_size = 0; current_number_size < 7; ++current_number_size) + { + for (size_t parity = 0; parity <= 1; ++parity) + { + std::string a_string = big_numbers[0].substr(0, numbers_size[current_number_size]); + std::string b_string = big_numbers[1].substr(0, numbers_size[current_number_size]); + std::string mod_string; + if (parity) + mod_string = odd_mod[current_number_size]; + else + mod_string = even_mod[current_number_size]; + + standard_number a_s(a_string), b_s(b_string), mod_s(mod_string), result_s(0); + params_number mod(mod_s); + modular_number a(a_s, mod), b(b_s, mod), result(0, mod); + BOOST_CHECK_EQUAL(pow(a, b).template convert_to(), powm(a_s % mod_s, b_s % mod_s, mod_s)); + } + } +} + +template +void run_tests() +{ + base_operators(); + comparsion_operators(); + bitwise_operators(); + pow_test(); +} + +int main() +{ +#ifdef TEST_CPP_INT + run_tests >(); +#endif + +#ifdef TEST_GMP + run_tests(); +#endif + +#ifdef TEST_TOMMATH + run_tests(); +#endif + return boost::report_errors(); +} diff --git a/test/test_ressol.cpp b/test/test_ressol.cpp new file mode 100644 index 000000000..d71a20ef6 --- /dev/null +++ b/test/test_ressol.cpp @@ -0,0 +1,76 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2018-2020 Mikhail Komarov +// Copyright (c) 2018-2020 Pavel Kharitonov +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifdef _MSC_VER +#define _SCL_SECURE_NO_WARNINGS +#endif + +#include "test.hpp" + +#if !defined(TEST_MPZ) && !defined(TEST_TOMMATH) && !defined(TEST_CPP_INT) +#define TEST_TOMMATH +#define TEST_MPZ +#define TEST_CPP_INT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPZ) +#include +#endif +#if defined(TEST_TOMMATH) +#include +#endif +#ifdef TEST_CPP_INT +#include +#endif + +#include + +template +void test() +{ + using namespace boost::multiprecision; + + BOOST_CHECK_EQUAL(ressol(T(5), T(11)), 4); + BOOST_CHECK_EQUAL(ressol(T(5), T("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151")), T("5128001483797946816458955548662741861156429216952843873274631897232136999791540518339021539968609345897897688700798659762992302941280478805021587896033442584")); + BOOST_CHECK_EQUAL(ressol(T(4), T("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057149")), -1); + BOOST_CHECK_EQUAL(ressol(T("20749193632488214633180774027217139706413443729200940480695355894185"), T("26959946667150639794667015087019630673557916260026308143510066298881")), T("1825097171398375765346899906888660610489759292065918530856859649959")); + BOOST_CHECK_EQUAL(ressol(T(64), T(85)), -1); + BOOST_CHECK_EQUAL(ressol(T(181), T(217)), -1); + BOOST_CHECK_EQUAL(ressol(T(4225), T(33153)), -1); + BOOST_CHECK_EQUAL(ressol(T(2048), T(31417)), -1); + BOOST_CHECK_EQUAL(ressol(T(2), T(4369)), -1); + BOOST_CHECK_EQUAL(ressol(T(1024), T("0x40000000000000000000000000000000000000000000000000000000000c100000000000000ffff")), 32); + BOOST_CHECK_EQUAL(ressol(T(1024), T(174763)), 174731); + BOOST_CHECK_EQUAL(ressol(T(1025), T("0x40000000000000000000000000000000000000000000000000000000000c100000000000000ffff")), T("7195614950510915163755738138441999335431224576038191833055420996031360079131617522512565985187")); + BOOST_CHECK_EQUAL(ressol(T(16), T("0x40000000000000000000000000000000000000000000000000000000000c100000000000000ffff")), 4); + BOOST_CHECK_EQUAL(ressol(T(120846049), T("0x40000000000000000000000000000000000000000000000000000000000c100000000000000ffff")), T("0x40000000000000000000000000000000000000000000000000000000000c100000000000000d50e")); +} + +int main() +{ +#ifdef TEST_CPP_INT + test(); +#endif +#ifdef TEST_MPZ + test(); +#endif +#if defined(TEST_TOMMATH) + test(); +#endif + + return boost::report_errors(); +}