mqt-core 3.3.2__cp314-cp314t-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mqt/core/__init__.py +89 -0
- mqt/core/__main__.py +55 -0
- mqt/core/_commands.py +52 -0
- mqt/core/_compat/__init__.py +11 -0
- mqt/core/_compat/typing.py +29 -0
- mqt/core/_version.py +34 -0
- mqt/core/_version.pyi +12 -0
- mqt/core/bin/mqt-core-algorithms.dll +0 -0
- mqt/core/bin/mqt-core-circuit-optimizer.dll +0 -0
- mqt/core/bin/mqt-core-dd.dll +0 -0
- mqt/core/bin/mqt-core-ds.dll +0 -0
- mqt/core/bin/mqt-core-fomac.dll +0 -0
- mqt/core/bin/mqt-core-ir.dll +0 -0
- mqt/core/bin/mqt-core-na-fomac.dll +0 -0
- mqt/core/bin/mqt-core-na.dll +0 -0
- mqt/core/bin/mqt-core-qasm.dll +0 -0
- mqt/core/bin/mqt-core-qdmi-driver.dll +0 -0
- mqt/core/bin/mqt-core-qdmi-na-device.dll +0 -0
- mqt/core/bin/mqt-core-zx.dll +0 -0
- mqt/core/dd.cp314t-win_amd64.pyd +0 -0
- mqt/core/dd.pyi +1016 -0
- mqt/core/dd_evaluation.py +368 -0
- mqt/core/fomac.cp314t-win_amd64.pyd +0 -0
- mqt/core/fomac.pyi +125 -0
- mqt/core/include/mqt-core/algorithms/BernsteinVazirani.hpp +39 -0
- mqt/core/include/mqt-core/algorithms/GHZState.hpp +18 -0
- mqt/core/include/mqt-core/algorithms/Grover.hpp +33 -0
- mqt/core/include/mqt-core/algorithms/QFT.hpp +21 -0
- mqt/core/include/mqt-core/algorithms/QPE.hpp +30 -0
- mqt/core/include/mqt-core/algorithms/RandomCliffordCircuit.hpp +22 -0
- mqt/core/include/mqt-core/algorithms/StatePreparation.hpp +43 -0
- mqt/core/include/mqt-core/algorithms/WState.hpp +18 -0
- mqt/core/include/mqt-core/algorithms/mqt_core_algorithms_export.h +43 -0
- mqt/core/include/mqt-core/boost/config/abi/borland_prefix.hpp +27 -0
- mqt/core/include/mqt-core/boost/config/abi/borland_suffix.hpp +12 -0
- mqt/core/include/mqt-core/boost/config/abi/msvc_prefix.hpp +22 -0
- mqt/core/include/mqt-core/boost/config/abi/msvc_suffix.hpp +8 -0
- mqt/core/include/mqt-core/boost/config/abi_prefix.hpp +25 -0
- mqt/core/include/mqt-core/boost/config/abi_suffix.hpp +25 -0
- mqt/core/include/mqt-core/boost/config/assert_cxx03.hpp +211 -0
- mqt/core/include/mqt-core/boost/config/assert_cxx11.hpp +212 -0
- mqt/core/include/mqt-core/boost/config/assert_cxx14.hpp +47 -0
- mqt/core/include/mqt-core/boost/config/assert_cxx17.hpp +65 -0
- mqt/core/include/mqt-core/boost/config/assert_cxx20.hpp +59 -0
- mqt/core/include/mqt-core/boost/config/assert_cxx23.hpp +41 -0
- mqt/core/include/mqt-core/boost/config/assert_cxx98.hpp +23 -0
- mqt/core/include/mqt-core/boost/config/auto_link.hpp +525 -0
- mqt/core/include/mqt-core/boost/config/compiler/borland.hpp +342 -0
- mqt/core/include/mqt-core/boost/config/compiler/clang.hpp +370 -0
- mqt/core/include/mqt-core/boost/config/compiler/clang_version.hpp +89 -0
- mqt/core/include/mqt-core/boost/config/compiler/codegear.hpp +389 -0
- mqt/core/include/mqt-core/boost/config/compiler/comeau.hpp +59 -0
- mqt/core/include/mqt-core/boost/config/compiler/common_edg.hpp +185 -0
- mqt/core/include/mqt-core/boost/config/compiler/compaq_cxx.hpp +19 -0
- mqt/core/include/mqt-core/boost/config/compiler/cray.hpp +446 -0
- mqt/core/include/mqt-core/boost/config/compiler/diab.hpp +26 -0
- mqt/core/include/mqt-core/boost/config/compiler/digitalmars.hpp +146 -0
- mqt/core/include/mqt-core/boost/config/compiler/gcc.hpp +386 -0
- mqt/core/include/mqt-core/boost/config/compiler/gcc_xml.hpp +115 -0
- mqt/core/include/mqt-core/boost/config/compiler/greenhills.hpp +28 -0
- mqt/core/include/mqt-core/boost/config/compiler/hp_acc.hpp +153 -0
- mqt/core/include/mqt-core/boost/config/compiler/intel.hpp +577 -0
- mqt/core/include/mqt-core/boost/config/compiler/kai.hpp +33 -0
- mqt/core/include/mqt-core/boost/config/compiler/metrowerks.hpp +201 -0
- mqt/core/include/mqt-core/boost/config/compiler/mpw.hpp +143 -0
- mqt/core/include/mqt-core/boost/config/compiler/nvcc.hpp +64 -0
- mqt/core/include/mqt-core/boost/config/compiler/pathscale.hpp +141 -0
- mqt/core/include/mqt-core/boost/config/compiler/pgi.hpp +23 -0
- mqt/core/include/mqt-core/boost/config/compiler/sgi_mipspro.hpp +29 -0
- mqt/core/include/mqt-core/boost/config/compiler/sunpro_cc.hpp +225 -0
- mqt/core/include/mqt-core/boost/config/compiler/vacpp.hpp +189 -0
- mqt/core/include/mqt-core/boost/config/compiler/visualc.hpp +398 -0
- mqt/core/include/mqt-core/boost/config/compiler/xlcpp.hpp +303 -0
- mqt/core/include/mqt-core/boost/config/compiler/xlcpp_zos.hpp +174 -0
- mqt/core/include/mqt-core/boost/config/detail/cxx_composite.hpp +218 -0
- mqt/core/include/mqt-core/boost/config/detail/posix_features.hpp +95 -0
- mqt/core/include/mqt-core/boost/config/detail/select_compiler_config.hpp +157 -0
- mqt/core/include/mqt-core/boost/config/detail/select_platform_config.hpp +147 -0
- mqt/core/include/mqt-core/boost/config/detail/select_stdlib_config.hpp +121 -0
- mqt/core/include/mqt-core/boost/config/detail/suffix.hpp +1334 -0
- mqt/core/include/mqt-core/boost/config/header_deprecated.hpp +26 -0
- mqt/core/include/mqt-core/boost/config/helper_macros.hpp +37 -0
- mqt/core/include/mqt-core/boost/config/no_tr1/cmath.hpp +28 -0
- mqt/core/include/mqt-core/boost/config/no_tr1/complex.hpp +28 -0
- mqt/core/include/mqt-core/boost/config/no_tr1/functional.hpp +28 -0
- mqt/core/include/mqt-core/boost/config/no_tr1/memory.hpp +28 -0
- mqt/core/include/mqt-core/boost/config/no_tr1/utility.hpp +28 -0
- mqt/core/include/mqt-core/boost/config/platform/aix.hpp +33 -0
- mqt/core/include/mqt-core/boost/config/platform/amigaos.hpp +15 -0
- mqt/core/include/mqt-core/boost/config/platform/beos.hpp +26 -0
- mqt/core/include/mqt-core/boost/config/platform/bsd.hpp +83 -0
- mqt/core/include/mqt-core/boost/config/platform/cloudabi.hpp +18 -0
- mqt/core/include/mqt-core/boost/config/platform/cray.hpp +18 -0
- mqt/core/include/mqt-core/boost/config/platform/cygwin.hpp +71 -0
- mqt/core/include/mqt-core/boost/config/platform/haiku.hpp +31 -0
- mqt/core/include/mqt-core/boost/config/platform/hpux.hpp +87 -0
- mqt/core/include/mqt-core/boost/config/platform/irix.hpp +31 -0
- mqt/core/include/mqt-core/boost/config/platform/linux.hpp +106 -0
- mqt/core/include/mqt-core/boost/config/platform/macos.hpp +87 -0
- mqt/core/include/mqt-core/boost/config/platform/qnxnto.hpp +31 -0
- mqt/core/include/mqt-core/boost/config/platform/solaris.hpp +31 -0
- mqt/core/include/mqt-core/boost/config/platform/symbian.hpp +97 -0
- mqt/core/include/mqt-core/boost/config/platform/vms.hpp +25 -0
- mqt/core/include/mqt-core/boost/config/platform/vxworks.hpp +422 -0
- mqt/core/include/mqt-core/boost/config/platform/wasm.hpp +23 -0
- mqt/core/include/mqt-core/boost/config/platform/win32.hpp +90 -0
- mqt/core/include/mqt-core/boost/config/platform/zos.hpp +32 -0
- mqt/core/include/mqt-core/boost/config/pragma_message.hpp +31 -0
- mqt/core/include/mqt-core/boost/config/requires_threads.hpp +92 -0
- mqt/core/include/mqt-core/boost/config/stdlib/dinkumware.hpp +324 -0
- mqt/core/include/mqt-core/boost/config/stdlib/libcomo.hpp +93 -0
- mqt/core/include/mqt-core/boost/config/stdlib/libcpp.hpp +180 -0
- mqt/core/include/mqt-core/boost/config/stdlib/libstdcpp3.hpp +482 -0
- mqt/core/include/mqt-core/boost/config/stdlib/modena.hpp +79 -0
- mqt/core/include/mqt-core/boost/config/stdlib/msl.hpp +98 -0
- mqt/core/include/mqt-core/boost/config/stdlib/roguewave.hpp +208 -0
- mqt/core/include/mqt-core/boost/config/stdlib/sgi.hpp +168 -0
- mqt/core/include/mqt-core/boost/config/stdlib/stlport.hpp +258 -0
- mqt/core/include/mqt-core/boost/config/stdlib/vacpp.hpp +74 -0
- mqt/core/include/mqt-core/boost/config/stdlib/xlcpp_zos.hpp +61 -0
- mqt/core/include/mqt-core/boost/config/user.hpp +133 -0
- mqt/core/include/mqt-core/boost/config/warning_disable.hpp +47 -0
- mqt/core/include/mqt-core/boost/config/workaround.hpp +305 -0
- mqt/core/include/mqt-core/boost/config.hpp +67 -0
- mqt/core/include/mqt-core/boost/cstdint.hpp +556 -0
- mqt/core/include/mqt-core/boost/cxx11_char_types.hpp +70 -0
- mqt/core/include/mqt-core/boost/detail/workaround.hpp +10 -0
- mqt/core/include/mqt-core/boost/limits.hpp +146 -0
- mqt/core/include/mqt-core/boost/multiprecision/complex128.hpp +24 -0
- mqt/core/include/mqt-core/boost/multiprecision/complex_adaptor.hpp +1046 -0
- mqt/core/include/mqt-core/boost/multiprecision/concepts/mp_number_archetypes.hpp +257 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_bin_float/io.hpp +698 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_bin_float/transcendental.hpp +157 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_bin_float.hpp +2297 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_complex.hpp +12 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_dec_float.hpp +3690 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/add.hpp +368 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/add_unsigned.hpp +387 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/bitwise.hpp +889 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/checked.hpp +178 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/comparison.hpp +374 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/cpp_int_config.hpp +161 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/divide.hpp +703 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/import_export.hpp +248 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/intel_intrinsics.hpp +138 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/limits.hpp +282 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/literals.hpp +295 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/misc.hpp +1457 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/multiply.hpp +848 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/serialize.hpp +211 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/value_pack.hpp +42 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int.hpp +2360 -0
- mqt/core/include/mqt-core/boost/multiprecision/debug_adaptor.hpp +760 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/assert.hpp +29 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/atomic.hpp +62 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/bitscan.hpp +317 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/check_cpp11_config.hpp +64 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/constexpr.hpp +88 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/default_ops.hpp +4052 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/digits.hpp +49 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/dynamic_array.hpp +44 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/empty_value.hpp +87 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/endian.hpp +35 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/et_ops.hpp +1831 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/float128_functions.hpp +95 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/float_string_cvt.hpp +333 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/fpclassify.hpp +101 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/functions/constants.hpp +288 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/functions/pow.hpp +905 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/functions/trig.hpp +1058 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/functions/trunc.hpp +82 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/generic_interconvert.hpp +687 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/hash.hpp +56 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/integer_ops.hpp +474 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/itos.hpp +39 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/min_max.hpp +106 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/no_et_ops.hpp +661 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/no_exceptions_support.hpp +55 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/number_base.hpp +1656 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/number_compare.hpp +848 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/precision.hpp +313 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/rebind.hpp +19 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/standalone_config.hpp +148 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/static_array.hpp +42 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/string_helpers.hpp +48 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/tables.hpp +80 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/ublas_interop.hpp +75 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/uniform_int_distribution.hpp +212 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/utype_helper.hpp +374 -0
- mqt/core/include/mqt-core/boost/multiprecision/eigen.hpp +248 -0
- mqt/core/include/mqt-core/boost/multiprecision/float128.hpp +920 -0
- mqt/core/include/mqt-core/boost/multiprecision/fwd.hpp +268 -0
- mqt/core/include/mqt-core/boost/multiprecision/gmp.hpp +4060 -0
- mqt/core/include/mqt-core/boost/multiprecision/integer.hpp +363 -0
- mqt/core/include/mqt-core/boost/multiprecision/logged_adaptor.hpp +834 -0
- mqt/core/include/mqt-core/boost/multiprecision/miller_rabin.hpp +221 -0
- mqt/core/include/mqt-core/boost/multiprecision/mpc.hpp +1721 -0
- mqt/core/include/mqt-core/boost/multiprecision/mpfi.hpp +2559 -0
- mqt/core/include/mqt-core/boost/multiprecision/mpfr.hpp +3644 -0
- mqt/core/include/mqt-core/boost/multiprecision/number.hpp +2500 -0
- mqt/core/include/mqt-core/boost/multiprecision/random.hpp +23 -0
- mqt/core/include/mqt-core/boost/multiprecision/rational_adaptor.hpp +1289 -0
- mqt/core/include/mqt-core/boost/multiprecision/tommath.hpp +1034 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/explicit_conversion.hpp +67 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/extract_exponent_type.hpp +28 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/is_backend.hpp +91 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/is_byte_container.hpp +51 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/is_complex.hpp +22 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/is_convertible_arithmetic.hpp +51 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/is_restricted_conversion.hpp +47 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/is_variable_precision.hpp +25 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/max_digits10.hpp +79 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/std_integer_traits.hpp +90 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/transcendental_reduction_type.hpp +21 -0
- mqt/core/include/mqt-core/boost/version.hpp +32 -0
- mqt/core/include/mqt-core/circuit_optimizer/CircuitOptimizer.hpp +119 -0
- mqt/core/include/mqt-core/circuit_optimizer/mqt_core_circuit_optimizer_export.h +43 -0
- mqt/core/include/mqt-core/datastructures/DirectedAcyclicGraph.hpp +117 -0
- mqt/core/include/mqt-core/datastructures/DirectedGraph.hpp +158 -0
- mqt/core/include/mqt-core/datastructures/DisjointSet.hpp +50 -0
- mqt/core/include/mqt-core/datastructures/Layer.hpp +172 -0
- mqt/core/include/mqt-core/datastructures/SymmetricMatrix.hpp +57 -0
- mqt/core/include/mqt-core/datastructures/UndirectedGraph.hpp +227 -0
- mqt/core/include/mqt-core/datastructures/mqt_core_ds_export.h +43 -0
- mqt/core/include/mqt-core/dd/Approximation.hpp +45 -0
- mqt/core/include/mqt-core/dd/CachedEdge.hpp +174 -0
- mqt/core/include/mqt-core/dd/Complex.hpp +165 -0
- mqt/core/include/mqt-core/dd/ComplexNumbers.hpp +150 -0
- mqt/core/include/mqt-core/dd/ComplexValue.hpp +184 -0
- mqt/core/include/mqt-core/dd/ComputeTable.hpp +183 -0
- mqt/core/include/mqt-core/dd/DDDefinitions.hpp +139 -0
- mqt/core/include/mqt-core/dd/DDpackageConfig.hpp +104 -0
- mqt/core/include/mqt-core/dd/DensityNoiseTable.hpp +114 -0
- mqt/core/include/mqt-core/dd/Edge.hpp +416 -0
- mqt/core/include/mqt-core/dd/Export.hpp +438 -0
- mqt/core/include/mqt-core/dd/FunctionalityConstruction.hpp +75 -0
- mqt/core/include/mqt-core/dd/GateMatrixDefinitions.hpp +43 -0
- mqt/core/include/mqt-core/dd/LinkedListBase.hpp +45 -0
- mqt/core/include/mqt-core/dd/MemoryManager.hpp +193 -0
- mqt/core/include/mqt-core/dd/Node.hpp +223 -0
- mqt/core/include/mqt-core/dd/NoiseFunctionality.hpp +144 -0
- mqt/core/include/mqt-core/dd/Operations.hpp +306 -0
- mqt/core/include/mqt-core/dd/Package.hpp +2036 -0
- mqt/core/include/mqt-core/dd/Package_fwd.hpp +22 -0
- mqt/core/include/mqt-core/dd/RealNumber.hpp +255 -0
- mqt/core/include/mqt-core/dd/RealNumberUniqueTable.hpp +217 -0
- mqt/core/include/mqt-core/dd/Simulation.hpp +98 -0
- mqt/core/include/mqt-core/dd/StateGeneration.hpp +143 -0
- mqt/core/include/mqt-core/dd/StochasticNoiseOperationTable.hpp +88 -0
- mqt/core/include/mqt-core/dd/UnaryComputeTable.hpp +121 -0
- mqt/core/include/mqt-core/dd/UniqueTable.hpp +243 -0
- mqt/core/include/mqt-core/dd/mqt_core_dd_export.h +43 -0
- mqt/core/include/mqt-core/dd/statistics/MemoryManagerStatistics.hpp +84 -0
- mqt/core/include/mqt-core/dd/statistics/PackageStatistics.hpp +55 -0
- mqt/core/include/mqt-core/dd/statistics/Statistics.hpp +48 -0
- mqt/core/include/mqt-core/dd/statistics/TableStatistics.hpp +79 -0
- mqt/core/include/mqt-core/dd/statistics/UniqueTableStatistics.hpp +31 -0
- mqt/core/include/mqt-core/fomac/FoMaC.hpp +568 -0
- mqt/core/include/mqt-core/ir/Definitions.hpp +108 -0
- mqt/core/include/mqt-core/ir/Permutation.hpp +213 -0
- mqt/core/include/mqt-core/ir/QuantumComputation.hpp +596 -0
- mqt/core/include/mqt-core/ir/Register.hpp +125 -0
- mqt/core/include/mqt-core/ir/mqt_core_ir_export.h +43 -0
- mqt/core/include/mqt-core/ir/operations/AodOperation.hpp +92 -0
- mqt/core/include/mqt-core/ir/operations/CompoundOperation.hpp +212 -0
- mqt/core/include/mqt-core/ir/operations/Control.hpp +142 -0
- mqt/core/include/mqt-core/ir/operations/Expression.hpp +847 -0
- mqt/core/include/mqt-core/ir/operations/IfElseOperation.hpp +169 -0
- mqt/core/include/mqt-core/ir/operations/NonUnitaryOperation.hpp +118 -0
- mqt/core/include/mqt-core/ir/operations/OpType.hpp +120 -0
- mqt/core/include/mqt-core/ir/operations/OpType.inc +76 -0
- mqt/core/include/mqt-core/ir/operations/Operation.hpp +247 -0
- mqt/core/include/mqt-core/ir/operations/StandardOperation.hpp +140 -0
- mqt/core/include/mqt-core/ir/operations/SymbolicOperation.hpp +144 -0
- mqt/core/include/mqt-core/mqt_na_qdmi/device.h +602 -0
- mqt/core/include/mqt-core/mqt_na_qdmi/types.h +78 -0
- mqt/core/include/mqt-core/na/NAComputation.hpp +185 -0
- mqt/core/include/mqt-core/na/device/Device.hpp +410 -0
- mqt/core/include/mqt-core/na/device/DeviceMemberInitializers.hpp +724 -0
- mqt/core/include/mqt-core/na/device/Generator.hpp +447 -0
- mqt/core/include/mqt-core/na/entities/Atom.hpp +62 -0
- mqt/core/include/mqt-core/na/entities/Location.hpp +154 -0
- mqt/core/include/mqt-core/na/entities/Zone.hpp +95 -0
- mqt/core/include/mqt-core/na/fomac/Device.hpp +169 -0
- mqt/core/include/mqt-core/na/mqt_core_na_export.h +43 -0
- mqt/core/include/mqt-core/na/operations/GlobalCZOp.hpp +38 -0
- mqt/core/include/mqt-core/na/operations/GlobalOp.hpp +58 -0
- mqt/core/include/mqt-core/na/operations/GlobalRYOp.hpp +42 -0
- mqt/core/include/mqt-core/na/operations/LoadOp.hpp +89 -0
- mqt/core/include/mqt-core/na/operations/LocalOp.hpp +56 -0
- mqt/core/include/mqt-core/na/operations/LocalRZOp.hpp +42 -0
- mqt/core/include/mqt-core/na/operations/LocalUOp.hpp +49 -0
- mqt/core/include/mqt-core/na/operations/MoveOp.hpp +66 -0
- mqt/core/include/mqt-core/na/operations/Op.hpp +62 -0
- mqt/core/include/mqt-core/na/operations/ShuttlingOp.hpp +51 -0
- mqt/core/include/mqt-core/na/operations/StoreOp.hpp +87 -0
- mqt/core/include/mqt-core/qasm3/Exception.hpp +85 -0
- mqt/core/include/mqt-core/qasm3/Gate.hpp +65 -0
- mqt/core/include/mqt-core/qasm3/Importer.hpp +192 -0
- mqt/core/include/mqt-core/qasm3/InstVisitor.hpp +145 -0
- mqt/core/include/mqt-core/qasm3/NestedEnvironment.hpp +41 -0
- mqt/core/include/mqt-core/qasm3/Parser.hpp +170 -0
- mqt/core/include/mqt-core/qasm3/Scanner.hpp +73 -0
- mqt/core/include/mqt-core/qasm3/Statement.hpp +486 -0
- mqt/core/include/mqt-core/qasm3/Statement_fwd.hpp +39 -0
- mqt/core/include/mqt-core/qasm3/StdGates.hpp +232 -0
- mqt/core/include/mqt-core/qasm3/Token.hpp +198 -0
- mqt/core/include/mqt-core/qasm3/Types.hpp +238 -0
- mqt/core/include/mqt-core/qasm3/Types_fwd.hpp +22 -0
- mqt/core/include/mqt-core/qasm3/mqt_core_qasm_export.h +43 -0
- mqt/core/include/mqt-core/qasm3/passes/CompilerPass.hpp +22 -0
- mqt/core/include/mqt-core/qasm3/passes/ConstEvalPass.hpp +102 -0
- mqt/core/include/mqt-core/qasm3/passes/TypeCheckPass.hpp +124 -0
- mqt/core/include/mqt-core/qdmi/Driver.hpp +431 -0
- mqt/core/include/mqt-core/zx/FunctionalityConstruction.hpp +125 -0
- mqt/core/include/mqt-core/zx/Rational.hpp +318 -0
- mqt/core/include/mqt-core/zx/Rules.hpp +132 -0
- mqt/core/include/mqt-core/zx/Simplify.hpp +182 -0
- mqt/core/include/mqt-core/zx/Utils.hpp +212 -0
- mqt/core/include/mqt-core/zx/ZXDefinitions.hpp +93 -0
- mqt/core/include/mqt-core/zx/ZXDiagram.hpp +480 -0
- mqt/core/include/mqt-core/zx/mqt_core_zx_export.h +43 -0
- mqt/core/include/nlohmann/adl_serializer.hpp +55 -0
- mqt/core/include/nlohmann/byte_container_with_subtype.hpp +103 -0
- mqt/core/include/nlohmann/detail/abi_macros.hpp +111 -0
- mqt/core/include/nlohmann/detail/conversions/from_json.hpp +577 -0
- mqt/core/include/nlohmann/detail/conversions/to_chars.hpp +1118 -0
- mqt/core/include/nlohmann/detail/conversions/to_json.hpp +479 -0
- mqt/core/include/nlohmann/detail/exceptions.hpp +291 -0
- mqt/core/include/nlohmann/detail/hash.hpp +129 -0
- mqt/core/include/nlohmann/detail/input/binary_reader.hpp +3068 -0
- mqt/core/include/nlohmann/detail/input/input_adapters.hpp +549 -0
- mqt/core/include/nlohmann/detail/input/json_sax.hpp +986 -0
- mqt/core/include/nlohmann/detail/input/lexer.hpp +1643 -0
- mqt/core/include/nlohmann/detail/input/parser.hpp +519 -0
- mqt/core/include/nlohmann/detail/input/position_t.hpp +37 -0
- mqt/core/include/nlohmann/detail/iterators/internal_iterator.hpp +35 -0
- mqt/core/include/nlohmann/detail/iterators/iter_impl.hpp +760 -0
- mqt/core/include/nlohmann/detail/iterators/iteration_proxy.hpp +235 -0
- mqt/core/include/nlohmann/detail/iterators/iterator_traits.hpp +61 -0
- mqt/core/include/nlohmann/detail/iterators/json_reverse_iterator.hpp +130 -0
- mqt/core/include/nlohmann/detail/iterators/primitive_iterator.hpp +132 -0
- mqt/core/include/nlohmann/detail/json_custom_base_class.hpp +39 -0
- mqt/core/include/nlohmann/detail/json_pointer.hpp +988 -0
- mqt/core/include/nlohmann/detail/json_ref.hpp +78 -0
- mqt/core/include/nlohmann/detail/macro_scope.hpp +595 -0
- mqt/core/include/nlohmann/detail/macro_unscope.hpp +46 -0
- mqt/core/include/nlohmann/detail/meta/call_std/begin.hpp +17 -0
- mqt/core/include/nlohmann/detail/meta/call_std/end.hpp +17 -0
- mqt/core/include/nlohmann/detail/meta/cpp_future.hpp +171 -0
- mqt/core/include/nlohmann/detail/meta/detected.hpp +70 -0
- mqt/core/include/nlohmann/detail/meta/identity_tag.hpp +21 -0
- mqt/core/include/nlohmann/detail/meta/is_sax.hpp +159 -0
- mqt/core/include/nlohmann/detail/meta/std_fs.hpp +29 -0
- mqt/core/include/nlohmann/detail/meta/type_traits.hpp +795 -0
- mqt/core/include/nlohmann/detail/meta/void_t.hpp +24 -0
- mqt/core/include/nlohmann/detail/output/binary_writer.hpp +1850 -0
- mqt/core/include/nlohmann/detail/output/output_adapters.hpp +147 -0
- mqt/core/include/nlohmann/detail/output/serializer.hpp +988 -0
- mqt/core/include/nlohmann/detail/string_concat.hpp +146 -0
- mqt/core/include/nlohmann/detail/string_escape.hpp +72 -0
- mqt/core/include/nlohmann/detail/string_utils.hpp +37 -0
- mqt/core/include/nlohmann/detail/value_t.hpp +118 -0
- mqt/core/include/nlohmann/json.hpp +5306 -0
- mqt/core/include/nlohmann/json_fwd.hpp +75 -0
- mqt/core/include/nlohmann/ordered_map.hpp +359 -0
- mqt/core/include/nlohmann/thirdparty/hedley/hedley.hpp +2045 -0
- mqt/core/include/nlohmann/thirdparty/hedley/hedley_undef.hpp +158 -0
- mqt/core/include/qdmi/qdmi/client.h +990 -0
- mqt/core/include/qdmi/qdmi/constants.h +1139 -0
- mqt/core/include/qdmi/qdmi/device.h +602 -0
- mqt/core/include/qdmi/qdmi/types.h +78 -0
- mqt/core/include/spdlog/async.h +99 -0
- mqt/core/include/spdlog/async_logger-inl.h +84 -0
- mqt/core/include/spdlog/async_logger.h +74 -0
- mqt/core/include/spdlog/cfg/argv.h +40 -0
- mqt/core/include/spdlog/cfg/env.h +36 -0
- mqt/core/include/spdlog/cfg/helpers-inl.h +107 -0
- mqt/core/include/spdlog/cfg/helpers.h +29 -0
- mqt/core/include/spdlog/common-inl.h +68 -0
- mqt/core/include/spdlog/common.h +406 -0
- mqt/core/include/spdlog/details/backtracer-inl.h +63 -0
- mqt/core/include/spdlog/details/backtracer.h +45 -0
- mqt/core/include/spdlog/details/circular_q.h +115 -0
- mqt/core/include/spdlog/details/console_globals.h +28 -0
- mqt/core/include/spdlog/details/file_helper-inl.h +153 -0
- mqt/core/include/spdlog/details/file_helper.h +61 -0
- mqt/core/include/spdlog/details/fmt_helper.h +141 -0
- mqt/core/include/spdlog/details/log_msg-inl.h +44 -0
- mqt/core/include/spdlog/details/log_msg.h +40 -0
- mqt/core/include/spdlog/details/log_msg_buffer-inl.h +54 -0
- mqt/core/include/spdlog/details/log_msg_buffer.h +32 -0
- mqt/core/include/spdlog/details/mpmc_blocking_q.h +177 -0
- mqt/core/include/spdlog/details/null_mutex.h +35 -0
- mqt/core/include/spdlog/details/os-inl.h +606 -0
- mqt/core/include/spdlog/details/os.h +127 -0
- mqt/core/include/spdlog/details/periodic_worker-inl.h +26 -0
- mqt/core/include/spdlog/details/periodic_worker.h +58 -0
- mqt/core/include/spdlog/details/registry-inl.h +270 -0
- mqt/core/include/spdlog/details/registry.h +131 -0
- mqt/core/include/spdlog/details/synchronous_factory.h +22 -0
- mqt/core/include/spdlog/details/tcp_client-windows.h +135 -0
- mqt/core/include/spdlog/details/tcp_client.h +127 -0
- mqt/core/include/spdlog/details/thread_pool-inl.h +126 -0
- mqt/core/include/spdlog/details/thread_pool.h +117 -0
- mqt/core/include/spdlog/details/udp_client-windows.h +98 -0
- mqt/core/include/spdlog/details/udp_client.h +81 -0
- mqt/core/include/spdlog/details/windows_include.h +11 -0
- mqt/core/include/spdlog/fmt/bin_to_hex.h +224 -0
- mqt/core/include/spdlog/fmt/bundled/args.h +220 -0
- mqt/core/include/spdlog/fmt/bundled/base.h +2989 -0
- mqt/core/include/spdlog/fmt/bundled/chrono.h +2330 -0
- mqt/core/include/spdlog/fmt/bundled/color.h +637 -0
- mqt/core/include/spdlog/fmt/bundled/compile.h +539 -0
- mqt/core/include/spdlog/fmt/bundled/core.h +5 -0
- mqt/core/include/spdlog/fmt/bundled/fmt.license.rst +27 -0
- mqt/core/include/spdlog/fmt/bundled/format-inl.h +1948 -0
- mqt/core/include/spdlog/fmt/bundled/format.h +4244 -0
- mqt/core/include/spdlog/fmt/bundled/os.h +427 -0
- mqt/core/include/spdlog/fmt/bundled/ostream.h +167 -0
- mqt/core/include/spdlog/fmt/bundled/printf.h +633 -0
- mqt/core/include/spdlog/fmt/bundled/ranges.h +850 -0
- mqt/core/include/spdlog/fmt/bundled/std.h +728 -0
- mqt/core/include/spdlog/fmt/bundled/xchar.h +369 -0
- mqt/core/include/spdlog/fmt/chrono.h +23 -0
- mqt/core/include/spdlog/fmt/compile.h +23 -0
- mqt/core/include/spdlog/fmt/fmt.h +30 -0
- mqt/core/include/spdlog/fmt/ostr.h +23 -0
- mqt/core/include/spdlog/fmt/ranges.h +23 -0
- mqt/core/include/spdlog/fmt/std.h +24 -0
- mqt/core/include/spdlog/fmt/xchar.h +23 -0
- mqt/core/include/spdlog/formatter.h +17 -0
- mqt/core/include/spdlog/fwd.h +18 -0
- mqt/core/include/spdlog/logger-inl.h +198 -0
- mqt/core/include/spdlog/logger.h +379 -0
- mqt/core/include/spdlog/mdc.h +52 -0
- mqt/core/include/spdlog/pattern_formatter-inl.h +1340 -0
- mqt/core/include/spdlog/pattern_formatter.h +118 -0
- mqt/core/include/spdlog/sinks/android_sink.h +137 -0
- mqt/core/include/spdlog/sinks/ansicolor_sink-inl.h +142 -0
- mqt/core/include/spdlog/sinks/ansicolor_sink.h +116 -0
- mqt/core/include/spdlog/sinks/base_sink-inl.h +59 -0
- mqt/core/include/spdlog/sinks/base_sink.h +51 -0
- mqt/core/include/spdlog/sinks/basic_file_sink-inl.h +48 -0
- mqt/core/include/spdlog/sinks/basic_file_sink.h +66 -0
- mqt/core/include/spdlog/sinks/callback_sink.h +56 -0
- mqt/core/include/spdlog/sinks/daily_file_sink.h +254 -0
- mqt/core/include/spdlog/sinks/dist_sink.h +81 -0
- mqt/core/include/spdlog/sinks/dup_filter_sink.h +91 -0
- mqt/core/include/spdlog/sinks/hourly_file_sink.h +193 -0
- mqt/core/include/spdlog/sinks/kafka_sink.h +119 -0
- mqt/core/include/spdlog/sinks/mongo_sink.h +108 -0
- mqt/core/include/spdlog/sinks/msvc_sink.h +68 -0
- mqt/core/include/spdlog/sinks/null_sink.h +41 -0
- mqt/core/include/spdlog/sinks/ostream_sink.h +43 -0
- mqt/core/include/spdlog/sinks/qt_sinks.h +304 -0
- mqt/core/include/spdlog/sinks/ringbuffer_sink.h +67 -0
- mqt/core/include/spdlog/sinks/rotating_file_sink-inl.h +179 -0
- mqt/core/include/spdlog/sinks/rotating_file_sink.h +93 -0
- mqt/core/include/spdlog/sinks/sink-inl.h +22 -0
- mqt/core/include/spdlog/sinks/sink.h +34 -0
- mqt/core/include/spdlog/sinks/stdout_color_sinks-inl.h +38 -0
- mqt/core/include/spdlog/sinks/stdout_color_sinks.h +49 -0
- mqt/core/include/spdlog/sinks/stdout_sinks-inl.h +127 -0
- mqt/core/include/spdlog/sinks/stdout_sinks.h +84 -0
- mqt/core/include/spdlog/sinks/syslog_sink.h +104 -0
- mqt/core/include/spdlog/sinks/systemd_sink.h +121 -0
- mqt/core/include/spdlog/sinks/tcp_sink.h +75 -0
- mqt/core/include/spdlog/sinks/udp_sink.h +69 -0
- mqt/core/include/spdlog/sinks/win_eventlog_sink.h +260 -0
- mqt/core/include/spdlog/sinks/wincolor_sink-inl.h +172 -0
- mqt/core/include/spdlog/sinks/wincolor_sink.h +82 -0
- mqt/core/include/spdlog/spdlog-inl.h +96 -0
- mqt/core/include/spdlog/spdlog.h +357 -0
- mqt/core/include/spdlog/stopwatch.h +66 -0
- mqt/core/include/spdlog/tweakme.h +148 -0
- mqt/core/include/spdlog/version.h +11 -0
- mqt/core/ir/__init__.pyi +2078 -0
- mqt/core/ir/operations.pyi +1011 -0
- mqt/core/ir/registers.pyi +91 -0
- mqt/core/ir/symbolic.pyi +177 -0
- mqt/core/ir.cp314t-win_amd64.pyd +0 -0
- mqt/core/lib/mqt-core-algorithms.lib +0 -0
- mqt/core/lib/mqt-core-circuit-optimizer.lib +0 -0
- mqt/core/lib/mqt-core-dd.lib +0 -0
- mqt/core/lib/mqt-core-ds.lib +0 -0
- mqt/core/lib/mqt-core-fomac.lib +0 -0
- mqt/core/lib/mqt-core-ir.lib +0 -0
- mqt/core/lib/mqt-core-na-fomac.lib +0 -0
- mqt/core/lib/mqt-core-na.lib +0 -0
- mqt/core/lib/mqt-core-qasm.lib +0 -0
- mqt/core/lib/mqt-core-qdmi-driver.lib +0 -0
- mqt/core/lib/mqt-core-qdmi-na-device-gen.lib +0 -0
- mqt/core/lib/mqt-core-qdmi-na-device.lib +0 -0
- mqt/core/lib/mqt-core-zx.lib +0 -0
- mqt/core/lib/pkgconfig/spdlog.pc +13 -0
- mqt/core/lib/spdlog.lib +0 -0
- mqt/core/na/__init__.py +12 -0
- mqt/core/na/fomac.cp314t-win_amd64.pyd +0 -0
- mqt/core/na/fomac.pyi +117 -0
- mqt/core/nlohmann_json.natvis +278 -0
- mqt/core/plugins/__init__.py +9 -0
- mqt/core/plugins/qiskit/__init__.py +19 -0
- mqt/core/plugins/qiskit/mqt_to_qiskit.py +420 -0
- mqt/core/plugins/qiskit/qiskit_to_mqt.py +562 -0
- mqt/core/py.typed +2 -0
- mqt/core/share/cmake/mqt-core/AddMQTPythonBinding.cmake +55 -0
- mqt/core/share/cmake/mqt-core/Cache.cmake +33 -0
- mqt/core/share/cmake/mqt-core/FindGMP.cmake +103 -0
- mqt/core/share/cmake/mqt-core/PackageAddTest.cmake +46 -0
- mqt/core/share/cmake/mqt-core/PreventInSourceBuilds.cmake +25 -0
- mqt/core/share/cmake/mqt-core/StandardProjectSettings.cmake +87 -0
- mqt/core/share/cmake/mqt-core/mqt-core-config-version.cmake +85 -0
- mqt/core/share/cmake/mqt-core/mqt-core-config.cmake +52 -0
- mqt/core/share/cmake/mqt-core/mqt-core-targets-release.cmake +141 -0
- mqt/core/share/cmake/mqt-core/mqt-core-targets.cmake +445 -0
- mqt/core/share/cmake/nlohmann_json/nlohmann_jsonConfig.cmake +15 -0
- mqt/core/share/cmake/nlohmann_json/nlohmann_jsonConfigVersion.cmake +20 -0
- mqt/core/share/cmake/nlohmann_json/nlohmann_jsonTargets.cmake +110 -0
- mqt/core/share/cmake/qdmi/Cache.cmake +44 -0
- mqt/core/share/cmake/qdmi/PrefixHandling.cmake +78 -0
- mqt/core/share/cmake/qdmi/prefix_defs.txt +26 -0
- mqt/core/share/cmake/qdmi/qdmi-config-version.cmake +85 -0
- mqt/core/share/cmake/qdmi/qdmi-config.cmake +42 -0
- mqt/core/share/cmake/qdmi/qdmi-targets.cmake +129 -0
- mqt/core/share/cmake/spdlog/spdlogConfig.cmake +44 -0
- mqt/core/share/cmake/spdlog/spdlogConfigTargets-release.cmake +19 -0
- mqt/core/share/cmake/spdlog/spdlogConfigTargets.cmake +121 -0
- mqt/core/share/cmake/spdlog/spdlogConfigVersion.cmake +65 -0
- mqt/core/share/pkgconfig/nlohmann_json.pc +7 -0
- mqt_core-3.3.2.dist-info/DELVEWHEEL +2 -0
- mqt_core-3.3.2.dist-info/METADATA +210 -0
- mqt_core-3.3.2.dist-info/RECORD +537 -0
- mqt_core-3.3.2.dist-info/WHEEL +5 -0
- mqt_core-3.3.2.dist-info/entry_points.txt +4 -0
- mqt_core-3.3.2.dist-info/licenses/LICENSE.md +22 -0
- mqt_core.libs/msvcp140.dll +0 -0
|
@@ -0,0 +1,4052 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright 2011-21 John Maddock.
|
|
3
|
+
// Copyright 2021 Iskandarov Lev. Distributed under the Boost
|
|
4
|
+
// Software License, Version 1.0. (See accompanying file
|
|
5
|
+
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
6
|
+
|
|
7
|
+
#ifndef BOOST_MP_DEFAULT_OPS
|
|
8
|
+
#define BOOST_MP_DEFAULT_OPS
|
|
9
|
+
|
|
10
|
+
#include <boost/multiprecision/detail/standalone_config.hpp>
|
|
11
|
+
#include <boost/multiprecision/detail/no_exceptions_support.hpp>
|
|
12
|
+
#include <boost/multiprecision/detail/number_base.hpp>
|
|
13
|
+
#include <boost/multiprecision/detail/assert.hpp>
|
|
14
|
+
#include <boost/multiprecision/traits/is_backend.hpp>
|
|
15
|
+
#include <boost/multiprecision/detail/fpclassify.hpp>
|
|
16
|
+
#include <cstdint>
|
|
17
|
+
#include <complex>
|
|
18
|
+
#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
|
|
19
|
+
#include <string_view>
|
|
20
|
+
#endif
|
|
21
|
+
|
|
22
|
+
#ifdef BOOST_MP_MATH_AVAILABLE
|
|
23
|
+
#include <boost/math/special_functions/fpclassify.hpp>
|
|
24
|
+
#include <boost/math/special_functions/next.hpp>
|
|
25
|
+
#include <boost/math/special_functions/hypot.hpp>
|
|
26
|
+
#include <boost/math/policies/error_handling.hpp>
|
|
27
|
+
#endif
|
|
28
|
+
|
|
29
|
+
#ifndef INSTRUMENT_BACKEND
|
|
30
|
+
#ifndef BOOST_MP_INSTRUMENT
|
|
31
|
+
#define INSTRUMENT_BACKEND(x)
|
|
32
|
+
#else
|
|
33
|
+
#define INSTRUMENT_BACKEND(x) \
|
|
34
|
+
std::cout << BOOST_STRINGIZE(x) << " = " << x.str(0, std::ios_base::scientific) << std::endl;
|
|
35
|
+
#endif
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
namespace boost {
|
|
39
|
+
namespace multiprecision {
|
|
40
|
+
|
|
41
|
+
namespace detail {
|
|
42
|
+
|
|
43
|
+
template <class To, class From>
|
|
44
|
+
void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/);
|
|
45
|
+
template <class To, class From>
|
|
46
|
+
void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_integer>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/);
|
|
47
|
+
template <class To, class From>
|
|
48
|
+
void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_floating_point>& /*from_type*/);
|
|
49
|
+
template <class To, class From>
|
|
50
|
+
void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_rational>& /*from_type*/);
|
|
51
|
+
template <class To, class From>
|
|
52
|
+
void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/);
|
|
53
|
+
|
|
54
|
+
template <class Integer>
|
|
55
|
+
BOOST_MP_CXX14_CONSTEXPR Integer karatsuba_sqrt(const Integer& x, Integer& r, size_t bits);
|
|
56
|
+
|
|
57
|
+
} // namespace detail
|
|
58
|
+
|
|
59
|
+
namespace default_ops {
|
|
60
|
+
|
|
61
|
+
template <class T>
|
|
62
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_backend<T>::value, int>::type eval_signbit(const T& val);
|
|
63
|
+
|
|
64
|
+
template <class T>
|
|
65
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!boost::multiprecision::detail::is_backend<T>::value, int>::type eval_signbit(const T& val) { return val < 0; }
|
|
66
|
+
|
|
67
|
+
inline int eval_signbit(float val) { return (std::signbit)(val); }
|
|
68
|
+
inline int eval_signbit(double val) { return (std::signbit)(val); }
|
|
69
|
+
inline int eval_signbit(long double val) { return (std::signbit)(val); }
|
|
70
|
+
#ifdef BOOST_HAS_FLOAT128
|
|
71
|
+
extern "C" int signbitq(float128_type) throw();
|
|
72
|
+
inline int eval_signbit(float128_type val) { return signbitq(val); }
|
|
73
|
+
#endif
|
|
74
|
+
|
|
75
|
+
template <class T>
|
|
76
|
+
BOOST_MP_CXX14_CONSTEXPR bool eval_is_zero(const T& val);
|
|
77
|
+
|
|
78
|
+
#ifdef BOOST_MSVC
|
|
79
|
+
// warning C4127: conditional expression is constant
|
|
80
|
+
// warning C4146: unary minus operator applied to unsigned type, result still unsigned
|
|
81
|
+
#pragma warning(push)
|
|
82
|
+
#pragma warning(disable : 4127 4146)
|
|
83
|
+
#endif
|
|
84
|
+
//
|
|
85
|
+
// Default versions of mixed arithmetic, these just construct a temporary
|
|
86
|
+
// from the arithmetic value and then do the arithmetic on that, two versions
|
|
87
|
+
// of each depending on whether the backend can be directly constructed from type V.
|
|
88
|
+
//
|
|
89
|
+
// Note that we have to provide *all* the template parameters to class number when used in
|
|
90
|
+
// enable_if as MSVC-10 won't compile the code if we rely on a computed-default parameter.
|
|
91
|
+
// Since the result of the test doesn't depend on whether expression templates are on or off
|
|
92
|
+
// we just use et_on everywhere. We could use a BOOST_WORKAROUND but that just obfuscates the
|
|
93
|
+
// code even more....
|
|
94
|
+
//
|
|
95
|
+
template <class T, class V>
|
|
96
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<V, T>::value>::type
|
|
97
|
+
eval_add(T& result, V const& v)
|
|
98
|
+
{
|
|
99
|
+
T t;
|
|
100
|
+
t = v;
|
|
101
|
+
eval_add(result, t);
|
|
102
|
+
}
|
|
103
|
+
template <class T, class V>
|
|
104
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, T>::value>::type
|
|
105
|
+
eval_add(T& result, V const& v)
|
|
106
|
+
{
|
|
107
|
+
T t(v);
|
|
108
|
+
eval_add(result, t);
|
|
109
|
+
}
|
|
110
|
+
template <class T, class V>
|
|
111
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<V, T>::value>::type
|
|
112
|
+
eval_subtract(T& result, V const& v)
|
|
113
|
+
{
|
|
114
|
+
T t;
|
|
115
|
+
t = v;
|
|
116
|
+
eval_subtract(result, t);
|
|
117
|
+
}
|
|
118
|
+
template <class T, class V>
|
|
119
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, T>::value>::type
|
|
120
|
+
eval_subtract(T& result, V const& v)
|
|
121
|
+
{
|
|
122
|
+
T t(v);
|
|
123
|
+
eval_subtract(result, t);
|
|
124
|
+
}
|
|
125
|
+
template <class T, class V>
|
|
126
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<V, T>::value>::type
|
|
127
|
+
eval_multiply(T& result, V const& v)
|
|
128
|
+
{
|
|
129
|
+
T t;
|
|
130
|
+
t = v;
|
|
131
|
+
eval_multiply(result, t);
|
|
132
|
+
}
|
|
133
|
+
template <class T, class V>
|
|
134
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, T>::value>::type
|
|
135
|
+
eval_multiply(T& result, V const& v)
|
|
136
|
+
{
|
|
137
|
+
T t(v);
|
|
138
|
+
eval_multiply(result, t);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
template <class T, class U, class V>
|
|
142
|
+
BOOST_MP_CXX14_CONSTEXPR void eval_multiply(T& t, const U& u, const V& v);
|
|
143
|
+
|
|
144
|
+
template <class T, class U, class V>
|
|
145
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::value)>::type eval_multiply_add(T& t, const U& u, const V& v)
|
|
146
|
+
{
|
|
147
|
+
T z;
|
|
148
|
+
eval_multiply(z, u, v);
|
|
149
|
+
eval_add(t, z);
|
|
150
|
+
}
|
|
151
|
+
template <class T, class U, class V>
|
|
152
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
|
|
153
|
+
{
|
|
154
|
+
eval_multiply_add(t, v, u);
|
|
155
|
+
}
|
|
156
|
+
template <class T, class U, class V>
|
|
157
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::value)>::type eval_multiply_subtract(T& t, const U& u, const V& v)
|
|
158
|
+
{
|
|
159
|
+
T z;
|
|
160
|
+
eval_multiply(z, u, v);
|
|
161
|
+
eval_subtract(t, z);
|
|
162
|
+
}
|
|
163
|
+
template <class T, class U, class V>
|
|
164
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
|
|
165
|
+
{
|
|
166
|
+
eval_multiply_subtract(t, v, u);
|
|
167
|
+
}
|
|
168
|
+
template <class T, class V>
|
|
169
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
|
|
170
|
+
eval_divide(T& result, V const& v)
|
|
171
|
+
{
|
|
172
|
+
T t;
|
|
173
|
+
t = v;
|
|
174
|
+
eval_divide(result, t);
|
|
175
|
+
}
|
|
176
|
+
template <class T, class V>
|
|
177
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
|
|
178
|
+
eval_divide(T& result, V const& v)
|
|
179
|
+
{
|
|
180
|
+
T t(v);
|
|
181
|
+
eval_divide(result, t);
|
|
182
|
+
}
|
|
183
|
+
template <class T, class V>
|
|
184
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
|
|
185
|
+
eval_modulus(T& result, V const& v)
|
|
186
|
+
{
|
|
187
|
+
T t;
|
|
188
|
+
t = v;
|
|
189
|
+
eval_modulus(result, t);
|
|
190
|
+
}
|
|
191
|
+
template <class T, class V>
|
|
192
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
|
|
193
|
+
eval_modulus(T& result, V const& v)
|
|
194
|
+
{
|
|
195
|
+
T t(v);
|
|
196
|
+
eval_modulus(result, t);
|
|
197
|
+
}
|
|
198
|
+
template <class T, class V>
|
|
199
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
|
|
200
|
+
eval_bitwise_and(T& result, V const& v)
|
|
201
|
+
{
|
|
202
|
+
T t;
|
|
203
|
+
t = v;
|
|
204
|
+
eval_bitwise_and(result, t);
|
|
205
|
+
}
|
|
206
|
+
template <class T, class V>
|
|
207
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
|
|
208
|
+
eval_bitwise_and(T& result, V const& v)
|
|
209
|
+
{
|
|
210
|
+
T t(v);
|
|
211
|
+
eval_bitwise_and(result, t);
|
|
212
|
+
}
|
|
213
|
+
template <class T, class V>
|
|
214
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
|
|
215
|
+
eval_bitwise_or(T& result, V const& v)
|
|
216
|
+
{
|
|
217
|
+
T t;
|
|
218
|
+
t = v;
|
|
219
|
+
eval_bitwise_or(result, t);
|
|
220
|
+
}
|
|
221
|
+
template <class T, class V>
|
|
222
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
|
|
223
|
+
eval_bitwise_or(T& result, V const& v)
|
|
224
|
+
{
|
|
225
|
+
T t(v);
|
|
226
|
+
eval_bitwise_or(result, t);
|
|
227
|
+
}
|
|
228
|
+
template <class T, class V>
|
|
229
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
|
|
230
|
+
eval_bitwise_xor(T& result, V const& v)
|
|
231
|
+
{
|
|
232
|
+
T t;
|
|
233
|
+
t = v;
|
|
234
|
+
eval_bitwise_xor(result, t);
|
|
235
|
+
}
|
|
236
|
+
template <class T, class V>
|
|
237
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
|
|
238
|
+
eval_bitwise_xor(T& result, V const& v)
|
|
239
|
+
{
|
|
240
|
+
T t(v);
|
|
241
|
+
eval_bitwise_xor(result, t);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
template <class T, class V>
|
|
245
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
|
|
246
|
+
eval_complement(T& result, V const& v)
|
|
247
|
+
{
|
|
248
|
+
T t;
|
|
249
|
+
t = v;
|
|
250
|
+
eval_complement(result, t);
|
|
251
|
+
}
|
|
252
|
+
template <class T, class V>
|
|
253
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
|
|
254
|
+
eval_complement(T& result, V const& v)
|
|
255
|
+
{
|
|
256
|
+
T t(v);
|
|
257
|
+
eval_complement(result, t);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
//
|
|
261
|
+
// Default versions of 3-arg arithmetic functions, these mostly just forward to the 2 arg versions:
|
|
262
|
+
//
|
|
263
|
+
template <class T, class U, class V>
|
|
264
|
+
BOOST_MP_CXX14_CONSTEXPR void eval_add(T& t, const U& u, const V& v);
|
|
265
|
+
|
|
266
|
+
template <class T>
|
|
267
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_add_default(T& t, const T& u, const T& v)
|
|
268
|
+
{
|
|
269
|
+
if (&t == &v)
|
|
270
|
+
{
|
|
271
|
+
eval_add(t, u);
|
|
272
|
+
}
|
|
273
|
+
else if (&t == &u)
|
|
274
|
+
{
|
|
275
|
+
eval_add(t, v);
|
|
276
|
+
}
|
|
277
|
+
else
|
|
278
|
+
{
|
|
279
|
+
t = u;
|
|
280
|
+
eval_add(t, v);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
template <class T, class U>
|
|
284
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
|
|
285
|
+
{
|
|
286
|
+
T vv;
|
|
287
|
+
vv = v;
|
|
288
|
+
eval_add(t, u, vv);
|
|
289
|
+
}
|
|
290
|
+
template <class T, class U>
|
|
291
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
|
|
292
|
+
{
|
|
293
|
+
T vv(v);
|
|
294
|
+
eval_add(t, u, vv);
|
|
295
|
+
}
|
|
296
|
+
template <class T, class U>
|
|
297
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_add_default(T& t, const U& u, const T& v)
|
|
298
|
+
{
|
|
299
|
+
eval_add(t, v, u);
|
|
300
|
+
}
|
|
301
|
+
template <class T, class U, class V>
|
|
302
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_add_default(T& t, const U& u, const V& v)
|
|
303
|
+
{
|
|
304
|
+
BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
|
|
305
|
+
{
|
|
306
|
+
if ((void*)&t == (void*)&v)
|
|
307
|
+
{
|
|
308
|
+
eval_add(t, u);
|
|
309
|
+
}
|
|
310
|
+
else
|
|
311
|
+
{
|
|
312
|
+
t = u;
|
|
313
|
+
eval_add(t, v);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
else
|
|
317
|
+
{
|
|
318
|
+
t = u;
|
|
319
|
+
eval_add(t, v);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
template <class T, class U, class V>
|
|
323
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_add(T& t, const U& u, const V& v)
|
|
324
|
+
{
|
|
325
|
+
eval_add_default(t, u, v);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
template <class T, class U, class V>
|
|
329
|
+
void BOOST_MP_CXX14_CONSTEXPR eval_subtract(T& t, const U& u, const V& v);
|
|
330
|
+
|
|
331
|
+
template <class T>
|
|
332
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract_default(T& t, const T& u, const T& v)
|
|
333
|
+
{
|
|
334
|
+
if ((&t == &v) && is_signed_number<T>::value)
|
|
335
|
+
{
|
|
336
|
+
eval_subtract(t, u);
|
|
337
|
+
t.negate();
|
|
338
|
+
}
|
|
339
|
+
else if (&t == &u)
|
|
340
|
+
{
|
|
341
|
+
eval_subtract(t, v);
|
|
342
|
+
}
|
|
343
|
+
else
|
|
344
|
+
{
|
|
345
|
+
t = u;
|
|
346
|
+
eval_subtract(t, v);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
template <class T, class U>
|
|
350
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
|
|
351
|
+
{
|
|
352
|
+
T vv;
|
|
353
|
+
vv = v;
|
|
354
|
+
eval_subtract(t, u, vv);
|
|
355
|
+
}
|
|
356
|
+
template <class T, class U>
|
|
357
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
|
|
358
|
+
{
|
|
359
|
+
T vv(v);
|
|
360
|
+
eval_subtract(t, u, vv);
|
|
361
|
+
}
|
|
362
|
+
template <class T, class U>
|
|
363
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && is_signed_number<T>::value && (number_category<T>::value != number_kind_complex)>::type eval_subtract_default(T& t, const U& u, const T& v)
|
|
364
|
+
{
|
|
365
|
+
eval_subtract(t, v, u);
|
|
366
|
+
if(!eval_is_zero(t) || (eval_signbit(u) != eval_signbit(v)))
|
|
367
|
+
t.negate();
|
|
368
|
+
}
|
|
369
|
+
template <class T, class U>
|
|
370
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && is_signed_number<T>::value && (number_category<T>::value == number_kind_complex)>::type eval_subtract_default(T& t, const U& u, const T& v)
|
|
371
|
+
{
|
|
372
|
+
eval_subtract(t, v, u);
|
|
373
|
+
t.negate();
|
|
374
|
+
}
|
|
375
|
+
template <class T, class U>
|
|
376
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
|
|
377
|
+
{
|
|
378
|
+
T temp;
|
|
379
|
+
temp = u;
|
|
380
|
+
eval_subtract(t, temp, v);
|
|
381
|
+
}
|
|
382
|
+
template <class T, class U>
|
|
383
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
|
|
384
|
+
{
|
|
385
|
+
T temp(u);
|
|
386
|
+
eval_subtract(t, temp, v);
|
|
387
|
+
}
|
|
388
|
+
template <class T, class U, class V>
|
|
389
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract_default(T& t, const U& u, const V& v)
|
|
390
|
+
{
|
|
391
|
+
BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
|
|
392
|
+
{
|
|
393
|
+
if ((void*)&t == (void*)&v)
|
|
394
|
+
{
|
|
395
|
+
eval_subtract(t, u);
|
|
396
|
+
t.negate();
|
|
397
|
+
}
|
|
398
|
+
else
|
|
399
|
+
{
|
|
400
|
+
t = u;
|
|
401
|
+
eval_subtract(t, v);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
else
|
|
405
|
+
{
|
|
406
|
+
t = u;
|
|
407
|
+
eval_subtract(t, v);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
template <class T, class U, class V>
|
|
411
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(T& t, const U& u, const V& v)
|
|
412
|
+
{
|
|
413
|
+
eval_subtract_default(t, u, v);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
template <class T>
|
|
417
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_default(T& t, const T& u, const T& v)
|
|
418
|
+
{
|
|
419
|
+
if (&t == &v)
|
|
420
|
+
{
|
|
421
|
+
eval_multiply(t, u);
|
|
422
|
+
}
|
|
423
|
+
else if (&t == &u)
|
|
424
|
+
{
|
|
425
|
+
eval_multiply(t, v);
|
|
426
|
+
}
|
|
427
|
+
else
|
|
428
|
+
{
|
|
429
|
+
t = u;
|
|
430
|
+
eval_multiply(t, v);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
|
|
434
|
+
template <class T, class U>
|
|
435
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
|
|
436
|
+
{
|
|
437
|
+
T vv;
|
|
438
|
+
vv = v;
|
|
439
|
+
eval_multiply(t, u, vv);
|
|
440
|
+
}
|
|
441
|
+
template <class T, class U>
|
|
442
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
|
|
443
|
+
{
|
|
444
|
+
T vv(v);
|
|
445
|
+
eval_multiply(t, u, vv);
|
|
446
|
+
}
|
|
447
|
+
template <class T, class U>
|
|
448
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_multiply_default(T& t, const U& u, const T& v)
|
|
449
|
+
{
|
|
450
|
+
eval_multiply(t, v, u);
|
|
451
|
+
}
|
|
452
|
+
#endif
|
|
453
|
+
template <class T, class U, class V>
|
|
454
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_default(T& t, const U& u, const V& v)
|
|
455
|
+
{
|
|
456
|
+
BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
|
|
457
|
+
{
|
|
458
|
+
if ((void*)&t == (void*)&v)
|
|
459
|
+
{
|
|
460
|
+
eval_multiply(t, u);
|
|
461
|
+
}
|
|
462
|
+
else
|
|
463
|
+
{
|
|
464
|
+
t = number<T>::canonical_value(u);
|
|
465
|
+
eval_multiply(t, v);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
else
|
|
469
|
+
{
|
|
470
|
+
t = number<T>::canonical_value(u);
|
|
471
|
+
eval_multiply(t, v);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
template <class T, class U, class V>
|
|
475
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(T& t, const U& u, const V& v)
|
|
476
|
+
{
|
|
477
|
+
eval_multiply_default(t, u, v);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
template <class T>
|
|
481
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_add(T& t, const T& u, const T& v, const T& x)
|
|
482
|
+
{
|
|
483
|
+
if ((void*)&x == (void*)&t)
|
|
484
|
+
{
|
|
485
|
+
T z;
|
|
486
|
+
z = number<T>::canonical_value(x);
|
|
487
|
+
eval_multiply_add(t, u, v, z);
|
|
488
|
+
}
|
|
489
|
+
else
|
|
490
|
+
{
|
|
491
|
+
eval_multiply(t, u, v);
|
|
492
|
+
eval_add(t, x);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
template <class T, class U>
|
|
497
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_same<T, U>::value, T>::type make_T(const U& u)
|
|
498
|
+
{
|
|
499
|
+
T t;
|
|
500
|
+
t = number<T>::canonical_value(u);
|
|
501
|
+
return t;
|
|
502
|
+
}
|
|
503
|
+
template <class T>
|
|
504
|
+
inline BOOST_MP_CXX14_CONSTEXPR const T& make_T(const T& t)
|
|
505
|
+
{
|
|
506
|
+
return t;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
template <class T, class U, class V, class X>
|
|
510
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::value)>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
|
|
511
|
+
{
|
|
512
|
+
eval_multiply_add(t, make_T<T>(u), make_T<T>(v), make_T<T>(x));
|
|
513
|
+
}
|
|
514
|
+
template <class T, class U, class V, class X>
|
|
515
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
|
|
516
|
+
{
|
|
517
|
+
eval_multiply_add(t, v, u, x);
|
|
518
|
+
}
|
|
519
|
+
template <class T, class U, class V, class X>
|
|
520
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::value)>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
|
|
521
|
+
{
|
|
522
|
+
if ((void*)&x == (void*)&t)
|
|
523
|
+
{
|
|
524
|
+
T z;
|
|
525
|
+
z = x;
|
|
526
|
+
eval_multiply_subtract(t, u, v, z);
|
|
527
|
+
}
|
|
528
|
+
else
|
|
529
|
+
{
|
|
530
|
+
eval_multiply(t, u, v);
|
|
531
|
+
eval_subtract(t, x);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
template <class T, class U, class V, class X>
|
|
535
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
|
|
536
|
+
{
|
|
537
|
+
eval_multiply_subtract(t, v, u, x);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
template <class T, class U, class V>
|
|
541
|
+
BOOST_MP_CXX14_CONSTEXPR void eval_divide(T& t, const U& u, const V& v);
|
|
542
|
+
|
|
543
|
+
template <class T>
|
|
544
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_divide_default(T& t, const T& u, const T& v)
|
|
545
|
+
{
|
|
546
|
+
if (&t == &u)
|
|
547
|
+
eval_divide(t, v);
|
|
548
|
+
else if (&t == &v)
|
|
549
|
+
{
|
|
550
|
+
T temp;
|
|
551
|
+
eval_divide(temp, u, v);
|
|
552
|
+
temp.swap(t);
|
|
553
|
+
}
|
|
554
|
+
else
|
|
555
|
+
{
|
|
556
|
+
t = u;
|
|
557
|
+
eval_divide(t, v);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
|
|
561
|
+
template <class T, class U>
|
|
562
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
|
|
563
|
+
{
|
|
564
|
+
T vv;
|
|
565
|
+
vv = v;
|
|
566
|
+
eval_divide(t, u, vv);
|
|
567
|
+
}
|
|
568
|
+
template <class T, class U>
|
|
569
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
|
|
570
|
+
{
|
|
571
|
+
T vv(v);
|
|
572
|
+
eval_divide(t, u, vv);
|
|
573
|
+
}
|
|
574
|
+
template <class T, class U>
|
|
575
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
|
|
576
|
+
{
|
|
577
|
+
T uu;
|
|
578
|
+
uu = u;
|
|
579
|
+
eval_divide(t, uu, v);
|
|
580
|
+
}
|
|
581
|
+
template <class T, class U>
|
|
582
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
|
|
583
|
+
{
|
|
584
|
+
T uu(u);
|
|
585
|
+
eval_divide(t, uu, v);
|
|
586
|
+
}
|
|
587
|
+
#endif
|
|
588
|
+
template <class T, class U, class V>
|
|
589
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_divide_default(T& t, const U& u, const V& v)
|
|
590
|
+
{
|
|
591
|
+
BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
|
|
592
|
+
{
|
|
593
|
+
if ((void*)&t == (void*)&v)
|
|
594
|
+
{
|
|
595
|
+
T temp;
|
|
596
|
+
temp = u;
|
|
597
|
+
eval_divide(temp, v);
|
|
598
|
+
t = temp;
|
|
599
|
+
}
|
|
600
|
+
else
|
|
601
|
+
{
|
|
602
|
+
t = u;
|
|
603
|
+
eval_divide(t, v);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
else
|
|
607
|
+
{
|
|
608
|
+
t = u;
|
|
609
|
+
eval_divide(t, v);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
template <class T, class U, class V>
|
|
613
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(T& t, const U& u, const V& v)
|
|
614
|
+
{
|
|
615
|
+
eval_divide_default(t, u, v);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
template <class T, class U, class V>
|
|
619
|
+
BOOST_MP_CXX14_CONSTEXPR void eval_modulus(T& t, const U& u, const V& v);
|
|
620
|
+
|
|
621
|
+
template <class T>
|
|
622
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus_default(T& t, const T& u, const T& v)
|
|
623
|
+
{
|
|
624
|
+
if (&t == &u)
|
|
625
|
+
eval_modulus(t, v);
|
|
626
|
+
else if (&t == &v)
|
|
627
|
+
{
|
|
628
|
+
T temp;
|
|
629
|
+
eval_modulus(temp, u, v);
|
|
630
|
+
temp.swap(t);
|
|
631
|
+
}
|
|
632
|
+
else
|
|
633
|
+
{
|
|
634
|
+
t = u;
|
|
635
|
+
eval_modulus(t, v);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
template <class T, class U>
|
|
639
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
|
|
640
|
+
{
|
|
641
|
+
T vv;
|
|
642
|
+
vv = v;
|
|
643
|
+
eval_modulus(t, u, vv);
|
|
644
|
+
}
|
|
645
|
+
template <class T, class U>
|
|
646
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
|
|
647
|
+
{
|
|
648
|
+
T vv(v);
|
|
649
|
+
eval_modulus(t, u, vv);
|
|
650
|
+
}
|
|
651
|
+
template <class T, class U>
|
|
652
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
|
|
653
|
+
{
|
|
654
|
+
T uu;
|
|
655
|
+
uu = u;
|
|
656
|
+
eval_modulus(t, uu, v);
|
|
657
|
+
}
|
|
658
|
+
template <class T, class U>
|
|
659
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
|
|
660
|
+
{
|
|
661
|
+
T uu(u);
|
|
662
|
+
eval_modulus(t, uu, v);
|
|
663
|
+
}
|
|
664
|
+
template <class T, class U, class V>
|
|
665
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus_default(T& t, const U& u, const V& v)
|
|
666
|
+
{
|
|
667
|
+
BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
|
|
668
|
+
{
|
|
669
|
+
if ((void*)&t == (void*)&v)
|
|
670
|
+
{
|
|
671
|
+
T temp(u);
|
|
672
|
+
eval_modulus(temp, v);
|
|
673
|
+
t = temp;
|
|
674
|
+
}
|
|
675
|
+
else
|
|
676
|
+
{
|
|
677
|
+
t = u;
|
|
678
|
+
eval_modulus(t, v);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
else
|
|
682
|
+
{
|
|
683
|
+
t = u;
|
|
684
|
+
eval_modulus(t, v);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
template <class T, class U, class V>
|
|
688
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus(T& t, const U& u, const V& v)
|
|
689
|
+
{
|
|
690
|
+
eval_modulus_default(t, u, v);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
template <class T, class U, class V>
|
|
694
|
+
BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and(T& t, const U& u, const V& v);
|
|
695
|
+
|
|
696
|
+
template <class T>
|
|
697
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and_default(T& t, const T& u, const T& v)
|
|
698
|
+
{
|
|
699
|
+
if (&t == &v)
|
|
700
|
+
{
|
|
701
|
+
eval_bitwise_and(t, u);
|
|
702
|
+
}
|
|
703
|
+
else if (&t == &u)
|
|
704
|
+
{
|
|
705
|
+
eval_bitwise_and(t, v);
|
|
706
|
+
}
|
|
707
|
+
else
|
|
708
|
+
{
|
|
709
|
+
t = u;
|
|
710
|
+
eval_bitwise_and(t, v);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
template <class T, class U>
|
|
714
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
|
|
715
|
+
{
|
|
716
|
+
T vv;
|
|
717
|
+
vv = v;
|
|
718
|
+
eval_bitwise_and(t, u, vv);
|
|
719
|
+
}
|
|
720
|
+
template <class T, class U>
|
|
721
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
|
|
722
|
+
{
|
|
723
|
+
T vv(v);
|
|
724
|
+
eval_bitwise_and(t, u, vv);
|
|
725
|
+
}
|
|
726
|
+
template <class T, class U>
|
|
727
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_and_default(T& t, const U& u, const T& v)
|
|
728
|
+
{
|
|
729
|
+
eval_bitwise_and(t, v, u);
|
|
730
|
+
}
|
|
731
|
+
template <class T, class U, class V>
|
|
732
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value || std::is_same<T, V>::value>::type eval_bitwise_and_default(T& t, const U& u, const V& v)
|
|
733
|
+
{
|
|
734
|
+
t = u;
|
|
735
|
+
eval_bitwise_and(t, v);
|
|
736
|
+
}
|
|
737
|
+
template <class T, class U, class V>
|
|
738
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and(T& t, const U& u, const V& v)
|
|
739
|
+
{
|
|
740
|
+
eval_bitwise_and_default(t, u, v);
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
template <class T, class U, class V>
|
|
744
|
+
BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or(T& t, const U& u, const V& v);
|
|
745
|
+
|
|
746
|
+
template <class T>
|
|
747
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or_default(T& t, const T& u, const T& v)
|
|
748
|
+
{
|
|
749
|
+
if (&t == &v)
|
|
750
|
+
{
|
|
751
|
+
eval_bitwise_or(t, u);
|
|
752
|
+
}
|
|
753
|
+
else if (&t == &u)
|
|
754
|
+
{
|
|
755
|
+
eval_bitwise_or(t, v);
|
|
756
|
+
}
|
|
757
|
+
else
|
|
758
|
+
{
|
|
759
|
+
t = u;
|
|
760
|
+
eval_bitwise_or(t, v);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
template <class T, class U>
|
|
764
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
|
|
765
|
+
{
|
|
766
|
+
T vv;
|
|
767
|
+
vv = v;
|
|
768
|
+
eval_bitwise_or(t, u, vv);
|
|
769
|
+
}
|
|
770
|
+
template <class T, class U>
|
|
771
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
|
|
772
|
+
{
|
|
773
|
+
T vv(v);
|
|
774
|
+
eval_bitwise_or(t, u, vv);
|
|
775
|
+
}
|
|
776
|
+
template <class T, class U>
|
|
777
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_or_default(T& t, const U& u, const T& v)
|
|
778
|
+
{
|
|
779
|
+
eval_bitwise_or(t, v, u);
|
|
780
|
+
}
|
|
781
|
+
template <class T, class U, class V>
|
|
782
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or_default(T& t, const U& u, const V& v)
|
|
783
|
+
{
|
|
784
|
+
BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
|
|
785
|
+
{
|
|
786
|
+
if ((void*)&t == (void*)&v)
|
|
787
|
+
{
|
|
788
|
+
eval_bitwise_or(t, u);
|
|
789
|
+
}
|
|
790
|
+
else
|
|
791
|
+
{
|
|
792
|
+
t = u;
|
|
793
|
+
eval_bitwise_or(t, v);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
else
|
|
797
|
+
{
|
|
798
|
+
t = u;
|
|
799
|
+
eval_bitwise_or(t, v);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
template <class T, class U, class V>
|
|
803
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or(T& t, const U& u, const V& v)
|
|
804
|
+
{
|
|
805
|
+
eval_bitwise_or_default(t, u, v);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
template <class T, class U, class V>
|
|
809
|
+
BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor(T& t, const U& u, const V& v);
|
|
810
|
+
|
|
811
|
+
template <class T>
|
|
812
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor_default(T& t, const T& u, const T& v)
|
|
813
|
+
{
|
|
814
|
+
if (&t == &v)
|
|
815
|
+
{
|
|
816
|
+
eval_bitwise_xor(t, u);
|
|
817
|
+
}
|
|
818
|
+
else if (&t == &u)
|
|
819
|
+
{
|
|
820
|
+
eval_bitwise_xor(t, v);
|
|
821
|
+
}
|
|
822
|
+
else
|
|
823
|
+
{
|
|
824
|
+
t = u;
|
|
825
|
+
eval_bitwise_xor(t, v);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
template <class T, class U>
|
|
829
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
|
|
830
|
+
{
|
|
831
|
+
T vv;
|
|
832
|
+
vv = v;
|
|
833
|
+
eval_bitwise_xor(t, u, vv);
|
|
834
|
+
}
|
|
835
|
+
template <class T, class U>
|
|
836
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
|
|
837
|
+
{
|
|
838
|
+
T vv(v);
|
|
839
|
+
eval_bitwise_xor(t, u, vv);
|
|
840
|
+
}
|
|
841
|
+
template <class T, class U>
|
|
842
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_xor_default(T& t, const U& u, const T& v)
|
|
843
|
+
{
|
|
844
|
+
eval_bitwise_xor(t, v, u);
|
|
845
|
+
}
|
|
846
|
+
template <class T, class U, class V>
|
|
847
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor_default(T& t, const U& u, const V& v)
|
|
848
|
+
{
|
|
849
|
+
BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
|
|
850
|
+
{
|
|
851
|
+
if ((void*)&t == (void*)&v)
|
|
852
|
+
{
|
|
853
|
+
eval_bitwise_xor(t, u);
|
|
854
|
+
}
|
|
855
|
+
else
|
|
856
|
+
{
|
|
857
|
+
t = u;
|
|
858
|
+
eval_bitwise_xor(t, v);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
else
|
|
862
|
+
{
|
|
863
|
+
t = u;
|
|
864
|
+
eval_bitwise_xor(t, v);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
template <class T, class U, class V>
|
|
868
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor(T& t, const U& u, const V& v)
|
|
869
|
+
{
|
|
870
|
+
eval_bitwise_xor_default(t, u, v);
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
template <class T>
|
|
874
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_increment(T& val)
|
|
875
|
+
{
|
|
876
|
+
using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
|
|
877
|
+
eval_add(val, static_cast<ui_type>(1u));
|
|
878
|
+
}
|
|
879
|
+
template <class T>
|
|
880
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_decrement(T& val)
|
|
881
|
+
{
|
|
882
|
+
using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
|
|
883
|
+
eval_subtract(val, static_cast<ui_type>(1u));
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
template <class T, class U, class V>
|
|
887
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_left_shift(T& result, const U& arg, const V val)
|
|
888
|
+
{
|
|
889
|
+
result = arg;
|
|
890
|
+
eval_left_shift(result, val);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
template <class T, class U, class V>
|
|
894
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_right_shift(T& result, const U& arg, const V val)
|
|
895
|
+
{
|
|
896
|
+
result = arg;
|
|
897
|
+
eval_right_shift(result, val);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
template <class T>
|
|
901
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool eval_is_zero(const T& val)
|
|
902
|
+
{
|
|
903
|
+
using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
|
|
904
|
+
return val.compare(static_cast<ui_type>(0)) == 0;
|
|
905
|
+
}
|
|
906
|
+
template <class T>
|
|
907
|
+
inline BOOST_MP_CXX14_CONSTEXPR int eval_get_sign(const T& val)
|
|
908
|
+
{
|
|
909
|
+
using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
|
|
910
|
+
return val.compare(static_cast<ui_type>(0));
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
template <class T, class V, class U>
|
|
914
|
+
inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::false_type&, const std::false_type&)
|
|
915
|
+
{
|
|
916
|
+
using component_number_type = typename component_type<number<T> >::type;
|
|
917
|
+
|
|
918
|
+
boost::multiprecision::detail::scoped_precision_options<component_number_type> sp(result);
|
|
919
|
+
(void)sp;
|
|
920
|
+
|
|
921
|
+
component_number_type x(v1), y(v2);
|
|
922
|
+
assign_components(result, x.backend(), y.backend());
|
|
923
|
+
}
|
|
924
|
+
template <class T, class V, class U>
|
|
925
|
+
inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::true_type&, const std::false_type&)
|
|
926
|
+
{
|
|
927
|
+
boost::multiprecision::detail::scoped_source_precision<number<V>> scope;
|
|
928
|
+
(void)scope;
|
|
929
|
+
assign_components_imp2(result, number<V>(v1), v2, std::false_type(), std::false_type());
|
|
930
|
+
}
|
|
931
|
+
template <class T, class V, class U>
|
|
932
|
+
inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::true_type&, const std::true_type&)
|
|
933
|
+
{
|
|
934
|
+
boost::multiprecision::detail::scoped_source_precision<number<V>> scope1;
|
|
935
|
+
boost::multiprecision::detail::scoped_source_precision<number<U>> scope2;
|
|
936
|
+
(void)scope1;
|
|
937
|
+
(void)scope2;
|
|
938
|
+
assign_components_imp2(result, number<V>(v1), number<U>(v2), std::false_type(), std::false_type());
|
|
939
|
+
}
|
|
940
|
+
template <class T, class V, class U>
|
|
941
|
+
inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::false_type&, const std::true_type&)
|
|
942
|
+
{
|
|
943
|
+
boost::multiprecision::detail::scoped_source_precision<number<U>> scope;
|
|
944
|
+
(void)scope;
|
|
945
|
+
assign_components_imp2(result, v1, number<U>(v2), std::false_type(), std::false_type());
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
|
|
949
|
+
template <class T, class V, class U>
|
|
950
|
+
inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp(T& result, const V& v1, const U& v2, const std::integral_constant<int, number_kind_rational>&)
|
|
951
|
+
{
|
|
952
|
+
result = v1;
|
|
953
|
+
T t;
|
|
954
|
+
t = v2;
|
|
955
|
+
eval_divide(result, t);
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
template <class T, class V, class U, int N>
|
|
959
|
+
inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp(T& result, const V& v1, const U& v2, const std::integral_constant<int, N>&)
|
|
960
|
+
{
|
|
961
|
+
assign_components_imp2(result, v1, v2, boost::multiprecision::detail::is_backend<V>(), boost::multiprecision::detail::is_backend<U>());
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
template <class T, class V, class U>
|
|
965
|
+
inline BOOST_MP_CXX14_CONSTEXPR void assign_components(T& result, const V& v1, const U& v2)
|
|
966
|
+
{
|
|
967
|
+
return assign_components_imp(result, v1, v2, typename number_category<T>::type());
|
|
968
|
+
}
|
|
969
|
+
#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
|
|
970
|
+
template <class Result, class Traits>
|
|
971
|
+
inline void assign_from_string_view(Result& result, const std::basic_string_view<char, Traits>& view)
|
|
972
|
+
{
|
|
973
|
+
// since most (all?) backends require a const char* to construct from, we just
|
|
974
|
+
// convert to that:
|
|
975
|
+
std::string s(view);
|
|
976
|
+
result = s.c_str();
|
|
977
|
+
}
|
|
978
|
+
template <class Result, class Traits>
|
|
979
|
+
inline void assign_from_string_view(Result& result, const std::basic_string_view<char, Traits>& view_x, const std::basic_string_view<char, Traits>& view_y)
|
|
980
|
+
{
|
|
981
|
+
// since most (all?) backends require a const char* to construct from, we just
|
|
982
|
+
// convert to that:
|
|
983
|
+
std::string x(view_x), y(view_y);
|
|
984
|
+
assign_components(result, x.c_str(), y.c_str());
|
|
985
|
+
}
|
|
986
|
+
#endif
|
|
987
|
+
template <class R, int b>
|
|
988
|
+
struct has_enough_bits
|
|
989
|
+
{
|
|
990
|
+
template <class T>
|
|
991
|
+
struct type : public std::integral_constant<bool, !std::is_same<R, T>::value && (std::numeric_limits<T>::digits >= b)>
|
|
992
|
+
{};
|
|
993
|
+
};
|
|
994
|
+
|
|
995
|
+
template <class R>
|
|
996
|
+
struct terminal
|
|
997
|
+
{
|
|
998
|
+
BOOST_MP_CXX14_CONSTEXPR terminal(const R& v) : value(v) {}
|
|
999
|
+
BOOST_MP_CXX14_CONSTEXPR terminal() {}
|
|
1000
|
+
BOOST_MP_CXX14_CONSTEXPR terminal& operator=(R val)
|
|
1001
|
+
{
|
|
1002
|
+
value = val;
|
|
1003
|
+
return *this;
|
|
1004
|
+
}
|
|
1005
|
+
R value;
|
|
1006
|
+
BOOST_MP_CXX14_CONSTEXPR operator R() const { return value; }
|
|
1007
|
+
};
|
|
1008
|
+
|
|
1009
|
+
template <class Tuple, int i, class T, bool = (i == std::tuple_size<Tuple>::value)>
|
|
1010
|
+
struct find_index_of_type
|
|
1011
|
+
{
|
|
1012
|
+
static constexpr int value =
|
|
1013
|
+
std::is_same<T, typename std::tuple_element<static_cast<std::size_t>(i), Tuple>::type>::value
|
|
1014
|
+
? i
|
|
1015
|
+
: find_index_of_type<Tuple, i + 1, T>::value;
|
|
1016
|
+
};
|
|
1017
|
+
template <class Tuple, int i, class T>
|
|
1018
|
+
struct find_index_of_type<Tuple, i, T, true>
|
|
1019
|
+
{
|
|
1020
|
+
static constexpr int value = -1;
|
|
1021
|
+
};
|
|
1022
|
+
|
|
1023
|
+
|
|
1024
|
+
template <class R, class B>
|
|
1025
|
+
struct calculate_next_larger_type
|
|
1026
|
+
{
|
|
1027
|
+
// Find which list we're looking through:
|
|
1028
|
+
using list_type = typename std::conditional<
|
|
1029
|
+
boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value,
|
|
1030
|
+
typename B::signed_types,
|
|
1031
|
+
typename std::conditional<
|
|
1032
|
+
boost::multiprecision::detail::is_unsigned<R>::value,
|
|
1033
|
+
typename B::unsigned_types,
|
|
1034
|
+
typename B::float_types>::type>::type;
|
|
1035
|
+
static constexpr int start = find_index_of_type<list_type, 0, R>::value;
|
|
1036
|
+
static constexpr int index_of_type = boost::multiprecision::detail::find_index_of_large_enough_type<list_type, start == INT_MAX ? 0 : start + 1, boost::multiprecision::detail::bits_of<R>::value> ::value;
|
|
1037
|
+
using type = typename boost::multiprecision::detail::dereference_tuple<index_of_type, list_type, terminal<R> >::type;
|
|
1038
|
+
};
|
|
1039
|
+
|
|
1040
|
+
template <class R, class T>
|
|
1041
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<R>::value, bool>::type check_in_range(const T& t)
|
|
1042
|
+
{
|
|
1043
|
+
// Can t fit in an R?
|
|
1044
|
+
if ((t > 0) && std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (t > (std::numeric_limits<R>::max)()))
|
|
1045
|
+
return true;
|
|
1046
|
+
else
|
|
1047
|
+
return false;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
template <class R, class B>
|
|
1051
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<R>::value>::type eval_convert_to(R* result, const B& backend)
|
|
1052
|
+
{
|
|
1053
|
+
using next_type = typename calculate_next_larger_type<R, B>::type;
|
|
1054
|
+
next_type n = next_type();
|
|
1055
|
+
eval_convert_to(&n, backend);
|
|
1056
|
+
BOOST_IF_CONSTEXPR(!boost::multiprecision::detail::is_unsigned<R>::value && std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded)
|
|
1057
|
+
{
|
|
1058
|
+
if(n > static_cast<next_type>((std::numeric_limits<R>::max)()))
|
|
1059
|
+
{
|
|
1060
|
+
*result = (std::numeric_limits<R>::max)();
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized&& std::numeric_limits<R>::is_bounded)
|
|
1065
|
+
{
|
|
1066
|
+
if (n < static_cast<next_type>((std::numeric_limits<R>::min)()))
|
|
1067
|
+
{
|
|
1068
|
+
*result = (std::numeric_limits<R>::min)();
|
|
1069
|
+
return;
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
*result = static_cast<R>(n);
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
template <class R, class B>
|
|
1076
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !boost::multiprecision::detail::is_integral<R>::value && !std::is_enum<R>::value>::type eval_convert_to(R* result, const B& backend)
|
|
1077
|
+
{
|
|
1078
|
+
using next_type = typename calculate_next_larger_type<R, B>::type;
|
|
1079
|
+
next_type n = next_type();
|
|
1080
|
+
eval_convert_to(&n, backend);
|
|
1081
|
+
BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded)
|
|
1082
|
+
{
|
|
1083
|
+
if ((n > (next_type)(std::numeric_limits<R>::max)() || (n < (next_type) - (std::numeric_limits<R>::max)())))
|
|
1084
|
+
{
|
|
1085
|
+
*result = n > 0 ? (std::numeric_limits<R>::max)() : -(std::numeric_limits<R>::max)();
|
|
1086
|
+
}
|
|
1087
|
+
else
|
|
1088
|
+
*result = static_cast<R>(n);
|
|
1089
|
+
}
|
|
1090
|
+
else
|
|
1091
|
+
*result = static_cast<R>(n);
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
template <class R, class B>
|
|
1095
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_enum<R>::value>::type eval_convert_to(R* result, const B& backend)
|
|
1096
|
+
{
|
|
1097
|
+
typename std::underlying_type<R>::type t{};
|
|
1098
|
+
eval_convert_to(&t, backend);
|
|
1099
|
+
*result = static_cast<R>(t);
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
#ifndef BOOST_MP_STANDALONE
|
|
1103
|
+
template <class R, class B>
|
|
1104
|
+
inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const std::integral_constant<bool, false>&)
|
|
1105
|
+
{
|
|
1106
|
+
//
|
|
1107
|
+
// We ran out of types to try for the conversion, try
|
|
1108
|
+
// a lexical_cast and hope for the best:
|
|
1109
|
+
//
|
|
1110
|
+
BOOST_IF_CONSTEXPR (std::numeric_limits<R>::is_integer && !std::numeric_limits<R>::is_signed)
|
|
1111
|
+
if (eval_get_sign(backend) < 0)
|
|
1112
|
+
BOOST_MP_THROW_EXCEPTION(std::range_error("Attempt to convert negative value to an unsigned integer results in undefined behaviour"));
|
|
1113
|
+
BOOST_MP_TRY {
|
|
1114
|
+
result->value = boost::lexical_cast<R>(backend.str(0, std::ios_base::fmtflags(0)));
|
|
1115
|
+
}
|
|
1116
|
+
BOOST_MP_CATCH (const bad_lexical_cast&)
|
|
1117
|
+
{
|
|
1118
|
+
if (eval_get_sign(backend) < 0)
|
|
1119
|
+
{
|
|
1120
|
+
BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_integer && !std::numeric_limits<R>::is_signed)
|
|
1121
|
+
*result = (std::numeric_limits<R>::max)(); // we should never get here, exception above will be raised.
|
|
1122
|
+
else BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_integer)
|
|
1123
|
+
*result = (std::numeric_limits<R>::min)();
|
|
1124
|
+
else
|
|
1125
|
+
*result = -(std::numeric_limits<R>::max)();
|
|
1126
|
+
}
|
|
1127
|
+
else
|
|
1128
|
+
*result = (std::numeric_limits<R>::max)();
|
|
1129
|
+
}
|
|
1130
|
+
BOOST_MP_CATCH_END
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
template <class R, class B>
|
|
1134
|
+
inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const std::integral_constant<bool, true>&)
|
|
1135
|
+
{
|
|
1136
|
+
//
|
|
1137
|
+
// Last chance conversion to an unsigned integer.
|
|
1138
|
+
// We ran out of types to try for the conversion, try
|
|
1139
|
+
// a lexical_cast and hope for the best:
|
|
1140
|
+
//
|
|
1141
|
+
if (eval_get_sign(backend) < 0)
|
|
1142
|
+
BOOST_MP_THROW_EXCEPTION(std::range_error("Attempt to convert negative value to an unsigned integer results in undefined behaviour"));
|
|
1143
|
+
BOOST_MP_TRY {
|
|
1144
|
+
B t(backend);
|
|
1145
|
+
R mask = ~static_cast<R>(0u);
|
|
1146
|
+
eval_bitwise_and(t, mask);
|
|
1147
|
+
result->value = boost::lexical_cast<R>(t.str(0, std::ios_base::fmtflags(0)));
|
|
1148
|
+
}
|
|
1149
|
+
BOOST_MP_CATCH (const bad_lexical_cast&)
|
|
1150
|
+
{
|
|
1151
|
+
// We should never really get here...
|
|
1152
|
+
*result = (std::numeric_limits<R>::max)();
|
|
1153
|
+
}
|
|
1154
|
+
BOOST_MP_CATCH_END
|
|
1155
|
+
}
|
|
1156
|
+
#else // Using standalone mode
|
|
1157
|
+
|
|
1158
|
+
template <class R, class B>
|
|
1159
|
+
inline void last_chance_eval_convert_to(terminal<R>*, const B&, const std::integral_constant<bool, false>&)
|
|
1160
|
+
{
|
|
1161
|
+
static_assert(sizeof(R) == 1, "This type can not be used in standalone mode. Please de-activate and file a bug at https://github.com/boostorg/multiprecision/");
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
template <class R, class B>
|
|
1165
|
+
inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const std::integral_constant<bool, true>&)
|
|
1166
|
+
{
|
|
1167
|
+
static_cast<void>(result);
|
|
1168
|
+
static_cast<void>(backend);
|
|
1169
|
+
|
|
1170
|
+
static_assert(sizeof(R) == 1, "This type can not be used in standalone mode. Please de-activate and file a bug at https://github.com/boostorg/multiprecision/");
|
|
1171
|
+
}
|
|
1172
|
+
#endif
|
|
1173
|
+
|
|
1174
|
+
template <class R, class B>
|
|
1175
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(terminal<R>* result, const B& backend)
|
|
1176
|
+
{
|
|
1177
|
+
using tag_type = std::integral_constant<bool, boost::multiprecision::detail::is_unsigned<R>::value && number_category<B>::value == number_kind_integer>;
|
|
1178
|
+
last_chance_eval_convert_to(result, backend, tag_type());
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
template <class B1, class B2, expression_template_option et>
|
|
1182
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(terminal<number<B1, et> >* result, const B2& backend)
|
|
1183
|
+
{
|
|
1184
|
+
//
|
|
1185
|
+
// We ran out of types to try for the conversion, try
|
|
1186
|
+
// a generic conversion and hope for the best:
|
|
1187
|
+
//
|
|
1188
|
+
boost::multiprecision::detail::generic_interconvert(result->value.backend(), backend, number_category<B1>(), number_category<B2>());
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
template <class B>
|
|
1192
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::string* result, const B& backend)
|
|
1193
|
+
{
|
|
1194
|
+
*result = backend.str(0, std::ios_base::fmtflags(0));
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
template <class B>
|
|
1198
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<float>* result, const B& backend)
|
|
1199
|
+
{
|
|
1200
|
+
using scalar_type = typename scalar_result_from_possible_complex<multiprecision::number<B> >::type;
|
|
1201
|
+
scalar_type re, im;
|
|
1202
|
+
eval_real(re.backend(), backend);
|
|
1203
|
+
eval_imag(im.backend(), backend);
|
|
1204
|
+
|
|
1205
|
+
*result = std::complex<float>(re.template convert_to<float>(), im.template convert_to<float>());
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
template <class B>
|
|
1209
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<double>* result, const B& backend)
|
|
1210
|
+
{
|
|
1211
|
+
using scalar_type = typename scalar_result_from_possible_complex<multiprecision::number<B> >::type;
|
|
1212
|
+
scalar_type re, im;
|
|
1213
|
+
eval_real(re.backend(), backend);
|
|
1214
|
+
eval_imag(im.backend(), backend);
|
|
1215
|
+
|
|
1216
|
+
*result = std::complex<double>(re.template convert_to<double>(), im.template convert_to<double>());
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
template <class B>
|
|
1220
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<long double>* result, const B& backend)
|
|
1221
|
+
{
|
|
1222
|
+
using scalar_type = typename scalar_result_from_possible_complex<multiprecision::number<B> >::type;
|
|
1223
|
+
scalar_type re, im;
|
|
1224
|
+
eval_real(re.backend(), backend);
|
|
1225
|
+
eval_imag(im.backend(), backend);
|
|
1226
|
+
|
|
1227
|
+
*result = std::complex<long double>(re.template convert_to<long double>(), im.template convert_to<long double>());
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
//
|
|
1231
|
+
// Functions:
|
|
1232
|
+
//
|
|
1233
|
+
template <class T, class U>
|
|
1234
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_abs(T& result, const U& arg)
|
|
1235
|
+
{
|
|
1236
|
+
using type_list = typename U::signed_types ;
|
|
1237
|
+
using front = typename std::tuple_element<0, type_list>::type;
|
|
1238
|
+
result = arg;
|
|
1239
|
+
if (arg.compare(front(0)) < 0)
|
|
1240
|
+
result.negate();
|
|
1241
|
+
}
|
|
1242
|
+
template <class T, class U>
|
|
1243
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_fabs(T& result, const U& arg)
|
|
1244
|
+
{
|
|
1245
|
+
static_assert(number_category<T>::value == number_kind_floating_point, "The fabs function is only valid for floating point types.");
|
|
1246
|
+
using type_list = typename U::signed_types ;
|
|
1247
|
+
using front = typename std::tuple_element<0, type_list>::type;
|
|
1248
|
+
result = arg;
|
|
1249
|
+
if (arg.compare(front(0)) < 0)
|
|
1250
|
+
result.negate();
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
template <class Backend>
|
|
1254
|
+
inline BOOST_MP_CXX14_CONSTEXPR int eval_fpclassify(const Backend& arg)
|
|
1255
|
+
{
|
|
1256
|
+
static_assert(number_category<Backend>::value == number_kind_floating_point, "The fpclassify function is only valid for floating point types.");
|
|
1257
|
+
return eval_is_zero(arg) ? FP_ZERO : FP_NORMAL;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
template <class T>
|
|
1261
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_fmod(T& result, const T& a, const T& b)
|
|
1262
|
+
{
|
|
1263
|
+
static_assert(number_category<T>::value == number_kind_floating_point, "The fmod function is only valid for floating point types.");
|
|
1264
|
+
if ((&result == &a) || (&result == &b))
|
|
1265
|
+
{
|
|
1266
|
+
T temp;
|
|
1267
|
+
eval_fmod(temp, a, b);
|
|
1268
|
+
result = temp;
|
|
1269
|
+
return;
|
|
1270
|
+
}
|
|
1271
|
+
switch (eval_fpclassify(a))
|
|
1272
|
+
{
|
|
1273
|
+
case FP_ZERO:
|
|
1274
|
+
result = a;
|
|
1275
|
+
return;
|
|
1276
|
+
case FP_INFINITE:
|
|
1277
|
+
case FP_NAN:
|
|
1278
|
+
result = std::numeric_limits<number<T> >::quiet_NaN().backend();
|
|
1279
|
+
errno = EDOM;
|
|
1280
|
+
return;
|
|
1281
|
+
}
|
|
1282
|
+
switch (eval_fpclassify(b))
|
|
1283
|
+
{
|
|
1284
|
+
case FP_ZERO:
|
|
1285
|
+
case FP_NAN:
|
|
1286
|
+
result = std::numeric_limits<number<T> >::quiet_NaN().backend();
|
|
1287
|
+
errno = EDOM;
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1290
|
+
T n;
|
|
1291
|
+
eval_divide(result, a, b);
|
|
1292
|
+
if (eval_get_sign(result) < 0)
|
|
1293
|
+
eval_ceil(n, result);
|
|
1294
|
+
else
|
|
1295
|
+
eval_floor(n, result);
|
|
1296
|
+
eval_multiply(n, b);
|
|
1297
|
+
eval_subtract(result, a, n);
|
|
1298
|
+
if (eval_get_sign(result) != 0)
|
|
1299
|
+
{
|
|
1300
|
+
//
|
|
1301
|
+
// Sanity check, that due to rounding errors in division,
|
|
1302
|
+
// we haven't accidently calculated the wrong value:
|
|
1303
|
+
// See https://github.com/boostorg/multiprecision/issues/604 for an example.
|
|
1304
|
+
//
|
|
1305
|
+
if (eval_get_sign(result) == eval_get_sign(b))
|
|
1306
|
+
{
|
|
1307
|
+
if (result.compare(b) >= 0)
|
|
1308
|
+
{
|
|
1309
|
+
eval_subtract(result, b);
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
else
|
|
1313
|
+
{
|
|
1314
|
+
n = b;
|
|
1315
|
+
n.negate();
|
|
1316
|
+
if (result.compare(n) >= 0)
|
|
1317
|
+
{
|
|
1318
|
+
eval_subtract(result, n);
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
template <class T, class A>
|
|
1324
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_fmod(T& result, const T& x, const A& a)
|
|
1325
|
+
{
|
|
1326
|
+
using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
|
|
1327
|
+
using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
|
|
1328
|
+
cast_type c;
|
|
1329
|
+
c = a;
|
|
1330
|
+
eval_fmod(result, x, c);
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
template <class T, class A>
|
|
1334
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_fmod(T& result, const A& x, const T& a)
|
|
1335
|
+
{
|
|
1336
|
+
using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
|
|
1337
|
+
using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
|
|
1338
|
+
cast_type c;
|
|
1339
|
+
c = x;
|
|
1340
|
+
eval_fmod(result, c, a);
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
template <class T>
|
|
1344
|
+
BOOST_MP_CXX14_CONSTEXPR void eval_round(T& result, const T& a);
|
|
1345
|
+
|
|
1346
|
+
template <class T>
|
|
1347
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_remquo(T& result, const T& a, const T& b, int* pi)
|
|
1348
|
+
{
|
|
1349
|
+
static_assert(number_category<T>::value == number_kind_floating_point, "The remquo function is only valid for floating point types.");
|
|
1350
|
+
if ((&result == &a) || (&result == &b))
|
|
1351
|
+
{
|
|
1352
|
+
T temp;
|
|
1353
|
+
eval_remquo(temp, a, b, pi);
|
|
1354
|
+
result = temp;
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
T n;
|
|
1358
|
+
eval_divide(result, a, b);
|
|
1359
|
+
eval_round(n, result);
|
|
1360
|
+
eval_convert_to(pi, n);
|
|
1361
|
+
eval_multiply(n, b);
|
|
1362
|
+
eval_subtract(result, a, n);
|
|
1363
|
+
if (eval_is_zero(result))
|
|
1364
|
+
{
|
|
1365
|
+
if (eval_signbit(a))
|
|
1366
|
+
result.negate();
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
template <class T, class A>
|
|
1370
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_remquo(T& result, const T& x, const A& a, int* pi)
|
|
1371
|
+
{
|
|
1372
|
+
using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
|
|
1373
|
+
using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
|
|
1374
|
+
cast_type c = cast_type();
|
|
1375
|
+
c = a;
|
|
1376
|
+
eval_remquo(result, x, c, pi);
|
|
1377
|
+
}
|
|
1378
|
+
template <class T, class A>
|
|
1379
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_remquo(T& result, const A& x, const T& a, int* pi)
|
|
1380
|
+
{
|
|
1381
|
+
using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
|
|
1382
|
+
using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
|
|
1383
|
+
cast_type c = cast_type();
|
|
1384
|
+
c = x;
|
|
1385
|
+
eval_remquo(result, c, a, pi);
|
|
1386
|
+
}
|
|
1387
|
+
template <class T, class U, class V>
|
|
1388
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_remainder(T& result, const U& a, const V& b)
|
|
1389
|
+
{
|
|
1390
|
+
int i(0);
|
|
1391
|
+
eval_remquo(result, a, b, &i);
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
template <class B>
|
|
1395
|
+
BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const B& a, const B& b);
|
|
1396
|
+
template <class T, class U>
|
|
1397
|
+
BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const T& a, const U& b);
|
|
1398
|
+
template <class B>
|
|
1399
|
+
BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const B& a, const B& b);
|
|
1400
|
+
template <class T, class U>
|
|
1401
|
+
BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const T& a, const U& b);
|
|
1402
|
+
|
|
1403
|
+
template <class T>
|
|
1404
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_fdim(T& result, const T& a, const T& b)
|
|
1405
|
+
{
|
|
1406
|
+
using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
|
|
1407
|
+
const ui_type zero = 0u;
|
|
1408
|
+
switch (eval_fpclassify(b))
|
|
1409
|
+
{
|
|
1410
|
+
case FP_NAN:
|
|
1411
|
+
case FP_INFINITE:
|
|
1412
|
+
result = zero;
|
|
1413
|
+
return;
|
|
1414
|
+
}
|
|
1415
|
+
switch (eval_fpclassify(a))
|
|
1416
|
+
{
|
|
1417
|
+
case FP_NAN:
|
|
1418
|
+
result = zero;
|
|
1419
|
+
return;
|
|
1420
|
+
case FP_INFINITE:
|
|
1421
|
+
result = a;
|
|
1422
|
+
return;
|
|
1423
|
+
}
|
|
1424
|
+
if (eval_gt(a, b))
|
|
1425
|
+
{
|
|
1426
|
+
eval_subtract(result, a, b);
|
|
1427
|
+
}
|
|
1428
|
+
else
|
|
1429
|
+
result = zero;
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
template <class T, class A>
|
|
1433
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value>::type eval_fdim(T& result, const T& a, const A& b)
|
|
1434
|
+
{
|
|
1435
|
+
using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
|
|
1436
|
+
using arithmetic_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
|
|
1437
|
+
const ui_type zero = 0u;
|
|
1438
|
+
arithmetic_type canonical_b = b;
|
|
1439
|
+
switch (BOOST_MP_FPCLASSIFY(b))
|
|
1440
|
+
{
|
|
1441
|
+
case FP_NAN:
|
|
1442
|
+
case FP_INFINITE:
|
|
1443
|
+
result = zero;
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
switch (eval_fpclassify(a))
|
|
1447
|
+
{
|
|
1448
|
+
case FP_NAN:
|
|
1449
|
+
result = zero;
|
|
1450
|
+
return;
|
|
1451
|
+
case FP_INFINITE:
|
|
1452
|
+
result = a;
|
|
1453
|
+
return;
|
|
1454
|
+
}
|
|
1455
|
+
if (eval_gt(a, canonical_b))
|
|
1456
|
+
{
|
|
1457
|
+
eval_subtract(result, a, canonical_b);
|
|
1458
|
+
}
|
|
1459
|
+
else
|
|
1460
|
+
result = zero;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
template <class T, class A>
|
|
1464
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value>::type eval_fdim(T& result, const A& a, const T& b)
|
|
1465
|
+
{
|
|
1466
|
+
using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
|
|
1467
|
+
using arithmetic_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
|
|
1468
|
+
const ui_type zero = 0u;
|
|
1469
|
+
arithmetic_type canonical_a = a;
|
|
1470
|
+
switch (eval_fpclassify(b))
|
|
1471
|
+
{
|
|
1472
|
+
case FP_NAN:
|
|
1473
|
+
case FP_INFINITE:
|
|
1474
|
+
result = zero;
|
|
1475
|
+
return;
|
|
1476
|
+
}
|
|
1477
|
+
switch (BOOST_MP_FPCLASSIFY(a))
|
|
1478
|
+
{
|
|
1479
|
+
case FP_NAN:
|
|
1480
|
+
result = zero;
|
|
1481
|
+
return;
|
|
1482
|
+
case FP_INFINITE:
|
|
1483
|
+
result = std::numeric_limits<number<T> >::infinity().backend();
|
|
1484
|
+
return;
|
|
1485
|
+
}
|
|
1486
|
+
if (eval_gt(canonical_a, b))
|
|
1487
|
+
{
|
|
1488
|
+
eval_subtract(result, canonical_a, b);
|
|
1489
|
+
}
|
|
1490
|
+
else
|
|
1491
|
+
result = zero;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
template <class T>
|
|
1495
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_trunc(T& result, const T& a)
|
|
1496
|
+
{
|
|
1497
|
+
static_assert(number_category<T>::value == number_kind_floating_point, "The trunc function is only valid for floating point types.");
|
|
1498
|
+
switch (eval_fpclassify(a))
|
|
1499
|
+
{
|
|
1500
|
+
case FP_NAN:
|
|
1501
|
+
errno = EDOM;
|
|
1502
|
+
// fallthrough...
|
|
1503
|
+
case FP_ZERO:
|
|
1504
|
+
case FP_INFINITE:
|
|
1505
|
+
result = a;
|
|
1506
|
+
return;
|
|
1507
|
+
}
|
|
1508
|
+
if (eval_get_sign(a) < 0)
|
|
1509
|
+
eval_ceil(result, a);
|
|
1510
|
+
else
|
|
1511
|
+
eval_floor(result, a);
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
template <class T>
|
|
1515
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_modf(T& result, T const& arg, T* pipart)
|
|
1516
|
+
{
|
|
1517
|
+
using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
|
|
1518
|
+
int c = eval_fpclassify(arg);
|
|
1519
|
+
if (c == static_cast<int>(FP_NAN))
|
|
1520
|
+
{
|
|
1521
|
+
if (pipart)
|
|
1522
|
+
*pipart = arg;
|
|
1523
|
+
result = arg;
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
else if (c == static_cast<int>(FP_INFINITE))
|
|
1527
|
+
{
|
|
1528
|
+
if (pipart)
|
|
1529
|
+
*pipart = arg;
|
|
1530
|
+
result = ui_type(0u);
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1533
|
+
if (pipart)
|
|
1534
|
+
{
|
|
1535
|
+
eval_trunc(*pipart, arg);
|
|
1536
|
+
eval_subtract(result, arg, *pipart);
|
|
1537
|
+
}
|
|
1538
|
+
else
|
|
1539
|
+
{
|
|
1540
|
+
T ipart;
|
|
1541
|
+
eval_trunc(ipart, arg);
|
|
1542
|
+
eval_subtract(result, arg, ipart);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
template <class T>
|
|
1547
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_round(T& result, const T& a)
|
|
1548
|
+
{
|
|
1549
|
+
static_assert(number_category<T>::value == number_kind_floating_point, "The round function is only valid for floating point types.");
|
|
1550
|
+
using fp_type = typename boost::multiprecision::detail::canonical<float, T>::type;
|
|
1551
|
+
int c = eval_fpclassify(a);
|
|
1552
|
+
if (c == static_cast<int>(FP_NAN))
|
|
1553
|
+
{
|
|
1554
|
+
result = a;
|
|
1555
|
+
errno = EDOM;
|
|
1556
|
+
return;
|
|
1557
|
+
}
|
|
1558
|
+
if ((c == FP_ZERO) || (c == static_cast<int>(FP_INFINITE)))
|
|
1559
|
+
{
|
|
1560
|
+
result = a;
|
|
1561
|
+
}
|
|
1562
|
+
else if (eval_get_sign(a) < 0)
|
|
1563
|
+
{
|
|
1564
|
+
eval_subtract(result, a, fp_type(0.5f));
|
|
1565
|
+
eval_ceil(result, result);
|
|
1566
|
+
}
|
|
1567
|
+
else
|
|
1568
|
+
{
|
|
1569
|
+
eval_add(result, a, fp_type(0.5f));
|
|
1570
|
+
eval_floor(result, result);
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
template <class B>
|
|
1575
|
+
BOOST_MP_CXX14_CONSTEXPR void eval_lcm(B& result, const B& a, const B& b);
|
|
1576
|
+
template <class B>
|
|
1577
|
+
BOOST_MP_CXX14_CONSTEXPR void eval_gcd(B& result, const B& a, const B& b);
|
|
1578
|
+
|
|
1579
|
+
template <class T, class Arithmetic>
|
|
1580
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_gcd(T& result, const T& a, const Arithmetic& b)
|
|
1581
|
+
{
|
|
1582
|
+
using si_type = typename boost::multiprecision::detail::canonical<Arithmetic, T>::type;
|
|
1583
|
+
using default_ops::eval_gcd;
|
|
1584
|
+
T t;
|
|
1585
|
+
t = static_cast<si_type>(b);
|
|
1586
|
+
eval_gcd(result, a, t);
|
|
1587
|
+
}
|
|
1588
|
+
template <class T, class Arithmetic>
|
|
1589
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_gcd(T& result, const Arithmetic& a, const T& b)
|
|
1590
|
+
{
|
|
1591
|
+
eval_gcd(result, b, a);
|
|
1592
|
+
}
|
|
1593
|
+
template <class T, class Arithmetic>
|
|
1594
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_lcm(T& result, const T& a, const Arithmetic& b)
|
|
1595
|
+
{
|
|
1596
|
+
using si_type = typename boost::multiprecision::detail::canonical<Arithmetic, T>::type;
|
|
1597
|
+
using default_ops::eval_lcm;
|
|
1598
|
+
T t;
|
|
1599
|
+
t = static_cast<si_type>(b);
|
|
1600
|
+
eval_lcm(result, a, t);
|
|
1601
|
+
}
|
|
1602
|
+
template <class T, class Arithmetic>
|
|
1603
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_lcm(T& result, const Arithmetic& a, const T& b)
|
|
1604
|
+
{
|
|
1605
|
+
eval_lcm(result, b, a);
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
template <class T>
|
|
1609
|
+
inline BOOST_MP_CXX14_CONSTEXPR std::size_t eval_lsb(const T& val)
|
|
1610
|
+
{
|
|
1611
|
+
using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
|
|
1612
|
+
int c = eval_get_sign(val);
|
|
1613
|
+
if (c == 0)
|
|
1614
|
+
{
|
|
1615
|
+
BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
|
|
1616
|
+
}
|
|
1617
|
+
if (c < 0)
|
|
1618
|
+
{
|
|
1619
|
+
BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
|
|
1620
|
+
}
|
|
1621
|
+
std::size_t result = 0;
|
|
1622
|
+
T mask, t;
|
|
1623
|
+
mask = ui_type(1);
|
|
1624
|
+
do
|
|
1625
|
+
{
|
|
1626
|
+
eval_bitwise_and(t, mask, val);
|
|
1627
|
+
++result;
|
|
1628
|
+
eval_left_shift(mask, 1);
|
|
1629
|
+
} while (eval_is_zero(t));
|
|
1630
|
+
|
|
1631
|
+
return --result;
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
template <class T>
|
|
1635
|
+
inline BOOST_MP_CXX14_CONSTEXPR std::ptrdiff_t eval_msb(const T& val)
|
|
1636
|
+
{
|
|
1637
|
+
int c = eval_get_sign(val);
|
|
1638
|
+
if (c == 0)
|
|
1639
|
+
{
|
|
1640
|
+
BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
|
|
1641
|
+
}
|
|
1642
|
+
if (c < 0)
|
|
1643
|
+
{
|
|
1644
|
+
BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
|
|
1645
|
+
}
|
|
1646
|
+
//
|
|
1647
|
+
// This implementation is really really rubbish - it does
|
|
1648
|
+
// a linear scan for the most-significant-bit. We should really
|
|
1649
|
+
// do a binary search, but as none of our backends actually needs
|
|
1650
|
+
// this implementation, we'll leave it for now. In fact for most
|
|
1651
|
+
// backends it's likely that there will always be a more efficient
|
|
1652
|
+
// native implementation possible.
|
|
1653
|
+
//
|
|
1654
|
+
std::size_t result = 0;
|
|
1655
|
+
T t(val);
|
|
1656
|
+
while (!eval_is_zero(t))
|
|
1657
|
+
{
|
|
1658
|
+
eval_right_shift(t, 1);
|
|
1659
|
+
++result;
|
|
1660
|
+
}
|
|
1661
|
+
--result;
|
|
1662
|
+
|
|
1663
|
+
return static_cast<std::ptrdiff_t>(result);
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
template <class T>
|
|
1667
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool eval_bit_test(const T& val, std::size_t index)
|
|
1668
|
+
{
|
|
1669
|
+
using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
|
|
1670
|
+
T mask, t;
|
|
1671
|
+
mask = ui_type(1);
|
|
1672
|
+
eval_left_shift(mask, index);
|
|
1673
|
+
eval_bitwise_and(t, mask, val);
|
|
1674
|
+
return !eval_is_zero(t);
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
template <class T>
|
|
1678
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_set(T& val, std::size_t index)
|
|
1679
|
+
{
|
|
1680
|
+
using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
|
|
1681
|
+
T mask;
|
|
1682
|
+
mask = ui_type(1);
|
|
1683
|
+
eval_left_shift(mask, index);
|
|
1684
|
+
eval_bitwise_or(val, mask);
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
template <class T>
|
|
1688
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_flip(T& val, std::size_t index)
|
|
1689
|
+
{
|
|
1690
|
+
using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
|
|
1691
|
+
T mask;
|
|
1692
|
+
mask = ui_type(1);
|
|
1693
|
+
eval_left_shift(mask, index);
|
|
1694
|
+
eval_bitwise_xor(val, mask);
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
template <class T>
|
|
1698
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_unset(T& val, std::size_t index)
|
|
1699
|
+
{
|
|
1700
|
+
using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
|
|
1701
|
+
T mask, t;
|
|
1702
|
+
mask = ui_type(1);
|
|
1703
|
+
eval_left_shift(mask, index);
|
|
1704
|
+
eval_bitwise_and(t, mask, val);
|
|
1705
|
+
if (!eval_is_zero(t))
|
|
1706
|
+
eval_bitwise_xor(val, mask);
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
template <class Backend>
|
|
1710
|
+
BOOST_MP_CXX14_CONSTEXPR void eval_qr(const Backend& x, const Backend& y, Backend& q, Backend& r);
|
|
1711
|
+
|
|
1712
|
+
template <class Backend>
|
|
1713
|
+
BOOST_MP_CXX14_CONSTEXPR void eval_karatsuba_sqrt(Backend& result, const Backend& x, Backend& r, Backend& t, size_t bits)
|
|
1714
|
+
{
|
|
1715
|
+
using default_ops::eval_is_zero;
|
|
1716
|
+
using default_ops::eval_subtract;
|
|
1717
|
+
using default_ops::eval_right_shift;
|
|
1718
|
+
using default_ops::eval_left_shift;
|
|
1719
|
+
using default_ops::eval_bit_set;
|
|
1720
|
+
using default_ops::eval_decrement;
|
|
1721
|
+
using default_ops::eval_bitwise_and;
|
|
1722
|
+
using default_ops::eval_add;
|
|
1723
|
+
using default_ops::eval_qr;
|
|
1724
|
+
|
|
1725
|
+
using small_uint = typename std::tuple_element<0, typename Backend::unsigned_types>::type;
|
|
1726
|
+
|
|
1727
|
+
constexpr small_uint zero = 0u;
|
|
1728
|
+
|
|
1729
|
+
// we can calculate it faster with std::sqrt
|
|
1730
|
+
#ifdef BOOST_HAS_INT128
|
|
1731
|
+
if (bits <= 128)
|
|
1732
|
+
{
|
|
1733
|
+
uint128_type a{}, b{}, c{};
|
|
1734
|
+
eval_convert_to(&a, x);
|
|
1735
|
+
c = boost::multiprecision::detail::karatsuba_sqrt(a, b, bits);
|
|
1736
|
+
r = number<Backend>::canonical_value(b);
|
|
1737
|
+
result = number<Backend>::canonical_value(c);
|
|
1738
|
+
return;
|
|
1739
|
+
}
|
|
1740
|
+
#else
|
|
1741
|
+
if (bits <= std::numeric_limits<std::uintmax_t>::digits)
|
|
1742
|
+
{
|
|
1743
|
+
std::uintmax_t a{ 0 }, b{ 0 }, c{ 0 };
|
|
1744
|
+
eval_convert_to(&a, x);
|
|
1745
|
+
c = boost::multiprecision::detail::karatsuba_sqrt(a, b, bits);
|
|
1746
|
+
r = number<Backend>::canonical_value(b);
|
|
1747
|
+
result = number<Backend>::canonical_value(c);
|
|
1748
|
+
return;
|
|
1749
|
+
}
|
|
1750
|
+
#endif
|
|
1751
|
+
// https://hal.inria.fr/file/index/docid/72854/filename/RR-3805.pdf
|
|
1752
|
+
std::size_t b = bits / 4;
|
|
1753
|
+
Backend q(x);
|
|
1754
|
+
eval_right_shift(q, b * 2);
|
|
1755
|
+
Backend s;
|
|
1756
|
+
eval_karatsuba_sqrt(s, q, r, t, bits - b * 2);
|
|
1757
|
+
t = zero;
|
|
1758
|
+
eval_bit_set(t, static_cast<unsigned>(b * 2));
|
|
1759
|
+
eval_left_shift(r, b);
|
|
1760
|
+
eval_decrement(t);
|
|
1761
|
+
eval_bitwise_and(t, x);
|
|
1762
|
+
eval_right_shift(t, b);
|
|
1763
|
+
eval_add(t, r);
|
|
1764
|
+
eval_left_shift(s, 1u);
|
|
1765
|
+
eval_qr(t, s, q, r);
|
|
1766
|
+
eval_left_shift(r, b);
|
|
1767
|
+
t = zero;
|
|
1768
|
+
eval_bit_set(t, static_cast<unsigned>(b));
|
|
1769
|
+
eval_decrement(t);
|
|
1770
|
+
eval_bitwise_and(t, x);
|
|
1771
|
+
eval_add(r, t);
|
|
1772
|
+
eval_left_shift(s, b - 1);
|
|
1773
|
+
eval_add(s, q);
|
|
1774
|
+
eval_multiply(q, q);
|
|
1775
|
+
// we substract after, so it works for unsigned integers too
|
|
1776
|
+
if (r.compare(q) < 0)
|
|
1777
|
+
{
|
|
1778
|
+
t = s;
|
|
1779
|
+
eval_left_shift(t, 1u);
|
|
1780
|
+
eval_decrement(t);
|
|
1781
|
+
eval_add(r, t);
|
|
1782
|
+
eval_decrement(s);
|
|
1783
|
+
}
|
|
1784
|
+
eval_subtract(r, q);
|
|
1785
|
+
result = s;
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
template <class B>
|
|
1789
|
+
void BOOST_MP_CXX14_CONSTEXPR eval_integer_sqrt_bitwise(B& s, B& r, const B& x)
|
|
1790
|
+
{
|
|
1791
|
+
//
|
|
1792
|
+
// This is slow bit-by-bit integer square root, see for example
|
|
1793
|
+
// http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29
|
|
1794
|
+
// There are better methods such as http://hal.inria.fr/docs/00/07/28/54/PDF/RR-3805.pdf
|
|
1795
|
+
// and http://hal.inria.fr/docs/00/07/21/13/PDF/RR-4475.pdf which should be implemented
|
|
1796
|
+
// at some point.
|
|
1797
|
+
//
|
|
1798
|
+
using ui_type = typename boost::multiprecision::detail::canonical<unsigned char, B>::type;
|
|
1799
|
+
|
|
1800
|
+
s = ui_type(0u);
|
|
1801
|
+
if (eval_get_sign(x) == 0)
|
|
1802
|
+
{
|
|
1803
|
+
r = ui_type(0u);
|
|
1804
|
+
return;
|
|
1805
|
+
}
|
|
1806
|
+
std::ptrdiff_t g = static_cast<std::ptrdiff_t>(eval_msb(x));
|
|
1807
|
+
if (g <= 1)
|
|
1808
|
+
{
|
|
1809
|
+
s = ui_type(1);
|
|
1810
|
+
eval_subtract(r, x, s);
|
|
1811
|
+
return;
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
B t;
|
|
1815
|
+
r = x;
|
|
1816
|
+
g /= 2;
|
|
1817
|
+
std::ptrdiff_t org_g = g;
|
|
1818
|
+
eval_bit_set(s, static_cast<std::size_t>(g));
|
|
1819
|
+
eval_bit_set(t, static_cast<std::size_t>(2 * g));
|
|
1820
|
+
eval_subtract(r, x, t);
|
|
1821
|
+
--g;
|
|
1822
|
+
if (eval_get_sign(r) == 0)
|
|
1823
|
+
return;
|
|
1824
|
+
std::ptrdiff_t msbr = static_cast<std::ptrdiff_t>(eval_msb(r));
|
|
1825
|
+
do
|
|
1826
|
+
{
|
|
1827
|
+
if (msbr >= org_g + g + 1)
|
|
1828
|
+
{
|
|
1829
|
+
t = s;
|
|
1830
|
+
eval_left_shift(t, static_cast<std::size_t>(g + 1));
|
|
1831
|
+
eval_bit_set(t, static_cast<std::size_t>(2 * g));
|
|
1832
|
+
if (t.compare(r) <= 0)
|
|
1833
|
+
{
|
|
1834
|
+
BOOST_MP_ASSERT(g >= 0);
|
|
1835
|
+
eval_bit_set(s, static_cast<std::size_t>(g));
|
|
1836
|
+
eval_subtract(r, t);
|
|
1837
|
+
if (eval_get_sign(r) == 0)
|
|
1838
|
+
return;
|
|
1839
|
+
msbr = static_cast<std::ptrdiff_t>(eval_msb(r));
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
--g;
|
|
1843
|
+
} while (g >= 0);
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
template <class Backend>
|
|
1847
|
+
BOOST_MP_CXX14_CONSTEXPR void eval_integer_sqrt(Backend& result, Backend& r, const Backend& x)
|
|
1848
|
+
{
|
|
1849
|
+
#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
|
|
1850
|
+
// recursive Karatsuba sqrt can cause issues in constexpr context:
|
|
1851
|
+
if (BOOST_MP_IS_CONST_EVALUATED(result.size()))
|
|
1852
|
+
return eval_integer_sqrt_bitwise(result, r, x);
|
|
1853
|
+
#endif
|
|
1854
|
+
using small_uint = typename std::tuple_element<0, typename Backend::unsigned_types>::type;
|
|
1855
|
+
|
|
1856
|
+
constexpr small_uint zero = 0u;
|
|
1857
|
+
|
|
1858
|
+
if (eval_is_zero(x))
|
|
1859
|
+
{
|
|
1860
|
+
r = zero;
|
|
1861
|
+
result = zero;
|
|
1862
|
+
return;
|
|
1863
|
+
}
|
|
1864
|
+
Backend t;
|
|
1865
|
+
eval_karatsuba_sqrt(result, x, r, t, eval_msb(x) + 1);
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
template <class B>
|
|
1869
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_conj(B& result, const B& val)
|
|
1870
|
+
{
|
|
1871
|
+
result = val; // assume non-complex result.
|
|
1872
|
+
}
|
|
1873
|
+
template <class B>
|
|
1874
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_proj(B& result, const B& val)
|
|
1875
|
+
{
|
|
1876
|
+
result = val; // assume non-complex result.
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
//
|
|
1880
|
+
// These have to implemented by the backend, declared here so that our macro generated code compiles OK.
|
|
1881
|
+
//
|
|
1882
|
+
template <class T>
|
|
1883
|
+
typename std::enable_if<sizeof(T) == 0>::type eval_floor();
|
|
1884
|
+
template <class T>
|
|
1885
|
+
typename std::enable_if<sizeof(T) == 0>::type eval_ceil();
|
|
1886
|
+
template <class T>
|
|
1887
|
+
typename std::enable_if<sizeof(T) == 0>::type eval_trunc();
|
|
1888
|
+
template <class T>
|
|
1889
|
+
typename std::enable_if<sizeof(T) == 0>::type eval_sqrt();
|
|
1890
|
+
template <class T>
|
|
1891
|
+
typename std::enable_if<sizeof(T) == 0>::type eval_ldexp();
|
|
1892
|
+
template <class T>
|
|
1893
|
+
typename std::enable_if<sizeof(T) == 0>::type eval_frexp();
|
|
1894
|
+
// TODO implement default versions of these:
|
|
1895
|
+
template <class T>
|
|
1896
|
+
typename std::enable_if<sizeof(T) == 0>::type eval_asinh();
|
|
1897
|
+
template <class T>
|
|
1898
|
+
typename std::enable_if<sizeof(T) == 0>::type eval_acosh();
|
|
1899
|
+
template <class T>
|
|
1900
|
+
typename std::enable_if<sizeof(T) == 0>::type eval_atanh();
|
|
1901
|
+
|
|
1902
|
+
//
|
|
1903
|
+
// eval_logb and eval_scalbn simply assume base 2 and forward to
|
|
1904
|
+
// eval_ldexp and eval_frexp:
|
|
1905
|
+
//
|
|
1906
|
+
template <class B>
|
|
1907
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename B::exponent_type eval_ilogb(const B& val)
|
|
1908
|
+
{
|
|
1909
|
+
static_assert(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of ilogb requires a base 2 number type");
|
|
1910
|
+
typename B::exponent_type e(0);
|
|
1911
|
+
switch (eval_fpclassify(val))
|
|
1912
|
+
{
|
|
1913
|
+
case FP_NAN:
|
|
1914
|
+
#ifdef FP_ILOGBNAN
|
|
1915
|
+
return FP_ILOGBNAN > 0 ? (std::numeric_limits<typename B::exponent_type>::max)() : (std::numeric_limits<typename B::exponent_type>::min)();
|
|
1916
|
+
#else
|
|
1917
|
+
return (std::numeric_limits<typename B::exponent_type>::max)();
|
|
1918
|
+
#endif
|
|
1919
|
+
case FP_INFINITE:
|
|
1920
|
+
return (std::numeric_limits<typename B::exponent_type>::max)();
|
|
1921
|
+
case FP_ZERO:
|
|
1922
|
+
return (std::numeric_limits<typename B::exponent_type>::min)();
|
|
1923
|
+
}
|
|
1924
|
+
B result;
|
|
1925
|
+
eval_frexp(result, val, &e);
|
|
1926
|
+
return e - 1;
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
template <class B>
|
|
1930
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_logb(B& result, const B& val)
|
|
1931
|
+
{
|
|
1932
|
+
switch (eval_fpclassify(val))
|
|
1933
|
+
{
|
|
1934
|
+
case FP_NAN:
|
|
1935
|
+
result = val;
|
|
1936
|
+
errno = EDOM;
|
|
1937
|
+
return;
|
|
1938
|
+
case FP_ZERO:
|
|
1939
|
+
result = std::numeric_limits<number<B> >::infinity().backend();
|
|
1940
|
+
result.negate();
|
|
1941
|
+
errno = ERANGE;
|
|
1942
|
+
return;
|
|
1943
|
+
case FP_INFINITE:
|
|
1944
|
+
result = val;
|
|
1945
|
+
if (eval_signbit(val))
|
|
1946
|
+
result.negate();
|
|
1947
|
+
return;
|
|
1948
|
+
}
|
|
1949
|
+
using max_t = typename std::conditional<std::is_same<std::intmax_t, long>::value, long long, std::intmax_t>::type;
|
|
1950
|
+
result = static_cast<max_t>(eval_ilogb(val));
|
|
1951
|
+
}
|
|
1952
|
+
template <class B, class A>
|
|
1953
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_scalbn(B& result, const B& val, A e)
|
|
1954
|
+
{
|
|
1955
|
+
static_assert(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of scalbn requires a base 2 number type");
|
|
1956
|
+
eval_ldexp(result, val, static_cast<typename B::exponent_type>(e));
|
|
1957
|
+
}
|
|
1958
|
+
template <class B, class A>
|
|
1959
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_scalbln(B& result, const B& val, A e)
|
|
1960
|
+
{
|
|
1961
|
+
eval_scalbn(result, val, e);
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
template <class T>
|
|
1965
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val, std::integral_constant<bool, true> const&, const std::integral_constant<bool, false>&)
|
|
1966
|
+
{
|
|
1967
|
+
return eval_fpclassify(val) == FP_NAN;
|
|
1968
|
+
}
|
|
1969
|
+
template <class T>
|
|
1970
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val, std::integral_constant<bool, false> const&, const std::integral_constant<bool, true>&)
|
|
1971
|
+
{
|
|
1972
|
+
return BOOST_MP_ISNAN(val);
|
|
1973
|
+
}
|
|
1974
|
+
template <class T>
|
|
1975
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T&, std::integral_constant<bool, false> const&, const std::integral_constant<bool, false>&)
|
|
1976
|
+
{
|
|
1977
|
+
return false;
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
template <class T>
|
|
1981
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val)
|
|
1982
|
+
{
|
|
1983
|
+
return is_arg_nan(val, std::integral_constant<bool, boost::multiprecision::detail::is_backend<T>::value>(), std::is_floating_point<T>());
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
template <class T, class U, class V>
|
|
1987
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_fmax(T& result, const U& a, const V& b)
|
|
1988
|
+
{
|
|
1989
|
+
if (is_arg_nan(a))
|
|
1990
|
+
result = number<T>::canonical_value(b);
|
|
1991
|
+
else if (is_arg_nan(b))
|
|
1992
|
+
result = number<T>::canonical_value(a);
|
|
1993
|
+
else if (eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
|
|
1994
|
+
result = number<T>::canonical_value(b);
|
|
1995
|
+
else
|
|
1996
|
+
result = number<T>::canonical_value(a);
|
|
1997
|
+
}
|
|
1998
|
+
template <class T, class U, class V>
|
|
1999
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_fmin(T& result, const U& a, const V& b)
|
|
2000
|
+
{
|
|
2001
|
+
if (is_arg_nan(a))
|
|
2002
|
+
result = number<T>::canonical_value(b);
|
|
2003
|
+
else if (is_arg_nan(b))
|
|
2004
|
+
result = number<T>::canonical_value(a);
|
|
2005
|
+
else if (eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
|
|
2006
|
+
result = number<T>::canonical_value(a);
|
|
2007
|
+
else
|
|
2008
|
+
result = number<T>::canonical_value(b);
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
template <class R, class T, class U>
|
|
2012
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_hypot(R& result, const T& a, const U& b)
|
|
2013
|
+
{
|
|
2014
|
+
//
|
|
2015
|
+
// Normalize x and y, so that both are positive and x >= y:
|
|
2016
|
+
//
|
|
2017
|
+
R x, y;
|
|
2018
|
+
x = number<R>::canonical_value(a);
|
|
2019
|
+
y = number<R>::canonical_value(b);
|
|
2020
|
+
if (eval_get_sign(x) < 0)
|
|
2021
|
+
x.negate();
|
|
2022
|
+
if (eval_get_sign(y) < 0)
|
|
2023
|
+
y.negate();
|
|
2024
|
+
|
|
2025
|
+
// Special case, see C99 Annex F.
|
|
2026
|
+
// The order of the if's is important: do not change!
|
|
2027
|
+
int c1 = eval_fpclassify(x);
|
|
2028
|
+
int c2 = eval_fpclassify(y);
|
|
2029
|
+
|
|
2030
|
+
if (c1 == FP_ZERO)
|
|
2031
|
+
{
|
|
2032
|
+
result = y;
|
|
2033
|
+
return;
|
|
2034
|
+
}
|
|
2035
|
+
if (c2 == FP_ZERO)
|
|
2036
|
+
{
|
|
2037
|
+
result = x;
|
|
2038
|
+
return;
|
|
2039
|
+
}
|
|
2040
|
+
if (c1 == FP_INFINITE)
|
|
2041
|
+
{
|
|
2042
|
+
result = x;
|
|
2043
|
+
return;
|
|
2044
|
+
}
|
|
2045
|
+
if ((c2 == FP_INFINITE) || (c2 == FP_NAN))
|
|
2046
|
+
{
|
|
2047
|
+
result = y;
|
|
2048
|
+
return;
|
|
2049
|
+
}
|
|
2050
|
+
if (c1 == FP_NAN)
|
|
2051
|
+
{
|
|
2052
|
+
result = x;
|
|
2053
|
+
return;
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2056
|
+
if (eval_gt(y, x))
|
|
2057
|
+
x.swap(y);
|
|
2058
|
+
|
|
2059
|
+
eval_multiply(result, x, std::numeric_limits<number<R> >::epsilon().backend());
|
|
2060
|
+
|
|
2061
|
+
if (eval_gt(result, y))
|
|
2062
|
+
{
|
|
2063
|
+
result = x;
|
|
2064
|
+
return;
|
|
2065
|
+
}
|
|
2066
|
+
|
|
2067
|
+
R rat;
|
|
2068
|
+
eval_divide(rat, y, x);
|
|
2069
|
+
eval_multiply(result, rat, rat);
|
|
2070
|
+
eval_increment(result);
|
|
2071
|
+
eval_sqrt(rat, result);
|
|
2072
|
+
eval_multiply(result, rat, x);
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
template <class R, class T>
|
|
2076
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_nearbyint(R& result, const T& a)
|
|
2077
|
+
{
|
|
2078
|
+
eval_round(result, a);
|
|
2079
|
+
}
|
|
2080
|
+
template <class R, class T>
|
|
2081
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_rint(R& result, const T& a)
|
|
2082
|
+
{
|
|
2083
|
+
eval_nearbyint(result, a);
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
template <class T>
|
|
2087
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_backend<T>::value, int>::type eval_signbit(const T& val)
|
|
2088
|
+
{
|
|
2089
|
+
return eval_get_sign(val) < 0 ? 1 : 0;
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
//
|
|
2093
|
+
// Real and imaginary parts:
|
|
2094
|
+
//
|
|
2095
|
+
template <class To, class From>
|
|
2096
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_real(To& to, const From& from)
|
|
2097
|
+
{
|
|
2098
|
+
to = from;
|
|
2099
|
+
}
|
|
2100
|
+
template <class To, class From>
|
|
2101
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_imag(To& to, const From&)
|
|
2102
|
+
{
|
|
2103
|
+
using ui_type = typename std::tuple_element<0, typename To::unsigned_types>::type;
|
|
2104
|
+
to = ui_type(0);
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
} // namespace default_ops
|
|
2108
|
+
namespace default_ops_adl {
|
|
2109
|
+
|
|
2110
|
+
template <class To, class From>
|
|
2111
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real_imp(To& to, const From& from)
|
|
2112
|
+
{
|
|
2113
|
+
using to_component_type = typename component_type<number<To> >::type;
|
|
2114
|
+
typename to_component_type::backend_type to_component;
|
|
2115
|
+
to_component = from;
|
|
2116
|
+
eval_set_real(to, to_component);
|
|
2117
|
+
}
|
|
2118
|
+
template <class To, class From>
|
|
2119
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag_imp(To& to, const From& from)
|
|
2120
|
+
{
|
|
2121
|
+
using to_component_type = typename component_type<number<To> >::type;
|
|
2122
|
+
typename to_component_type::backend_type to_component;
|
|
2123
|
+
to_component = from;
|
|
2124
|
+
eval_set_imag(to, to_component);
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
} // namespace default_ops_adl
|
|
2128
|
+
namespace default_ops {
|
|
2129
|
+
|
|
2130
|
+
template <class To, class From>
|
|
2131
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<To>::value == number_kind_complex>::type eval_set_real(To& to, const From& from)
|
|
2132
|
+
{
|
|
2133
|
+
default_ops_adl::eval_set_real_imp(to, from);
|
|
2134
|
+
}
|
|
2135
|
+
template <class To, class From>
|
|
2136
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<To>::value != number_kind_complex>::type eval_set_real(To& to, const From& from)
|
|
2137
|
+
{
|
|
2138
|
+
to = from;
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
template <class To, class From>
|
|
2142
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(To& to, const From& from)
|
|
2143
|
+
{
|
|
2144
|
+
default_ops_adl::eval_set_imag_imp(to, from);
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
template <class T>
|
|
2148
|
+
inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(T& to, const T& from)
|
|
2149
|
+
{
|
|
2150
|
+
to = from;
|
|
2151
|
+
}
|
|
2152
|
+
template <class T>
|
|
2153
|
+
void BOOST_MP_CXX14_CONSTEXPR eval_set_imag(T&, const T&)
|
|
2154
|
+
{
|
|
2155
|
+
static_assert(sizeof(T) == INT_MAX, "eval_set_imag needs to be specialised for each specific backend");
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
//
|
|
2159
|
+
// These functions are implemented in separate files, but expanded inline here,
|
|
2160
|
+
// DO NOT CHANGE THE ORDER OF THESE INCLUDES:
|
|
2161
|
+
//
|
|
2162
|
+
#include <boost/multiprecision/detail/functions/constants.hpp>
|
|
2163
|
+
#include <boost/multiprecision/detail/functions/pow.hpp>
|
|
2164
|
+
#include <boost/multiprecision/detail/functions/trig.hpp>
|
|
2165
|
+
|
|
2166
|
+
} // namespace default_ops
|
|
2167
|
+
|
|
2168
|
+
//
|
|
2169
|
+
// Default versions of floating point classification routines:
|
|
2170
|
+
//
|
|
2171
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2172
|
+
inline BOOST_MP_CXX14_CONSTEXPR int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2173
|
+
{
|
|
2174
|
+
using multiprecision::default_ops::eval_fpclassify;
|
|
2175
|
+
return eval_fpclassify(arg.backend());
|
|
2176
|
+
}
|
|
2177
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2178
|
+
inline BOOST_MP_CXX14_CONSTEXPR int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2179
|
+
{
|
|
2180
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2181
|
+
return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
|
|
2182
|
+
}
|
|
2183
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2184
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2185
|
+
{
|
|
2186
|
+
int v = fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg);
|
|
2187
|
+
return (v != static_cast<int>(FP_INFINITE)) && (v != static_cast<int>(FP_NAN));
|
|
2188
|
+
}
|
|
2189
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2190
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2191
|
+
{
|
|
2192
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2193
|
+
return isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
|
|
2194
|
+
}
|
|
2195
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2196
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2197
|
+
{
|
|
2198
|
+
return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == static_cast<int>(FP_NAN);
|
|
2199
|
+
}
|
|
2200
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2201
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2202
|
+
{
|
|
2203
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2204
|
+
return isnan BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
|
|
2205
|
+
}
|
|
2206
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2207
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2208
|
+
{
|
|
2209
|
+
return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == static_cast<int>(FP_INFINITE);
|
|
2210
|
+
}
|
|
2211
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2212
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2213
|
+
{
|
|
2214
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2215
|
+
return isinf BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
|
|
2216
|
+
}
|
|
2217
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2218
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2219
|
+
{
|
|
2220
|
+
return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == static_cast<int>(FP_NORMAL);
|
|
2221
|
+
}
|
|
2222
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2223
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2224
|
+
{
|
|
2225
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2226
|
+
return isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
|
|
2227
|
+
}
|
|
2228
|
+
|
|
2229
|
+
// Default versions of sign manipulation functions, if individual backends can do better than this
|
|
2230
|
+
// (for example with signed zero), then they should overload these functions further:
|
|
2231
|
+
|
|
2232
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2233
|
+
inline BOOST_MP_CXX14_CONSTEXPR int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2234
|
+
{
|
|
2235
|
+
return arg.sign();
|
|
2236
|
+
}
|
|
2237
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2238
|
+
inline BOOST_MP_CXX14_CONSTEXPR int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2239
|
+
{
|
|
2240
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2241
|
+
return sign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2245
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2246
|
+
{
|
|
2247
|
+
using default_ops::eval_signbit;
|
|
2248
|
+
return static_cast<bool>(eval_signbit(arg.backend()));
|
|
2249
|
+
}
|
|
2250
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2251
|
+
inline BOOST_MP_CXX14_CONSTEXPR bool signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2252
|
+
{
|
|
2253
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2254
|
+
return static_cast<bool>(signbit BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)));
|
|
2255
|
+
}
|
|
2256
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2257
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2258
|
+
{
|
|
2259
|
+
return -arg;
|
|
2260
|
+
}
|
|
2261
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2262
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2263
|
+
{
|
|
2264
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2265
|
+
return changesign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
|
|
2266
|
+
}
|
|
2267
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2268
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
|
|
2269
|
+
{
|
|
2270
|
+
return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? (boost::multiprecision::changesign)(a) : a;
|
|
2271
|
+
}
|
|
2272
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
|
|
2273
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
|
|
2274
|
+
{
|
|
2275
|
+
return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
|
|
2276
|
+
}
|
|
2277
|
+
template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2278
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
|
|
2279
|
+
{
|
|
2280
|
+
return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
|
|
2281
|
+
}
|
|
2282
|
+
template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
|
|
2283
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
|
|
2284
|
+
{
|
|
2285
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2286
|
+
return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
|
|
2287
|
+
}
|
|
2288
|
+
//
|
|
2289
|
+
// real and imag:
|
|
2290
|
+
//
|
|
2291
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2292
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type
|
|
2293
|
+
real(const multiprecision::number<Backend, ExpressionTemplates>& a)
|
|
2294
|
+
{
|
|
2295
|
+
using default_ops::eval_real;
|
|
2296
|
+
using result_type = typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type;
|
|
2297
|
+
boost::multiprecision::detail::scoped_default_precision<result_type> precision_guard(a);
|
|
2298
|
+
result_type result;
|
|
2299
|
+
eval_real(result.backend(), a.backend());
|
|
2300
|
+
return result;
|
|
2301
|
+
}
|
|
2302
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2303
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type
|
|
2304
|
+
imag(const multiprecision::number<Backend, ExpressionTemplates>& a)
|
|
2305
|
+
{
|
|
2306
|
+
using default_ops::eval_imag;
|
|
2307
|
+
using result_type = typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type;
|
|
2308
|
+
boost::multiprecision::detail::scoped_default_precision<result_type> precision_guard(a);
|
|
2309
|
+
result_type result;
|
|
2310
|
+
eval_imag(result.backend(), a.backend());
|
|
2311
|
+
return result;
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2315
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
|
2316
|
+
real(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2317
|
+
{
|
|
2318
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2319
|
+
detail::scoped_default_precision<value_type> precision_guard(arg);
|
|
2320
|
+
return real(value_type(arg));
|
|
2321
|
+
}
|
|
2322
|
+
|
|
2323
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2324
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
|
2325
|
+
imag(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2326
|
+
{
|
|
2327
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2328
|
+
detail::scoped_default_precision<value_type> precision_guard(arg);
|
|
2329
|
+
return imag(value_type(arg));
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
//
|
|
2333
|
+
// Complex number functions, these are overloaded at the Backend level, we just provide the
|
|
2334
|
+
// expression template versions here, plus overloads for non-complex types:
|
|
2335
|
+
//
|
|
2336
|
+
#ifdef BOOST_MP_MATH_AVAILABLE
|
|
2337
|
+
template <class T, expression_template_option ExpressionTemplates>
|
|
2338
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_complex, component_type<number<T, ExpressionTemplates>>>::type::type
|
|
2339
|
+
abs(const number<T, ExpressionTemplates>& v)
|
|
2340
|
+
{
|
|
2341
|
+
return std::move(boost::math::hypot(real(v), imag(v)));
|
|
2342
|
+
}
|
|
2343
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2344
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_complex, component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type>>::type::type
|
|
2345
|
+
abs(const detail::expression<tag, A1, A2, A3, A4>& v)
|
|
2346
|
+
{
|
|
2347
|
+
using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2348
|
+
return std::move(abs(static_cast<number_type>(v)));
|
|
2349
|
+
}
|
|
2350
|
+
|
|
2351
|
+
template <class T, expression_template_option ExpressionTemplates>
|
|
2352
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_complex, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
|
|
2353
|
+
arg(const number<T, ExpressionTemplates>& v)
|
|
2354
|
+
{
|
|
2355
|
+
return std::move(atan2(imag(v), real(v)));
|
|
2356
|
+
}
|
|
2357
|
+
template <class T, expression_template_option ExpressionTemplates>
|
|
2358
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
|
|
2359
|
+
arg(const number<T, ExpressionTemplates>&)
|
|
2360
|
+
{
|
|
2361
|
+
return 0;
|
|
2362
|
+
}
|
|
2363
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2364
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_complex || number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename scalar_result_from_possible_complex<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
|
|
2365
|
+
arg(const detail::expression<tag, A1, A2, A3, A4>& v)
|
|
2366
|
+
{
|
|
2367
|
+
using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2368
|
+
return std::move(arg(static_cast<number_type>(v)));
|
|
2369
|
+
}
|
|
2370
|
+
#endif // BOOST_MP_MATH_AVAILABLE
|
|
2371
|
+
|
|
2372
|
+
template <class T, expression_template_option ExpressionTemplates>
|
|
2373
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_complex, component_type<number<T, ExpressionTemplates>>>::type::type
|
|
2374
|
+
norm(const number<T, ExpressionTemplates>& v)
|
|
2375
|
+
{
|
|
2376
|
+
typename component_type<number<T, ExpressionTemplates> >::type a(real(v)), b(imag(v));
|
|
2377
|
+
return std::move(a * a + b * b);
|
|
2378
|
+
}
|
|
2379
|
+
template <class T, expression_template_option ExpressionTemplates>
|
|
2380
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value != number_kind_complex, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
|
|
2381
|
+
norm(const number<T, ExpressionTemplates>& v)
|
|
2382
|
+
{
|
|
2383
|
+
return v * v;
|
|
2384
|
+
}
|
|
2385
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2386
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
|
2387
|
+
norm(const detail::expression<tag, A1, A2, A3, A4>& v)
|
|
2388
|
+
{
|
|
2389
|
+
using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2390
|
+
return std::move(norm(static_cast<number_type>(v)));
|
|
2391
|
+
}
|
|
2392
|
+
|
|
2393
|
+
template <class Backend, expression_template_option ExpressionTemplates>
|
|
2394
|
+
BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type polar(number<Backend, ExpressionTemplates> const& r, number<Backend, ExpressionTemplates> const& theta)
|
|
2395
|
+
{
|
|
2396
|
+
return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
template <class tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
|
|
2400
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, ExpressionTemplates> >::value,
|
|
2401
|
+
typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
|
|
2402
|
+
polar(detail::expression<tag, A1, A2, A3, A4> const& r, number<Backend, ExpressionTemplates> const& theta)
|
|
2403
|
+
{
|
|
2404
|
+
return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
|
|
2405
|
+
}
|
|
2406
|
+
|
|
2407
|
+
template <class Backend, expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
|
|
2408
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, ExpressionTemplates> >::value,
|
|
2409
|
+
typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
|
|
2410
|
+
polar(number<Backend, ExpressionTemplates> const& r, detail::expression<tag, A1, A2, A3, A4> const& theta)
|
|
2411
|
+
{
|
|
2412
|
+
return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
|
|
2416
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, typename detail::expression<tagb, A1b, A2b, A3b, A4b>::result_type>::value,
|
|
2417
|
+
typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
|
|
2418
|
+
polar(detail::expression<tag, A1, A2, A3, A4> const& r, detail::expression<tagb, A1b, A2b, A3b, A4b> const& theta)
|
|
2419
|
+
{
|
|
2420
|
+
using scalar_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2421
|
+
return typename complex_result_from_scalar<scalar_type>::type(scalar_type(r * cos(theta)), scalar_type(r * sin(theta)));
|
|
2422
|
+
}
|
|
2423
|
+
//
|
|
2424
|
+
// We also allow the first argument to polar to be an arithmetic type (probably a literal):
|
|
2425
|
+
//
|
|
2426
|
+
template <class Scalar, class Backend, expression_template_option ExpressionTemplates>
|
|
2427
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<Scalar>::value, typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
|
|
2428
|
+
polar(Scalar const& r, number<Backend, ExpressionTemplates> const& theta)
|
|
2429
|
+
{
|
|
2430
|
+
return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
template <class tag, class A1, class A2, class A3, class A4, class Scalar>
|
|
2434
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<Scalar>::value,
|
|
2435
|
+
typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
|
|
2436
|
+
polar(Scalar const& r, detail::expression<tag, A1, A2, A3, A4> const& theta)
|
|
2437
|
+
{
|
|
2438
|
+
using scalar_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2439
|
+
return typename complex_result_from_scalar<scalar_type>::type(scalar_type(r * cos(theta)), scalar_type(r * sin(theta)));
|
|
2440
|
+
}
|
|
2441
|
+
//
|
|
2442
|
+
// Single argument overloads:
|
|
2443
|
+
//
|
|
2444
|
+
template <class Backend, expression_template_option ExpressionTemplates>
|
|
2445
|
+
BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type polar(number<Backend, ExpressionTemplates> const& r)
|
|
2446
|
+
{
|
|
2447
|
+
return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(r);
|
|
2448
|
+
}
|
|
2449
|
+
|
|
2450
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2451
|
+
BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
|
2452
|
+
polar(detail::expression<tag, A1, A2, A3, A4> const& r)
|
|
2453
|
+
{
|
|
2454
|
+
return typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type(r);
|
|
2455
|
+
}
|
|
2456
|
+
|
|
2457
|
+
} // namespace multiprecision
|
|
2458
|
+
|
|
2459
|
+
namespace math {
|
|
2460
|
+
|
|
2461
|
+
//
|
|
2462
|
+
// Import Math functions here, so they can be found by Boost.Math:
|
|
2463
|
+
//
|
|
2464
|
+
using boost::multiprecision::changesign;
|
|
2465
|
+
using boost::multiprecision::copysign;
|
|
2466
|
+
using boost::multiprecision::fpclassify;
|
|
2467
|
+
using boost::multiprecision::isfinite;
|
|
2468
|
+
using boost::multiprecision::isinf;
|
|
2469
|
+
using boost::multiprecision::isnan;
|
|
2470
|
+
using boost::multiprecision::isnormal;
|
|
2471
|
+
using boost::multiprecision::sign;
|
|
2472
|
+
using boost::multiprecision::signbit;
|
|
2473
|
+
|
|
2474
|
+
#ifndef BOOST_MP_MATH_AVAILABLE
|
|
2475
|
+
namespace policies {
|
|
2476
|
+
|
|
2477
|
+
template <typename... Args>
|
|
2478
|
+
class policy {};
|
|
2479
|
+
|
|
2480
|
+
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
|
2481
|
+
void raise_rounding_error(T1, T2, T3, T4, T5)
|
|
2482
|
+
{
|
|
2483
|
+
BOOST_MP_THROW_EXCEPTION(std::runtime_error("Rounding error"));
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
|
2487
|
+
void raise_overflow_error(T1, T2, T3, T4, T5)
|
|
2488
|
+
{
|
|
2489
|
+
BOOST_MP_THROW_EXCEPTION(std::overflow_error("Overflow error"));
|
|
2490
|
+
}
|
|
2491
|
+
|
|
2492
|
+
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
|
2493
|
+
void raise_evaluation_error(T1, T2, T3, T4, T5)
|
|
2494
|
+
{
|
|
2495
|
+
BOOST_MP_THROW_EXCEPTION(std::runtime_error("Evaluation error"));
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2498
|
+
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
|
2499
|
+
void raise_domain_error(T1, T2, T3, T4, T5)
|
|
2500
|
+
{
|
|
2501
|
+
BOOST_MP_THROW_EXCEPTION(std::domain_error("Domain error"));
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
template <typename T, typename... Args>
|
|
2505
|
+
struct is_policy
|
|
2506
|
+
{
|
|
2507
|
+
static constexpr bool value = false;
|
|
2508
|
+
};
|
|
2509
|
+
|
|
2510
|
+
template <typename... Args>
|
|
2511
|
+
struct is_policy<policy<Args...>>
|
|
2512
|
+
{
|
|
2513
|
+
static constexpr bool value = true;
|
|
2514
|
+
};
|
|
2515
|
+
|
|
2516
|
+
} // namespace policies
|
|
2517
|
+
#endif
|
|
2518
|
+
|
|
2519
|
+
} // namespace math
|
|
2520
|
+
|
|
2521
|
+
namespace multiprecision {
|
|
2522
|
+
#ifdef BOOST_MP_MATH_AVAILABLE
|
|
2523
|
+
using c99_error_policy = ::boost::math::policies::policy<
|
|
2524
|
+
::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>,
|
|
2525
|
+
::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>,
|
|
2526
|
+
::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>,
|
|
2527
|
+
::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>,
|
|
2528
|
+
::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error> >;
|
|
2529
|
+
|
|
2530
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2531
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
|
|
2532
|
+
asinh
|
|
2533
|
+
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2534
|
+
{
|
|
2535
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
|
|
2536
|
+
return boost::math::asinh(arg, c99_error_policy());
|
|
2537
|
+
}
|
|
2538
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2539
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
|
2540
|
+
asinh
|
|
2541
|
+
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2542
|
+
{
|
|
2543
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2544
|
+
detail::scoped_default_precision<value_type> precision_guard(arg);
|
|
2545
|
+
return asinh(value_type(arg));
|
|
2546
|
+
}
|
|
2547
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2548
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
|
|
2549
|
+
acosh
|
|
2550
|
+
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2551
|
+
{
|
|
2552
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
|
|
2553
|
+
return boost::math::acosh(arg, c99_error_policy());
|
|
2554
|
+
}
|
|
2555
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2556
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
|
2557
|
+
acosh
|
|
2558
|
+
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2559
|
+
{
|
|
2560
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2561
|
+
detail::scoped_default_precision<value_type> precision_guard(arg);
|
|
2562
|
+
return acosh(value_type(arg));
|
|
2563
|
+
}
|
|
2564
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2565
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
|
|
2566
|
+
atanh
|
|
2567
|
+
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2568
|
+
{
|
|
2569
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
|
|
2570
|
+
return boost::math::atanh(arg, c99_error_policy());
|
|
2571
|
+
}
|
|
2572
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2573
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
|
2574
|
+
atanh
|
|
2575
|
+
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2576
|
+
{
|
|
2577
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2578
|
+
detail::scoped_default_precision<value_type> precision_guard(arg);
|
|
2579
|
+
return atanh(value_type(arg));
|
|
2580
|
+
}
|
|
2581
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2582
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2583
|
+
{
|
|
2584
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
|
|
2585
|
+
return boost::math::cbrt(arg, c99_error_policy());
|
|
2586
|
+
}
|
|
2587
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2588
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2589
|
+
{
|
|
2590
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2591
|
+
detail::scoped_default_precision<value_type> precision_guard(arg);
|
|
2592
|
+
return cbrt(value_type(arg));
|
|
2593
|
+
}
|
|
2594
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2595
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2596
|
+
{
|
|
2597
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
|
|
2598
|
+
return boost::math::erf(arg, c99_error_policy());
|
|
2599
|
+
}
|
|
2600
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2601
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2602
|
+
{
|
|
2603
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2604
|
+
detail::scoped_default_precision<value_type> precision_guard(arg);
|
|
2605
|
+
return erf(value_type(arg));
|
|
2606
|
+
}
|
|
2607
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2608
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2609
|
+
{
|
|
2610
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
|
|
2611
|
+
return boost::math::erfc(arg, c99_error_policy());
|
|
2612
|
+
}
|
|
2613
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2614
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2615
|
+
{
|
|
2616
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2617
|
+
detail::scoped_default_precision<value_type> precision_guard(arg);
|
|
2618
|
+
return erfc(value_type(arg));
|
|
2619
|
+
}
|
|
2620
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2621
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2622
|
+
{
|
|
2623
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
|
|
2624
|
+
return boost::math::expm1(arg, c99_error_policy());
|
|
2625
|
+
}
|
|
2626
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2627
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2628
|
+
{
|
|
2629
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2630
|
+
detail::scoped_default_precision<value_type> precision_guard(arg);
|
|
2631
|
+
return expm1(value_type(arg));
|
|
2632
|
+
}
|
|
2633
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2634
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2635
|
+
{
|
|
2636
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
|
|
2637
|
+
multiprecision::number<Backend, ExpressionTemplates> result;
|
|
2638
|
+
result = boost::math::lgamma(arg, c99_error_policy());
|
|
2639
|
+
if ((boost::multiprecision::isnan)(result) && !(boost::multiprecision::isnan)(arg))
|
|
2640
|
+
{
|
|
2641
|
+
result = std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::infinity();
|
|
2642
|
+
errno = ERANGE;
|
|
2643
|
+
}
|
|
2644
|
+
return result;
|
|
2645
|
+
}
|
|
2646
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2647
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2648
|
+
{
|
|
2649
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2650
|
+
detail::scoped_default_precision<value_type> precision_guard(arg);
|
|
2651
|
+
return lgamma(value_type(arg));
|
|
2652
|
+
}
|
|
2653
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2654
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2655
|
+
{
|
|
2656
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
|
|
2657
|
+
if ((arg == 0) && std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::has_infinity)
|
|
2658
|
+
{
|
|
2659
|
+
errno = ERANGE;
|
|
2660
|
+
return 1 / arg;
|
|
2661
|
+
}
|
|
2662
|
+
return boost::math::tgamma(arg, c99_error_policy());
|
|
2663
|
+
}
|
|
2664
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2665
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2666
|
+
{
|
|
2667
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2668
|
+
detail::scoped_default_precision<value_type> precision_guard(arg);
|
|
2669
|
+
return tgamma(value_type(arg));
|
|
2670
|
+
}
|
|
2671
|
+
|
|
2672
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2673
|
+
inline BOOST_MP_CXX14_CONSTEXPR long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2674
|
+
{
|
|
2675
|
+
return lround(arg);
|
|
2676
|
+
}
|
|
2677
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2678
|
+
inline BOOST_MP_CXX14_CONSTEXPR long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2679
|
+
{
|
|
2680
|
+
return lround(arg);
|
|
2681
|
+
}
|
|
2682
|
+
#ifndef BOOST_NO_LONG_LONG
|
|
2683
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2684
|
+
inline BOOST_MP_CXX14_CONSTEXPR long long llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2685
|
+
{
|
|
2686
|
+
return llround(arg);
|
|
2687
|
+
}
|
|
2688
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2689
|
+
inline BOOST_MP_CXX14_CONSTEXPR long long llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2690
|
+
{
|
|
2691
|
+
return llround(arg);
|
|
2692
|
+
}
|
|
2693
|
+
#endif
|
|
2694
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2695
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
|
2696
|
+
{
|
|
2697
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
|
|
2698
|
+
return boost::math::log1p(arg, c99_error_policy());
|
|
2699
|
+
}
|
|
2700
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2701
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
2702
|
+
{
|
|
2703
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2704
|
+
detail::scoped_default_precision<value_type> precision_guard(arg);
|
|
2705
|
+
return log1p(value_type(arg));
|
|
2706
|
+
}
|
|
2707
|
+
|
|
2708
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2709
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
|
|
2710
|
+
{
|
|
2711
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
|
|
2712
|
+
return boost::math::nextafter(a, b, c99_error_policy());
|
|
2713
|
+
}
|
|
2714
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
|
|
2715
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
|
|
2716
|
+
{
|
|
2717
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
|
|
2718
|
+
return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
|
|
2719
|
+
}
|
|
2720
|
+
template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2721
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
|
|
2722
|
+
{
|
|
2723
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
|
|
2724
|
+
return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
|
|
2725
|
+
}
|
|
2726
|
+
template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
|
|
2727
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
|
|
2728
|
+
{
|
|
2729
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2730
|
+
detail::scoped_default_precision<value_type> precision_guard(a, b);
|
|
2731
|
+
return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
|
|
2732
|
+
}
|
|
2733
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2734
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
|
|
2735
|
+
{
|
|
2736
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
|
|
2737
|
+
return boost::math::nextafter(a, b, c99_error_policy());
|
|
2738
|
+
}
|
|
2739
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
|
|
2740
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
|
|
2741
|
+
{
|
|
2742
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
|
|
2743
|
+
return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
|
|
2744
|
+
}
|
|
2745
|
+
template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2746
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
|
|
2747
|
+
{
|
|
2748
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
|
|
2749
|
+
return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
|
|
2750
|
+
}
|
|
2751
|
+
template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
|
|
2752
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
|
|
2753
|
+
{
|
|
2754
|
+
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2755
|
+
detail::scoped_default_precision<value_type> precision_guard(a, b);
|
|
2756
|
+
return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
|
|
2757
|
+
}
|
|
2758
|
+
#endif // BOOST_MP_MATH_AVAILABLE
|
|
2759
|
+
|
|
2760
|
+
template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
|
|
2761
|
+
inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& add(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
|
|
2762
|
+
{
|
|
2763
|
+
static_assert((std::is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
|
2764
|
+
static_assert((std::is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
|
2765
|
+
using default_ops::eval_add;
|
|
2766
|
+
eval_add(result.backend(), a.backend(), b.backend());
|
|
2767
|
+
return result;
|
|
2768
|
+
}
|
|
2769
|
+
|
|
2770
|
+
template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
|
|
2771
|
+
inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& subtract(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
|
|
2772
|
+
{
|
|
2773
|
+
static_assert((std::is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
|
2774
|
+
static_assert((std::is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
|
2775
|
+
using default_ops::eval_subtract;
|
|
2776
|
+
eval_subtract(result.backend(), a.backend(), b.backend());
|
|
2777
|
+
return result;
|
|
2778
|
+
}
|
|
2779
|
+
|
|
2780
|
+
template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
|
|
2781
|
+
inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& multiply(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
|
|
2782
|
+
{
|
|
2783
|
+
static_assert((std::is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
|
2784
|
+
static_assert((std::is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
|
2785
|
+
using default_ops::eval_multiply;
|
|
2786
|
+
eval_multiply(result.backend(), a.backend(), b.backend());
|
|
2787
|
+
return result;
|
|
2788
|
+
}
|
|
2789
|
+
|
|
2790
|
+
template <class B, expression_template_option ET, class I>
|
|
2791
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value, number<B, ET>&>::type
|
|
2792
|
+
add(number<B, ET>& result, const I& a, const I& b)
|
|
2793
|
+
{
|
|
2794
|
+
using default_ops::eval_add;
|
|
2795
|
+
using canonical_type = typename detail::canonical<I, B>::type;
|
|
2796
|
+
eval_add(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
|
|
2797
|
+
return result;
|
|
2798
|
+
}
|
|
2799
|
+
|
|
2800
|
+
template <class B, expression_template_option ET, class I>
|
|
2801
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value, number<B, ET>&>::type
|
|
2802
|
+
subtract(number<B, ET>& result, const I& a, const I& b)
|
|
2803
|
+
{
|
|
2804
|
+
using default_ops::eval_subtract;
|
|
2805
|
+
using canonical_type = typename detail::canonical<I, B>::type;
|
|
2806
|
+
eval_subtract(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
|
|
2807
|
+
return result;
|
|
2808
|
+
}
|
|
2809
|
+
|
|
2810
|
+
template <class B, expression_template_option ET, class I>
|
|
2811
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value, number<B, ET>&>::type
|
|
2812
|
+
multiply(number<B, ET>& result, const I& a, const I& b)
|
|
2813
|
+
{
|
|
2814
|
+
using default_ops::eval_multiply;
|
|
2815
|
+
using canonical_type = typename detail::canonical<I, B>::type;
|
|
2816
|
+
eval_multiply(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
|
|
2817
|
+
return result;
|
|
2818
|
+
}
|
|
2819
|
+
|
|
2820
|
+
template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
|
2821
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<tag, A1, A2, A3, A4>::result_type trunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
|
2822
|
+
{
|
|
2823
|
+
using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2824
|
+
return std::move(trunc(number_type(v), pol));
|
|
2825
|
+
}
|
|
2826
|
+
|
|
2827
|
+
template <class Backend, expression_template_option ExpressionTemplates, class Policy>
|
|
2828
|
+
inline BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates> trunc(const number<Backend, ExpressionTemplates>& v, const Policy&)
|
|
2829
|
+
{
|
|
2830
|
+
using default_ops::eval_trunc;
|
|
2831
|
+
detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(v);
|
|
2832
|
+
number<Backend, ExpressionTemplates> result;
|
|
2833
|
+
eval_trunc(result.backend(), v.backend());
|
|
2834
|
+
return result;
|
|
2835
|
+
}
|
|
2836
|
+
|
|
2837
|
+
template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
|
2838
|
+
inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
|
2839
|
+
{
|
|
2840
|
+
using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2841
|
+
number_type r(trunc(v, pol));
|
|
2842
|
+
if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_ISFINITE(v))
|
|
2843
|
+
return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", nullptr, number_type(v), 0, pol);
|
|
2844
|
+
return r.template convert_to<int>();
|
|
2845
|
+
}
|
|
2846
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2847
|
+
inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
|
|
2848
|
+
{
|
|
2849
|
+
return itrunc(v, boost::math::policies::policy<>());
|
|
2850
|
+
}
|
|
2851
|
+
template <class Backend, expression_template_option ExpressionTemplates, class Policy>
|
|
2852
|
+
inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const number<Backend, ExpressionTemplates>& v, const Policy& pol)
|
|
2853
|
+
{
|
|
2854
|
+
number<Backend, ExpressionTemplates> r(trunc(v, pol));
|
|
2855
|
+
if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_ISFINITE(v))
|
|
2856
|
+
return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", nullptr, v, 0, pol);
|
|
2857
|
+
return r.template convert_to<int>();
|
|
2858
|
+
}
|
|
2859
|
+
template <class Backend, expression_template_option ExpressionTemplates>
|
|
2860
|
+
inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const number<Backend, ExpressionTemplates>& v)
|
|
2861
|
+
{
|
|
2862
|
+
return itrunc(v, boost::math::policies::policy<>());
|
|
2863
|
+
}
|
|
2864
|
+
template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
|
2865
|
+
inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
|
2866
|
+
{
|
|
2867
|
+
using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2868
|
+
number_type r(trunc(v, pol));
|
|
2869
|
+
if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_ISFINITE(v))
|
|
2870
|
+
return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", nullptr, number_type(v), 0L, pol);
|
|
2871
|
+
return r.template convert_to<long>();
|
|
2872
|
+
}
|
|
2873
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2874
|
+
inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
|
|
2875
|
+
{
|
|
2876
|
+
return ltrunc(v, boost::math::policies::policy<>());
|
|
2877
|
+
}
|
|
2878
|
+
template <class T, expression_template_option ExpressionTemplates, class Policy>
|
|
2879
|
+
inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
|
|
2880
|
+
{
|
|
2881
|
+
number<T, ExpressionTemplates> r(trunc(v, pol));
|
|
2882
|
+
if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_ISFINITE(v))
|
|
2883
|
+
return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", nullptr, v, 0L, pol);
|
|
2884
|
+
return r.template convert_to<long>();
|
|
2885
|
+
}
|
|
2886
|
+
template <class T, expression_template_option ExpressionTemplates>
|
|
2887
|
+
inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const number<T, ExpressionTemplates>& v)
|
|
2888
|
+
{
|
|
2889
|
+
return ltrunc(v, boost::math::policies::policy<>());
|
|
2890
|
+
}
|
|
2891
|
+
#ifndef BOOST_NO_LONG_LONG
|
|
2892
|
+
template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
|
2893
|
+
inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
|
2894
|
+
{
|
|
2895
|
+
using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2896
|
+
number_type r(trunc(v, pol));
|
|
2897
|
+
if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_ISFINITE(v))
|
|
2898
|
+
return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", nullptr, number_type(v), 0LL, pol);
|
|
2899
|
+
return r.template convert_to<long long>();
|
|
2900
|
+
}
|
|
2901
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2902
|
+
inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
|
|
2903
|
+
{
|
|
2904
|
+
return lltrunc(v, boost::math::policies::policy<>());
|
|
2905
|
+
}
|
|
2906
|
+
template <class T, expression_template_option ExpressionTemplates, class Policy>
|
|
2907
|
+
inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
|
|
2908
|
+
{
|
|
2909
|
+
number<T, ExpressionTemplates> r(trunc(v, pol));
|
|
2910
|
+
if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_ISFINITE(v))
|
|
2911
|
+
return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", nullptr, v, 0LL, pol);
|
|
2912
|
+
return r.template convert_to<long long>();
|
|
2913
|
+
}
|
|
2914
|
+
template <class T, expression_template_option ExpressionTemplates>
|
|
2915
|
+
inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const number<T, ExpressionTemplates>& v)
|
|
2916
|
+
{
|
|
2917
|
+
return lltrunc(v, boost::math::policies::policy<>());
|
|
2918
|
+
}
|
|
2919
|
+
#endif
|
|
2920
|
+
template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
|
2921
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<tag, A1, A2, A3, A4>::result_type round(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
|
2922
|
+
{
|
|
2923
|
+
using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2924
|
+
return std::move(round(static_cast<number_type>(v), pol));
|
|
2925
|
+
}
|
|
2926
|
+
template <class T, expression_template_option ExpressionTemplates, class Policy>
|
|
2927
|
+
inline BOOST_MP_CXX14_CONSTEXPR number<T, ExpressionTemplates> round(const number<T, ExpressionTemplates>& v, const Policy&)
|
|
2928
|
+
{
|
|
2929
|
+
using default_ops::eval_round;
|
|
2930
|
+
detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
|
|
2931
|
+
number<T, ExpressionTemplates> result;
|
|
2932
|
+
eval_round(result.backend(), v.backend());
|
|
2933
|
+
return result;
|
|
2934
|
+
}
|
|
2935
|
+
|
|
2936
|
+
template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
|
2937
|
+
inline BOOST_MP_CXX14_CONSTEXPR int iround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
|
2938
|
+
{
|
|
2939
|
+
using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2940
|
+
number_type r(round(v, pol));
|
|
2941
|
+
if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_ISFINITE(v))
|
|
2942
|
+
return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", nullptr, number_type(v), 0, pol);
|
|
2943
|
+
return r.template convert_to<int>();
|
|
2944
|
+
}
|
|
2945
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2946
|
+
inline BOOST_MP_CXX14_CONSTEXPR int iround(const detail::expression<tag, A1, A2, A3, A4>& v)
|
|
2947
|
+
{
|
|
2948
|
+
return iround(v, boost::math::policies::policy<>());
|
|
2949
|
+
}
|
|
2950
|
+
template <class T, expression_template_option ExpressionTemplates, class Policy>
|
|
2951
|
+
inline BOOST_MP_CXX14_CONSTEXPR int iround(const number<T, ExpressionTemplates>& v, const Policy& pol)
|
|
2952
|
+
{
|
|
2953
|
+
number<T, ExpressionTemplates> r(round(v, pol));
|
|
2954
|
+
if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_ISFINITE(v))
|
|
2955
|
+
return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", nullptr, v, 0, pol);
|
|
2956
|
+
return r.template convert_to<int>();
|
|
2957
|
+
}
|
|
2958
|
+
template <class T, expression_template_option ExpressionTemplates>
|
|
2959
|
+
inline BOOST_MP_CXX14_CONSTEXPR int iround(const number<T, ExpressionTemplates>& v)
|
|
2960
|
+
{
|
|
2961
|
+
return iround(v, boost::math::policies::policy<>());
|
|
2962
|
+
}
|
|
2963
|
+
template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
|
2964
|
+
inline BOOST_MP_CXX14_CONSTEXPR long lround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
|
2965
|
+
{
|
|
2966
|
+
using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2967
|
+
number_type r(round(v, pol));
|
|
2968
|
+
if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_ISFINITE(v))
|
|
2969
|
+
return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", nullptr, number_type(v), 0L, pol);
|
|
2970
|
+
return r.template convert_to<long>();
|
|
2971
|
+
}
|
|
2972
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2973
|
+
inline BOOST_MP_CXX14_CONSTEXPR long lround(const detail::expression<tag, A1, A2, A3, A4>& v)
|
|
2974
|
+
{
|
|
2975
|
+
return lround(v, boost::math::policies::policy<>());
|
|
2976
|
+
}
|
|
2977
|
+
template <class T, expression_template_option ExpressionTemplates, class Policy>
|
|
2978
|
+
inline BOOST_MP_CXX14_CONSTEXPR long lround(const number<T, ExpressionTemplates>& v, const Policy& pol)
|
|
2979
|
+
{
|
|
2980
|
+
number<T, ExpressionTemplates> r(round(v, pol));
|
|
2981
|
+
if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_ISFINITE(v))
|
|
2982
|
+
return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", nullptr, v, 0L, pol);
|
|
2983
|
+
return r.template convert_to<long>();
|
|
2984
|
+
}
|
|
2985
|
+
template <class T, expression_template_option ExpressionTemplates>
|
|
2986
|
+
inline BOOST_MP_CXX14_CONSTEXPR long lround(const number<T, ExpressionTemplates>& v)
|
|
2987
|
+
{
|
|
2988
|
+
return lround(v, boost::math::policies::policy<>());
|
|
2989
|
+
}
|
|
2990
|
+
#ifndef BOOST_NO_LONG_LONG
|
|
2991
|
+
template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
|
2992
|
+
inline BOOST_MP_CXX14_CONSTEXPR long long llround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
|
2993
|
+
{
|
|
2994
|
+
using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
2995
|
+
number_type r(round(v, pol));
|
|
2996
|
+
if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_ISFINITE(v))
|
|
2997
|
+
return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", nullptr, number_type(v), 0LL, pol);
|
|
2998
|
+
return r.template convert_to<long long>();
|
|
2999
|
+
}
|
|
3000
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
3001
|
+
inline BOOST_MP_CXX14_CONSTEXPR long long llround(const detail::expression<tag, A1, A2, A3, A4>& v)
|
|
3002
|
+
{
|
|
3003
|
+
return llround(v, boost::math::policies::policy<>());
|
|
3004
|
+
}
|
|
3005
|
+
template <class T, expression_template_option ExpressionTemplates, class Policy>
|
|
3006
|
+
inline BOOST_MP_CXX14_CONSTEXPR long long llround(const number<T, ExpressionTemplates>& v, const Policy& pol)
|
|
3007
|
+
{
|
|
3008
|
+
number<T, ExpressionTemplates> r(round(v, pol));
|
|
3009
|
+
if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_ISFINITE(v))
|
|
3010
|
+
return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", nullptr, v, 0LL, pol);
|
|
3011
|
+
return r.template convert_to<long long>();
|
|
3012
|
+
}
|
|
3013
|
+
template <class T, expression_template_option ExpressionTemplates>
|
|
3014
|
+
inline BOOST_MP_CXX14_CONSTEXPR long long llround(const number<T, ExpressionTemplates>& v)
|
|
3015
|
+
{
|
|
3016
|
+
return llround(v, boost::math::policies::policy<>());
|
|
3017
|
+
}
|
|
3018
|
+
#endif
|
|
3019
|
+
//
|
|
3020
|
+
// frexp does not return an expression template since we require the
|
|
3021
|
+
// integer argument to be evaluated even if the returned value is
|
|
3022
|
+
// not assigned to anything...
|
|
3023
|
+
//
|
|
3024
|
+
template <class T, expression_template_option ExpressionTemplates>
|
|
3025
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, short* pint)
|
|
3026
|
+
{
|
|
3027
|
+
using default_ops::eval_frexp;
|
|
3028
|
+
detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
|
|
3029
|
+
number<T, ExpressionTemplates> result;
|
|
3030
|
+
eval_frexp(result.backend(), v.backend(), pint);
|
|
3031
|
+
return result;
|
|
3032
|
+
}
|
|
3033
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
3034
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
|
3035
|
+
frexp(const detail::expression<tag, A1, A2, A3, A4>& v, short* pint)
|
|
3036
|
+
{
|
|
3037
|
+
using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
3038
|
+
return std::move(frexp(static_cast<number_type>(v), pint));
|
|
3039
|
+
}
|
|
3040
|
+
template <class T, expression_template_option ExpressionTemplates>
|
|
3041
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, int* pint)
|
|
3042
|
+
{
|
|
3043
|
+
using default_ops::eval_frexp;
|
|
3044
|
+
detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
|
|
3045
|
+
number<T, ExpressionTemplates> result;
|
|
3046
|
+
eval_frexp(result.backend(), v.backend(), pint);
|
|
3047
|
+
return result;
|
|
3048
|
+
}
|
|
3049
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
3050
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
|
3051
|
+
frexp(const detail::expression<tag, A1, A2, A3, A4>& v, int* pint)
|
|
3052
|
+
{
|
|
3053
|
+
using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
3054
|
+
return std::move(frexp(static_cast<number_type>(v), pint));
|
|
3055
|
+
}
|
|
3056
|
+
template <class T, expression_template_option ExpressionTemplates>
|
|
3057
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long* pint)
|
|
3058
|
+
{
|
|
3059
|
+
using default_ops::eval_frexp;
|
|
3060
|
+
detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
|
|
3061
|
+
number<T, ExpressionTemplates> result;
|
|
3062
|
+
eval_frexp(result.backend(), v.backend(), pint);
|
|
3063
|
+
return result;
|
|
3064
|
+
}
|
|
3065
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
3066
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
|
3067
|
+
frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long* pint)
|
|
3068
|
+
{
|
|
3069
|
+
using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
3070
|
+
return std::move(frexp(static_cast<number_type>(v), pint));
|
|
3071
|
+
}
|
|
3072
|
+
template <class T, expression_template_option ExpressionTemplates>
|
|
3073
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long long* pint)
|
|
3074
|
+
{
|
|
3075
|
+
using default_ops::eval_frexp;
|
|
3076
|
+
detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
|
|
3077
|
+
number<T, ExpressionTemplates> result;
|
|
3078
|
+
eval_frexp(result.backend(), v.backend(), pint);
|
|
3079
|
+
return result;
|
|
3080
|
+
}
|
|
3081
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
3082
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
|
3083
|
+
frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long long* pint)
|
|
3084
|
+
{
|
|
3085
|
+
using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
3086
|
+
return std::move(frexp(static_cast<number_type>(v), pint));
|
|
3087
|
+
}
|
|
3088
|
+
//
|
|
3089
|
+
// modf does not return an expression template since we require the
|
|
3090
|
+
// second argument to be evaluated even if the returned value is
|
|
3091
|
+
// not assigned to anything...
|
|
3092
|
+
//
|
|
3093
|
+
template <class T, expression_template_option ExpressionTemplates>
|
|
3094
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type modf(const number<T, ExpressionTemplates>& v, number<T, ExpressionTemplates>* pipart)
|
|
3095
|
+
{
|
|
3096
|
+
using default_ops::eval_modf;
|
|
3097
|
+
detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
|
|
3098
|
+
number<T, ExpressionTemplates> result;
|
|
3099
|
+
eval_modf(result.backend(), v.backend(), pipart ? &pipart->backend() : nullptr);
|
|
3100
|
+
return result;
|
|
3101
|
+
}
|
|
3102
|
+
template <class T, expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
|
|
3103
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type modf(const detail::expression<tag, A1, A2, A3, A4>& v, number<T, ExpressionTemplates>* pipart)
|
|
3104
|
+
{
|
|
3105
|
+
using default_ops::eval_modf;
|
|
3106
|
+
detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
|
|
3107
|
+
number<T, ExpressionTemplates> result, arg(v);
|
|
3108
|
+
eval_modf(result.backend(), arg.backend(), pipart ? &pipart->backend() : nullptr);
|
|
3109
|
+
return result;
|
|
3110
|
+
}
|
|
3111
|
+
|
|
3112
|
+
//
|
|
3113
|
+
// Integer square root:
|
|
3114
|
+
//
|
|
3115
|
+
template <class B, expression_template_option ExpressionTemplates>
|
|
3116
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
|
|
3117
|
+
sqrt(const number<B, ExpressionTemplates>& x)
|
|
3118
|
+
{
|
|
3119
|
+
using default_ops::eval_integer_sqrt;
|
|
3120
|
+
number<B, ExpressionTemplates> s, r;
|
|
3121
|
+
eval_integer_sqrt(s.backend(), r.backend(), x.backend());
|
|
3122
|
+
return s;
|
|
3123
|
+
}
|
|
3124
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
3125
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_integer, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
|
3126
|
+
sqrt(const detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
3127
|
+
{
|
|
3128
|
+
using default_ops::eval_integer_sqrt;
|
|
3129
|
+
using result_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
|
|
3130
|
+
detail::scoped_default_precision<result_type> precision_guard(arg);
|
|
3131
|
+
result_type result, v(arg), r;
|
|
3132
|
+
eval_integer_sqrt(result.backend(), r.backend(), v.backend());
|
|
3133
|
+
return result;
|
|
3134
|
+
}
|
|
3135
|
+
|
|
3136
|
+
//
|
|
3137
|
+
// fma:
|
|
3138
|
+
//
|
|
3139
|
+
|
|
3140
|
+
namespace default_ops {
|
|
3141
|
+
|
|
3142
|
+
struct fma_func
|
|
3143
|
+
{
|
|
3144
|
+
template <class B, class T, class U, class V>
|
|
3145
|
+
BOOST_MP_CXX14_CONSTEXPR void operator()(B& result, const T& a, const U& b, const V& c) const
|
|
3146
|
+
{
|
|
3147
|
+
eval_multiply_add(result, a, b, c);
|
|
3148
|
+
}
|
|
3149
|
+
};
|
|
3150
|
+
|
|
3151
|
+
} // namespace default_ops
|
|
3152
|
+
|
|
3153
|
+
template <class Backend, class U, class V>
|
|
3154
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
3155
|
+
(number_category<number<Backend, et_on> >::value == number_kind_floating_point) &&
|
|
3156
|
+
(is_number<U>::value || is_number_expression<U>::value || boost::multiprecision::detail::is_arithmetic<U>::value) &&
|
|
3157
|
+
(is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
|
|
3158
|
+
detail::expression<detail::function, default_ops::fma_func, number<Backend, et_on>, U, V> >::type
|
|
3159
|
+
fma(const number<Backend, et_on>& a, const U& b, const V& c)
|
|
3160
|
+
{
|
|
3161
|
+
return detail::expression<detail::function, default_ops::fma_func, number<Backend, et_on>, U, V>(
|
|
3162
|
+
default_ops::fma_func(), a, b, c);
|
|
3163
|
+
}
|
|
3164
|
+
|
|
3165
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class U, class V>
|
|
3166
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
3167
|
+
(number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) &&
|
|
3168
|
+
(is_number<U>::value || is_number_expression<U>::value || boost::multiprecision::detail::is_arithmetic<U>::value) &&
|
|
3169
|
+
(is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
|
|
3170
|
+
detail::expression<detail::function, default_ops::fma_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, V> >::type
|
|
3171
|
+
fma(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const U& b, const V& c)
|
|
3172
|
+
{
|
|
3173
|
+
return detail::expression<detail::function, default_ops::fma_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, V>(
|
|
3174
|
+
default_ops::fma_func(), a, b, c);
|
|
3175
|
+
}
|
|
3176
|
+
|
|
3177
|
+
template <class Backend, class U, class V>
|
|
3178
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
3179
|
+
(number_category<number<Backend, et_off> >::value == number_kind_floating_point) &&
|
|
3180
|
+
(is_number<U>::value || is_number_expression<U>::value || boost::multiprecision::detail::is_arithmetic<U>::value) &&
|
|
3181
|
+
(is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
|
|
3182
|
+
number<Backend, et_off> >::type
|
|
3183
|
+
fma(const number<Backend, et_off>& a, const U& b, const V& c)
|
|
3184
|
+
{
|
|
3185
|
+
using default_ops::eval_multiply_add;
|
|
3186
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
|
|
3187
|
+
number<Backend, et_off> result;
|
|
3188
|
+
eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
|
|
3189
|
+
return result;
|
|
3190
|
+
}
|
|
3191
|
+
|
|
3192
|
+
template <class U, class Backend, class V>
|
|
3193
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
3194
|
+
(number_category<number<Backend, et_on> >::value == number_kind_floating_point) &&
|
|
3195
|
+
boost::multiprecision::detail::is_arithmetic<U>::value &&
|
|
3196
|
+
(is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
|
|
3197
|
+
detail::expression<detail::function, default_ops::fma_func, U, number<Backend, et_on>, V> >::type
|
|
3198
|
+
fma(const U& a, const number<Backend, et_on>& b, const V& c)
|
|
3199
|
+
{
|
|
3200
|
+
return detail::expression<detail::function, default_ops::fma_func, U, number<Backend, et_on>, V>(
|
|
3201
|
+
default_ops::fma_func(), a, b, c);
|
|
3202
|
+
}
|
|
3203
|
+
|
|
3204
|
+
template <class U, class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
|
|
3205
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
3206
|
+
(number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) &&
|
|
3207
|
+
boost::multiprecision::detail::is_arithmetic<U>::value &&
|
|
3208
|
+
(is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
|
|
3209
|
+
detail::expression<detail::function, default_ops::fma_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
|
|
3210
|
+
fma(const U& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b, const V& c)
|
|
3211
|
+
{
|
|
3212
|
+
return detail::expression<detail::function, default_ops::fma_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(
|
|
3213
|
+
default_ops::fma_func(), a, b, c);
|
|
3214
|
+
}
|
|
3215
|
+
|
|
3216
|
+
template <class U, class Backend, class V>
|
|
3217
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
3218
|
+
(number_category<number<Backend, et_off> >::value == number_kind_floating_point) &&
|
|
3219
|
+
boost::multiprecision::detail::is_arithmetic<U>::value &&
|
|
3220
|
+
(is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
|
|
3221
|
+
number<Backend, et_off> >::type
|
|
3222
|
+
fma(const U& a, const number<Backend, et_off>& b, const V& c)
|
|
3223
|
+
{
|
|
3224
|
+
using default_ops::eval_multiply_add;
|
|
3225
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
|
|
3226
|
+
number<Backend, et_off> result;
|
|
3227
|
+
eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
|
|
3228
|
+
return result;
|
|
3229
|
+
}
|
|
3230
|
+
|
|
3231
|
+
template <class U, class V, class Backend>
|
|
3232
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
3233
|
+
(number_category<number<Backend, et_on> >::value == number_kind_floating_point) &&
|
|
3234
|
+
boost::multiprecision::detail::is_arithmetic<U>::value &&
|
|
3235
|
+
boost::multiprecision::detail::is_arithmetic<V>::value,
|
|
3236
|
+
detail::expression<detail::function, default_ops::fma_func, U, V, number<Backend, et_on> > >::type
|
|
3237
|
+
fma(const U& a, const V& b, const number<Backend, et_on>& c)
|
|
3238
|
+
{
|
|
3239
|
+
return detail::expression<detail::function, default_ops::fma_func, U, V, number<Backend, et_on> >(
|
|
3240
|
+
default_ops::fma_func(), a, b, c);
|
|
3241
|
+
}
|
|
3242
|
+
|
|
3243
|
+
template <class U, class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
3244
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
3245
|
+
(number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) &&
|
|
3246
|
+
boost::multiprecision::detail::is_arithmetic<U>::value &&
|
|
3247
|
+
boost::multiprecision::detail::is_arithmetic<V>::value,
|
|
3248
|
+
detail::expression<detail::function, default_ops::fma_func, U, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
|
|
3249
|
+
fma(const U& a, const V& b, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& c)
|
|
3250
|
+
{
|
|
3251
|
+
return detail::expression<detail::function, default_ops::fma_func, U, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(
|
|
3252
|
+
default_ops::fma_func(), a, b, c);
|
|
3253
|
+
}
|
|
3254
|
+
|
|
3255
|
+
template <class U, class V, class Backend>
|
|
3256
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
3257
|
+
(number_category<number<Backend, et_off> >::value == number_kind_floating_point) &&
|
|
3258
|
+
boost::multiprecision::detail::is_arithmetic<U>::value &&
|
|
3259
|
+
boost::multiprecision::detail::is_arithmetic<V>::value,
|
|
3260
|
+
number<Backend, et_off> >::type
|
|
3261
|
+
fma(const U& a, const V& b, const number<Backend, et_off>& c)
|
|
3262
|
+
{
|
|
3263
|
+
using default_ops::eval_multiply_add;
|
|
3264
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
|
|
3265
|
+
number<Backend, et_off> result;
|
|
3266
|
+
eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
|
|
3267
|
+
return result;
|
|
3268
|
+
}
|
|
3269
|
+
|
|
3270
|
+
namespace default_ops {
|
|
3271
|
+
|
|
3272
|
+
struct remquo_func
|
|
3273
|
+
{
|
|
3274
|
+
template <class B, class T, class U>
|
|
3275
|
+
BOOST_MP_CXX14_CONSTEXPR void operator()(B& result, const T& a, const U& b, int* pi) const
|
|
3276
|
+
{
|
|
3277
|
+
eval_remquo(result, a, b, pi);
|
|
3278
|
+
}
|
|
3279
|
+
};
|
|
3280
|
+
|
|
3281
|
+
} // namespace default_ops
|
|
3282
|
+
|
|
3283
|
+
template <class Backend, class U>
|
|
3284
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
3285
|
+
number_category<number<Backend, et_on> >::value == number_kind_floating_point,
|
|
3286
|
+
detail::expression<detail::function, default_ops::remquo_func, number<Backend, et_on>, U, int*> >::type
|
|
3287
|
+
remquo(const number<Backend, et_on>& a, const U& b, int* pi)
|
|
3288
|
+
{
|
|
3289
|
+
return detail::expression<detail::function, default_ops::remquo_func, number<Backend, et_on>, U, int*>(
|
|
3290
|
+
default_ops::remquo_func(), a, b, pi);
|
|
3291
|
+
}
|
|
3292
|
+
|
|
3293
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class U>
|
|
3294
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
3295
|
+
number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point,
|
|
3296
|
+
detail::expression<detail::function, default_ops::remquo_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, int*> >::type
|
|
3297
|
+
remquo(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const U& b, int* pi)
|
|
3298
|
+
{
|
|
3299
|
+
return detail::expression<detail::function, default_ops::remquo_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, int*>(
|
|
3300
|
+
default_ops::remquo_func(), a, b, pi);
|
|
3301
|
+
}
|
|
3302
|
+
|
|
3303
|
+
template <class U, class Backend>
|
|
3304
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
3305
|
+
(number_category<number<Backend, et_on> >::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
|
|
3306
|
+
detail::expression<detail::function, default_ops::remquo_func, U, number<Backend, et_on>, int*> >::type
|
|
3307
|
+
remquo(const U& a, const number<Backend, et_on>& b, int* pi)
|
|
3308
|
+
{
|
|
3309
|
+
return detail::expression<detail::function, default_ops::remquo_func, U, number<Backend, et_on>, int*>(
|
|
3310
|
+
default_ops::remquo_func(), a, b, pi);
|
|
3311
|
+
}
|
|
3312
|
+
|
|
3313
|
+
template <class U, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
3314
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
3315
|
+
(number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
|
|
3316
|
+
detail::expression<detail::function, default_ops::remquo_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, int*> >::type
|
|
3317
|
+
remquo(const U& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b, int* pi)
|
|
3318
|
+
{
|
|
3319
|
+
return detail::expression<detail::function, default_ops::remquo_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, int*>(
|
|
3320
|
+
default_ops::remquo_func(), a, b, pi);
|
|
3321
|
+
}
|
|
3322
|
+
|
|
3323
|
+
template <class Backend, class U>
|
|
3324
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
3325
|
+
number_category<number<Backend, et_on> >::value == number_kind_floating_point,
|
|
3326
|
+
number<Backend, et_off> >::type
|
|
3327
|
+
remquo(const number<Backend, et_off>& a, const U& b, int* pi)
|
|
3328
|
+
{
|
|
3329
|
+
using default_ops::eval_remquo;
|
|
3330
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b);
|
|
3331
|
+
number<Backend, et_off> result;
|
|
3332
|
+
eval_remquo(result.backend(), a.backend(), number<Backend, et_off>::canonical_value(b), pi);
|
|
3333
|
+
return result;
|
|
3334
|
+
}
|
|
3335
|
+
template <class U, class Backend>
|
|
3336
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
3337
|
+
(number_category<number<Backend, et_on> >::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
|
|
3338
|
+
number<Backend, et_off> >::type
|
|
3339
|
+
remquo(const U& a, const number<Backend, et_off>& b, int* pi)
|
|
3340
|
+
{
|
|
3341
|
+
using default_ops::eval_remquo;
|
|
3342
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b);
|
|
3343
|
+
number<Backend, et_off> result;
|
|
3344
|
+
eval_remquo(result.backend(), number<Backend, et_off>::canonical_value(a), b.backend(), pi);
|
|
3345
|
+
return result;
|
|
3346
|
+
}
|
|
3347
|
+
|
|
3348
|
+
template <class B, expression_template_option ExpressionTemplates>
|
|
3349
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
|
|
3350
|
+
sqrt(const number<B, ExpressionTemplates>& x, number<B, ExpressionTemplates>& r)
|
|
3351
|
+
{
|
|
3352
|
+
using default_ops::eval_integer_sqrt;
|
|
3353
|
+
detail::scoped_default_precision<multiprecision::number<B, ExpressionTemplates> > precision_guard(x, r);
|
|
3354
|
+
number<B, ExpressionTemplates> s;
|
|
3355
|
+
eval_integer_sqrt(s.backend(), r.backend(), x.backend());
|
|
3356
|
+
return s;
|
|
3357
|
+
}
|
|
3358
|
+
template <class B, expression_template_option ExpressionTemplates, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
3359
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
|
|
3360
|
+
sqrt(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& arg, number<B, ExpressionTemplates>& r)
|
|
3361
|
+
{
|
|
3362
|
+
using default_ops::eval_integer_sqrt;
|
|
3363
|
+
detail::scoped_default_precision<multiprecision::number<B, ExpressionTemplates> > precision_guard(r);
|
|
3364
|
+
number<B, ExpressionTemplates> s;
|
|
3365
|
+
number<B, ExpressionTemplates> x(arg);
|
|
3366
|
+
eval_integer_sqrt(s.backend(), r.backend(), x.backend());
|
|
3367
|
+
return s;
|
|
3368
|
+
}
|
|
3369
|
+
|
|
3370
|
+
// clang-format off
|
|
3371
|
+
//
|
|
3372
|
+
// Regrettably, when the argument to a function is an rvalue we must return by value, and not return an
|
|
3373
|
+
// expression template, otherwise we can end up with dangling references.
|
|
3374
|
+
// See https://github.com/boostorg/multiprecision/issues/175.
|
|
3375
|
+
//
|
|
3376
|
+
#define UNARY_OP_FUNCTOR_CXX11_RVALUE(func, category)\
|
|
3377
|
+
template <class Backend> \
|
|
3378
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> > ::type \
|
|
3379
|
+
func(number<Backend, et_on>&& arg) \
|
|
3380
|
+
{ \
|
|
3381
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg); \
|
|
3382
|
+
number<Backend, et_on> result; \
|
|
3383
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3384
|
+
BOOST_JOIN(eval_, func)(result.backend(), arg.backend()); \
|
|
3385
|
+
return result; \
|
|
3386
|
+
} \
|
|
3387
|
+
|
|
3388
|
+
#define BINARY_OP_FUNCTOR_CXX11_RVALUE(func, category)\
|
|
3389
|
+
template <class Backend> \
|
|
3390
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> >::type func(number<Backend, et_on>&& arg, const number<Backend, et_on>& a) \
|
|
3391
|
+
{ \
|
|
3392
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg, a); \
|
|
3393
|
+
number<Backend, et_on> result; \
|
|
3394
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3395
|
+
BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
|
|
3396
|
+
return result; \
|
|
3397
|
+
} \
|
|
3398
|
+
template <class Backend> \
|
|
3399
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> >::type func(const number<Backend, et_on>& arg, number<Backend, et_on>&& a) \
|
|
3400
|
+
{ \
|
|
3401
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg, a); \
|
|
3402
|
+
number<Backend, et_on> result; \
|
|
3403
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3404
|
+
BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
|
|
3405
|
+
return result; \
|
|
3406
|
+
} \
|
|
3407
|
+
template <class Backend> \
|
|
3408
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> >::type func(number<Backend, et_on>&& arg, number<Backend, et_on>&& a) \
|
|
3409
|
+
{ \
|
|
3410
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg, a); \
|
|
3411
|
+
number<Backend, et_on> result; \
|
|
3412
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3413
|
+
BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
|
|
3414
|
+
return result; \
|
|
3415
|
+
} \
|
|
3416
|
+
template <class Backend, class tag, class A1, class A2, class A3, class A4> \
|
|
3417
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
|
|
3418
|
+
number<Backend, et_on> > ::type \
|
|
3419
|
+
func(number<Backend, et_on>&& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
|
|
3420
|
+
{ \
|
|
3421
|
+
return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
|
|
3422
|
+
number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
|
|
3423
|
+
} \
|
|
3424
|
+
template <class tag, class A1, class A2, class A3, class A4, class Backend> \
|
|
3425
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
|
|
3426
|
+
number<Backend, et_on> > ::type \
|
|
3427
|
+
func(const detail::expression<tag, A1, A2, A3, A4>& arg, number<Backend, et_on>&& a) \
|
|
3428
|
+
{ \
|
|
3429
|
+
return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
|
|
3430
|
+
detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
|
|
3431
|
+
} \
|
|
3432
|
+
template <class Backend, class Arithmetic> \
|
|
3433
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
|
|
3434
|
+
is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
|
|
3435
|
+
number<Backend, et_on> >::type \
|
|
3436
|
+
func(number<Backend, et_on>&& arg, const Arithmetic& a) \
|
|
3437
|
+
{ \
|
|
3438
|
+
return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, \
|
|
3439
|
+
number<Backend, et_on>, Arithmetic > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
|
|
3440
|
+
} \
|
|
3441
|
+
template <class Backend, class Arithmetic> \
|
|
3442
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
|
|
3443
|
+
is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
|
|
3444
|
+
number<Backend, et_on> > ::type \
|
|
3445
|
+
func(const Arithmetic& arg, number<Backend, et_on>&& a) \
|
|
3446
|
+
{ \
|
|
3447
|
+
return detail::expression< \
|
|
3448
|
+
detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
|
|
3449
|
+
Arithmetic, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
|
|
3450
|
+
} \
|
|
3451
|
+
|
|
3452
|
+
|
|
3453
|
+
#define UNARY_OP_FUNCTOR(func, category) \
|
|
3454
|
+
namespace detail { \
|
|
3455
|
+
template <class Backend> \
|
|
3456
|
+
struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
|
|
3457
|
+
{ \
|
|
3458
|
+
BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const \
|
|
3459
|
+
{ \
|
|
3460
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3461
|
+
BOOST_JOIN(eval_, func) \
|
|
3462
|
+
(result, arg); \
|
|
3463
|
+
} \
|
|
3464
|
+
template <class U> \
|
|
3465
|
+
BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg) const \
|
|
3466
|
+
{ \
|
|
3467
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3468
|
+
Backend temp; \
|
|
3469
|
+
BOOST_JOIN(eval_, func) \
|
|
3470
|
+
(temp, arg); \
|
|
3471
|
+
result = std::move(temp); \
|
|
3472
|
+
} \
|
|
3473
|
+
}; \
|
|
3474
|
+
} \
|
|
3475
|
+
\
|
|
3476
|
+
template <class tag, class A1, class A2, class A3, class A4> \
|
|
3477
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category, \
|
|
3478
|
+
detail::expression<detail::function, \
|
|
3479
|
+
detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
|
|
3480
|
+
detail::expression<tag, A1, A2, A3, A4> > > ::type \
|
|
3481
|
+
func(const detail::expression<tag, A1, A2, A3, A4>& arg) \
|
|
3482
|
+
{ \
|
|
3483
|
+
return detail::expression< \
|
|
3484
|
+
detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
|
|
3485
|
+
detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg); \
|
|
3486
|
+
} \
|
|
3487
|
+
template <class Backend> \
|
|
3488
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, \
|
|
3489
|
+
detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, number<Backend, et_on> > > ::type \
|
|
3490
|
+
func(const number<Backend, et_on>& arg) \
|
|
3491
|
+
{ \
|
|
3492
|
+
return detail::expression< \
|
|
3493
|
+
detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
|
|
3494
|
+
number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg); \
|
|
3495
|
+
} \
|
|
3496
|
+
template <class Backend> \
|
|
3497
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
|
|
3498
|
+
boost::multiprecision::number_category<Backend>::value == category, \
|
|
3499
|
+
number<Backend, et_off> >::type \
|
|
3500
|
+
func(const number<Backend, et_off>& arg) \
|
|
3501
|
+
{ \
|
|
3502
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
|
|
3503
|
+
number<Backend, et_off> result; \
|
|
3504
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3505
|
+
BOOST_JOIN(eval_, func)(result.backend(), arg.backend()); \
|
|
3506
|
+
return result; \
|
|
3507
|
+
}\
|
|
3508
|
+
UNARY_OP_FUNCTOR_CXX11_RVALUE(func, category)\
|
|
3509
|
+
|
|
3510
|
+
#define BINARY_OP_FUNCTOR(func, category) \
|
|
3511
|
+
namespace detail { \
|
|
3512
|
+
template <class Backend> \
|
|
3513
|
+
struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
|
|
3514
|
+
{ \
|
|
3515
|
+
BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg, const Backend& a) const \
|
|
3516
|
+
{ \
|
|
3517
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3518
|
+
BOOST_JOIN(eval_, func) \
|
|
3519
|
+
(result, arg, a); \
|
|
3520
|
+
} \
|
|
3521
|
+
template <class Arithmetic> \
|
|
3522
|
+
BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg, const Arithmetic& a) const \
|
|
3523
|
+
{ \
|
|
3524
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3525
|
+
BOOST_JOIN(eval_, func) \
|
|
3526
|
+
(result, arg, number<Backend>::canonical_value(a)); \
|
|
3527
|
+
} \
|
|
3528
|
+
template <class Arithmetic> \
|
|
3529
|
+
BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Arithmetic& arg, const Backend& a) const \
|
|
3530
|
+
{ \
|
|
3531
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3532
|
+
BOOST_JOIN(eval_, func) \
|
|
3533
|
+
(result, number<Backend>::canonical_value(arg), a); \
|
|
3534
|
+
} \
|
|
3535
|
+
template <class U> \
|
|
3536
|
+
BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg, const Backend& a) const \
|
|
3537
|
+
{ \
|
|
3538
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3539
|
+
Backend r; \
|
|
3540
|
+
BOOST_JOIN(eval_, func) \
|
|
3541
|
+
(r, arg, a); \
|
|
3542
|
+
result = std::move(r); \
|
|
3543
|
+
} \
|
|
3544
|
+
template <class U, class Arithmetic> \
|
|
3545
|
+
BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg, const Arithmetic& a) const \
|
|
3546
|
+
{ \
|
|
3547
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3548
|
+
Backend r; \
|
|
3549
|
+
BOOST_JOIN(eval_, func) \
|
|
3550
|
+
(r, arg, number<Backend>::canonical_value(a)); \
|
|
3551
|
+
result = std::move(r); \
|
|
3552
|
+
} \
|
|
3553
|
+
template <class U, class Arithmetic> \
|
|
3554
|
+
BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Arithmetic& arg, const Backend& a) const \
|
|
3555
|
+
{ \
|
|
3556
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3557
|
+
Backend r; \
|
|
3558
|
+
BOOST_JOIN(eval_, func) \
|
|
3559
|
+
(r, number<Backend>::canonical_value(arg), a); \
|
|
3560
|
+
result = std::move(r); \
|
|
3561
|
+
} \
|
|
3562
|
+
}; \
|
|
3563
|
+
} \
|
|
3564
|
+
template <class Backend> \
|
|
3565
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, detail::expression<detail::function, \
|
|
3566
|
+
detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, number<Backend, et_on>, number<Backend, et_on> > > ::type \
|
|
3567
|
+
func(const number<Backend, et_on>& arg, const number<Backend, et_on>& a) \
|
|
3568
|
+
{ \
|
|
3569
|
+
return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
|
|
3570
|
+
number<Backend, et_on>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
|
|
3571
|
+
} \
|
|
3572
|
+
template <class Backend, class tag, class A1, class A2, class A3, class A4> \
|
|
3573
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
|
|
3574
|
+
detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > > ::type \
|
|
3575
|
+
func(const number<Backend, et_on>& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
|
|
3576
|
+
{ \
|
|
3577
|
+
return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
|
|
3578
|
+
number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
|
|
3579
|
+
} \
|
|
3580
|
+
template <class tag, class A1, class A2, class A3, class A4, class Backend> \
|
|
3581
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
|
|
3582
|
+
detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > > ::type \
|
|
3583
|
+
func(const detail::expression<tag, A1, A2, A3, A4>& arg, const number<Backend, et_on>& a) \
|
|
3584
|
+
{ \
|
|
3585
|
+
return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
|
|
3586
|
+
detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
|
|
3587
|
+
} \
|
|
3588
|
+
template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b> \
|
|
3589
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category) && (number_category<detail::expression<tagb, A1b, A2b, A3b, A4b> >::value == category), \
|
|
3590
|
+
detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
|
|
3591
|
+
detail::expression<tag, A1, A2, A3, A4>, detail::expression<tagb, A1b, A2b, A3b, A4b> > > ::type \
|
|
3592
|
+
func(const detail::expression<tag, A1, A2, A3, A4>& arg, const detail::expression<tagb, A1b, A2b, A3b, A4b>& a) \
|
|
3593
|
+
{ \
|
|
3594
|
+
return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
|
|
3595
|
+
detail::expression<tag, A1, A2, A3, A4>, detail::expression<tagb, A1b, A2b, A3b, A4b> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg, a); \
|
|
3596
|
+
} \
|
|
3597
|
+
template <class Backend, class Arithmetic> \
|
|
3598
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
|
|
3599
|
+
is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
|
|
3600
|
+
detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
|
|
3601
|
+
number<Backend, et_on>, Arithmetic> > ::type \
|
|
3602
|
+
func(const number<Backend, et_on>& arg, const Arithmetic& a) \
|
|
3603
|
+
{ \
|
|
3604
|
+
return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, \
|
|
3605
|
+
number<Backend, et_on>, Arithmetic > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
|
|
3606
|
+
} \
|
|
3607
|
+
template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
|
|
3608
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
|
|
3609
|
+
is_compatible_arithmetic_type<Arithmetic, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category), \
|
|
3610
|
+
detail::expression< \
|
|
3611
|
+
detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
|
|
3612
|
+
detail::expression<tag, A1, A2, A3, A4>, Arithmetic> > ::type \
|
|
3613
|
+
func(const detail::expression<tag, A1, A2, A3, A4>& arg, const Arithmetic& a) \
|
|
3614
|
+
{ \
|
|
3615
|
+
return detail::expression< \
|
|
3616
|
+
detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
|
|
3617
|
+
detail::expression<tag, A1, A2, A3, A4>, Arithmetic > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg, a); \
|
|
3618
|
+
} \
|
|
3619
|
+
template <class Backend, class Arithmetic> \
|
|
3620
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
|
|
3621
|
+
is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
|
|
3622
|
+
detail::expression< \
|
|
3623
|
+
detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
|
|
3624
|
+
Arithmetic, number<Backend, et_on> > > ::type \
|
|
3625
|
+
func(const Arithmetic& arg, const number<Backend, et_on>& a) \
|
|
3626
|
+
{ \
|
|
3627
|
+
return detail::expression< \
|
|
3628
|
+
detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
|
|
3629
|
+
Arithmetic, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
|
|
3630
|
+
} \
|
|
3631
|
+
template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
|
|
3632
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
|
|
3633
|
+
is_compatible_arithmetic_type<Arithmetic, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category), \
|
|
3634
|
+
detail::expression< \
|
|
3635
|
+
detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
|
|
3636
|
+
Arithmetic, detail::expression<tag, A1, A2, A3, A4> > > ::type \
|
|
3637
|
+
func(const Arithmetic& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
|
|
3638
|
+
{ \
|
|
3639
|
+
return detail::expression< \
|
|
3640
|
+
detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
|
|
3641
|
+
Arithmetic, detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg, a); \
|
|
3642
|
+
} \
|
|
3643
|
+
template <class Backend> \
|
|
3644
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category), number<Backend, et_off> >::type \
|
|
3645
|
+
func(const number<Backend, et_off>& arg, const number<Backend, et_off>& a) \
|
|
3646
|
+
{ \
|
|
3647
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg, a); \
|
|
3648
|
+
number<Backend, et_off> result; \
|
|
3649
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3650
|
+
BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
|
|
3651
|
+
return result; \
|
|
3652
|
+
} \
|
|
3653
|
+
template <class Backend, class Arithmetic> \
|
|
3654
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
|
|
3655
|
+
is_compatible_arithmetic_type<Arithmetic, number<Backend, et_off> >::value && (number_category<Backend>::value == category), \
|
|
3656
|
+
number<Backend, et_off> >::type \
|
|
3657
|
+
func(const number<Backend, et_off>& arg, const Arithmetic& a) \
|
|
3658
|
+
{ \
|
|
3659
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
|
|
3660
|
+
number<Backend, et_off> result; \
|
|
3661
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3662
|
+
BOOST_JOIN(eval_, func) \
|
|
3663
|
+
(result.backend(), arg.backend(), number<Backend, et_off>::canonical_value(a)); \
|
|
3664
|
+
return result; \
|
|
3665
|
+
} \
|
|
3666
|
+
template <class Backend, class Arithmetic> \
|
|
3667
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
|
|
3668
|
+
is_compatible_arithmetic_type<Arithmetic, number<Backend, et_off> >::value && (number_category<Backend>::value == category), \
|
|
3669
|
+
number<Backend, et_off> >::type \
|
|
3670
|
+
func(const Arithmetic& a, const number<Backend, et_off>& arg) \
|
|
3671
|
+
{ \
|
|
3672
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
|
|
3673
|
+
number<Backend, et_off> result; \
|
|
3674
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3675
|
+
BOOST_JOIN(eval_, func) \
|
|
3676
|
+
(result.backend(), number<Backend, et_off>::canonical_value(a), arg.backend()); \
|
|
3677
|
+
return result; \
|
|
3678
|
+
}\
|
|
3679
|
+
BINARY_OP_FUNCTOR_CXX11_RVALUE(func, category)
|
|
3680
|
+
|
|
3681
|
+
#define HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category) \
|
|
3682
|
+
template <class tag, class A1, class A2, class A3, class A4> \
|
|
3683
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
|
|
3684
|
+
(number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category), \
|
|
3685
|
+
detail::expression< \
|
|
3686
|
+
detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
|
|
3687
|
+
detail::expression<tag, A1, A2, A3, A4>, Arg2> > ::type \
|
|
3688
|
+
func(const detail::expression<tag, A1, A2, A3, A4>& arg, Arg2 const& a) \
|
|
3689
|
+
{ \
|
|
3690
|
+
return detail::expression< \
|
|
3691
|
+
detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
|
|
3692
|
+
detail::expression<tag, A1, A2, A3, A4>, Arg2 > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg, a); \
|
|
3693
|
+
} \
|
|
3694
|
+
template <class Backend> \
|
|
3695
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
|
|
3696
|
+
(number_category<Backend>::value == category), \
|
|
3697
|
+
detail::expression< \
|
|
3698
|
+
detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
|
|
3699
|
+
number<Backend, et_on>, Arg2> > ::type \
|
|
3700
|
+
func(const number<Backend, et_on>& arg, Arg2 const& a) \
|
|
3701
|
+
{ \
|
|
3702
|
+
return detail::expression< \
|
|
3703
|
+
detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
|
|
3704
|
+
number<Backend, et_on>, Arg2 > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
|
|
3705
|
+
} \
|
|
3706
|
+
template <class Backend> \
|
|
3707
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
|
|
3708
|
+
(number_category<Backend>::value == category), \
|
|
3709
|
+
number<Backend, et_off> >::type \
|
|
3710
|
+
func(const number<Backend, et_off>& arg, Arg2 const& a) \
|
|
3711
|
+
{ \
|
|
3712
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg, a); \
|
|
3713
|
+
number<Backend, et_off> result; \
|
|
3714
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3715
|
+
BOOST_JOIN(eval_, func) \
|
|
3716
|
+
(result.backend(), arg.backend(), a); \
|
|
3717
|
+
return result; \
|
|
3718
|
+
}
|
|
3719
|
+
|
|
3720
|
+
#define HETERO_BINARY_OP_FUNCTOR(func, Arg2, category) \
|
|
3721
|
+
namespace detail { \
|
|
3722
|
+
template <class Backend> \
|
|
3723
|
+
struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
|
|
3724
|
+
{ \
|
|
3725
|
+
template <class Arg> \
|
|
3726
|
+
BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, Backend const& arg, Arg a) const \
|
|
3727
|
+
{ \
|
|
3728
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3729
|
+
BOOST_JOIN(eval_, func) \
|
|
3730
|
+
(result, arg, a); \
|
|
3731
|
+
} \
|
|
3732
|
+
template <class U, class Arg> \
|
|
3733
|
+
BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, Backend const& arg, Arg a) const \
|
|
3734
|
+
{ \
|
|
3735
|
+
using default_ops::BOOST_JOIN(eval_, func); \
|
|
3736
|
+
Backend temp; \
|
|
3737
|
+
BOOST_JOIN(eval_, func) \
|
|
3738
|
+
(temp, arg, a); \
|
|
3739
|
+
result = std::move(temp); \
|
|
3740
|
+
} \
|
|
3741
|
+
}; \
|
|
3742
|
+
} \
|
|
3743
|
+
\
|
|
3744
|
+
HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)
|
|
3745
|
+
|
|
3746
|
+
// clang-format on
|
|
3747
|
+
|
|
3748
|
+
namespace detail {
|
|
3749
|
+
template <class Backend>
|
|
3750
|
+
struct abs_funct
|
|
3751
|
+
{
|
|
3752
|
+
BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
|
|
3753
|
+
{
|
|
3754
|
+
using default_ops::eval_abs;
|
|
3755
|
+
eval_abs(result, arg);
|
|
3756
|
+
}
|
|
3757
|
+
};
|
|
3758
|
+
template <class Backend>
|
|
3759
|
+
struct conj_funct
|
|
3760
|
+
{
|
|
3761
|
+
BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
|
|
3762
|
+
{
|
|
3763
|
+
using default_ops::eval_conj;
|
|
3764
|
+
eval_conj(result, arg);
|
|
3765
|
+
}
|
|
3766
|
+
//
|
|
3767
|
+
// To allow for mixed complex/scalar arithmetic where conj is called on the scalar type (as in Eigen)
|
|
3768
|
+
// we provide an overload that will promote the arg to the distination type:
|
|
3769
|
+
//
|
|
3770
|
+
template <class Other>
|
|
3771
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_constructible<Other, Backend>::value>::type operator()(Other& result, const Backend& arg) const
|
|
3772
|
+
{
|
|
3773
|
+
using default_ops::eval_conj;
|
|
3774
|
+
Other t(arg);
|
|
3775
|
+
eval_conj(result, t);
|
|
3776
|
+
}
|
|
3777
|
+
};
|
|
3778
|
+
template <class Backend>
|
|
3779
|
+
struct proj_funct
|
|
3780
|
+
{
|
|
3781
|
+
BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
|
|
3782
|
+
{
|
|
3783
|
+
using default_ops::eval_proj;
|
|
3784
|
+
eval_proj(result, arg);
|
|
3785
|
+
}
|
|
3786
|
+
};
|
|
3787
|
+
|
|
3788
|
+
} // namespace detail
|
|
3789
|
+
|
|
3790
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
3791
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex,
|
|
3792
|
+
detail::expression<
|
|
3793
|
+
detail::function, detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> > >::type
|
|
3794
|
+
abs(const detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
3795
|
+
{
|
|
3796
|
+
return detail::expression<
|
|
3797
|
+
detail::function, detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
|
|
3798
|
+
detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
|
|
3799
|
+
}
|
|
3800
|
+
template <class Backend>
|
|
3801
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex,
|
|
3802
|
+
detail::expression<
|
|
3803
|
+
detail::function, detail::abs_funct<Backend>, number<Backend, et_on> > >::type
|
|
3804
|
+
abs(const number<Backend, et_on>& arg)
|
|
3805
|
+
{
|
|
3806
|
+
return detail::expression<
|
|
3807
|
+
detail::function, detail::abs_funct<Backend>, number<Backend, et_on> >(
|
|
3808
|
+
detail::abs_funct<Backend>(), arg);
|
|
3809
|
+
}
|
|
3810
|
+
template <class Backend>
|
|
3811
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, number<Backend, et_off> >::type
|
|
3812
|
+
abs(const number<Backend, et_off>& arg)
|
|
3813
|
+
{
|
|
3814
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
|
|
3815
|
+
number<Backend, et_off> result;
|
|
3816
|
+
using default_ops::eval_abs;
|
|
3817
|
+
eval_abs(result.backend(), arg.backend());
|
|
3818
|
+
return result;
|
|
3819
|
+
}
|
|
3820
|
+
|
|
3821
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
3822
|
+
inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
|
|
3823
|
+
detail::function, detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >
|
|
3824
|
+
conj(const detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
3825
|
+
{
|
|
3826
|
+
return detail::expression<
|
|
3827
|
+
detail::function, detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
|
|
3828
|
+
detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
|
|
3829
|
+
}
|
|
3830
|
+
template <class Backend>
|
|
3831
|
+
inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
|
|
3832
|
+
detail::function, detail::conj_funct<Backend>, number<Backend, et_on> >
|
|
3833
|
+
conj(const number<Backend, et_on>& arg)
|
|
3834
|
+
{
|
|
3835
|
+
return detail::expression<
|
|
3836
|
+
detail::function, detail::conj_funct<Backend>, number<Backend, et_on> >(
|
|
3837
|
+
detail::conj_funct<Backend>(), arg);
|
|
3838
|
+
}
|
|
3839
|
+
template <class Backend>
|
|
3840
|
+
inline BOOST_MP_CXX14_CONSTEXPR number<Backend, et_off>
|
|
3841
|
+
conj(const number<Backend, et_off>& arg)
|
|
3842
|
+
{
|
|
3843
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
|
|
3844
|
+
number<Backend, et_off> result;
|
|
3845
|
+
using default_ops::eval_conj;
|
|
3846
|
+
eval_conj(result.backend(), arg.backend());
|
|
3847
|
+
return result;
|
|
3848
|
+
}
|
|
3849
|
+
|
|
3850
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
3851
|
+
inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
|
|
3852
|
+
detail::function, detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >
|
|
3853
|
+
proj(const detail::expression<tag, A1, A2, A3, A4>& arg)
|
|
3854
|
+
{
|
|
3855
|
+
return detail::expression<
|
|
3856
|
+
detail::function, detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
|
|
3857
|
+
detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
|
|
3858
|
+
}
|
|
3859
|
+
template <class Backend>
|
|
3860
|
+
inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
|
|
3861
|
+
detail::function, detail::proj_funct<Backend>, number<Backend, et_on> >
|
|
3862
|
+
proj(const number<Backend, et_on>& arg)
|
|
3863
|
+
{
|
|
3864
|
+
return detail::expression<
|
|
3865
|
+
detail::function, detail::proj_funct<Backend>, number<Backend, et_on> >(
|
|
3866
|
+
detail::proj_funct<Backend>(), arg);
|
|
3867
|
+
}
|
|
3868
|
+
template <class Backend>
|
|
3869
|
+
inline BOOST_MP_CXX14_CONSTEXPR number<Backend, et_off>
|
|
3870
|
+
proj(const number<Backend, et_off>& arg)
|
|
3871
|
+
{
|
|
3872
|
+
detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
|
|
3873
|
+
number<Backend, et_off> result;
|
|
3874
|
+
using default_ops::eval_proj;
|
|
3875
|
+
eval_proj(result.backend(), arg.backend());
|
|
3876
|
+
return result;
|
|
3877
|
+
}
|
|
3878
|
+
|
|
3879
|
+
UNARY_OP_FUNCTOR(fabs, number_kind_floating_point)
|
|
3880
|
+
UNARY_OP_FUNCTOR(sqrt, number_kind_floating_point)
|
|
3881
|
+
UNARY_OP_FUNCTOR(floor, number_kind_floating_point)
|
|
3882
|
+
UNARY_OP_FUNCTOR(ceil, number_kind_floating_point)
|
|
3883
|
+
UNARY_OP_FUNCTOR(trunc, number_kind_floating_point)
|
|
3884
|
+
UNARY_OP_FUNCTOR(round, number_kind_floating_point)
|
|
3885
|
+
UNARY_OP_FUNCTOR(exp, number_kind_floating_point)
|
|
3886
|
+
UNARY_OP_FUNCTOR(exp2, number_kind_floating_point)
|
|
3887
|
+
UNARY_OP_FUNCTOR(log, number_kind_floating_point)
|
|
3888
|
+
UNARY_OP_FUNCTOR(log10, number_kind_floating_point)
|
|
3889
|
+
UNARY_OP_FUNCTOR(cos, number_kind_floating_point)
|
|
3890
|
+
UNARY_OP_FUNCTOR(sin, number_kind_floating_point)
|
|
3891
|
+
UNARY_OP_FUNCTOR(tan, number_kind_floating_point)
|
|
3892
|
+
UNARY_OP_FUNCTOR(asin, number_kind_floating_point)
|
|
3893
|
+
UNARY_OP_FUNCTOR(acos, number_kind_floating_point)
|
|
3894
|
+
UNARY_OP_FUNCTOR(atan, number_kind_floating_point)
|
|
3895
|
+
UNARY_OP_FUNCTOR(cosh, number_kind_floating_point)
|
|
3896
|
+
UNARY_OP_FUNCTOR(sinh, number_kind_floating_point)
|
|
3897
|
+
UNARY_OP_FUNCTOR(tanh, number_kind_floating_point)
|
|
3898
|
+
UNARY_OP_FUNCTOR(log2, number_kind_floating_point)
|
|
3899
|
+
UNARY_OP_FUNCTOR(nearbyint, number_kind_floating_point)
|
|
3900
|
+
UNARY_OP_FUNCTOR(rint, number_kind_floating_point)
|
|
3901
|
+
|
|
3902
|
+
HETERO_BINARY_OP_FUNCTOR(ldexp, short, number_kind_floating_point)
|
|
3903
|
+
//HETERO_BINARY_OP_FUNCTOR(frexp, short*, number_kind_floating_point)
|
|
3904
|
+
HETERO_BINARY_OP_FUNCTOR_B(ldexp, int, number_kind_floating_point)
|
|
3905
|
+
//HETERO_BINARY_OP_FUNCTOR_B(frexp, int*, number_kind_floating_point)
|
|
3906
|
+
HETERO_BINARY_OP_FUNCTOR_B(ldexp, long, number_kind_floating_point)
|
|
3907
|
+
//HETERO_BINARY_OP_FUNCTOR_B(frexp, long*, number_kind_floating_point)
|
|
3908
|
+
HETERO_BINARY_OP_FUNCTOR_B(ldexp, long long, number_kind_floating_point)
|
|
3909
|
+
//HETERO_BINARY_OP_FUNCTOR_B(frexp, long long*, number_kind_floating_point)
|
|
3910
|
+
BINARY_OP_FUNCTOR(pow, number_kind_floating_point)
|
|
3911
|
+
BINARY_OP_FUNCTOR(fmod, number_kind_floating_point)
|
|
3912
|
+
BINARY_OP_FUNCTOR(fmax, number_kind_floating_point)
|
|
3913
|
+
BINARY_OP_FUNCTOR(fmin, number_kind_floating_point)
|
|
3914
|
+
BINARY_OP_FUNCTOR(atan2, number_kind_floating_point)
|
|
3915
|
+
BINARY_OP_FUNCTOR(fdim, number_kind_floating_point)
|
|
3916
|
+
BINARY_OP_FUNCTOR(hypot, number_kind_floating_point)
|
|
3917
|
+
BINARY_OP_FUNCTOR(remainder, number_kind_floating_point)
|
|
3918
|
+
|
|
3919
|
+
UNARY_OP_FUNCTOR(logb, number_kind_floating_point)
|
|
3920
|
+
HETERO_BINARY_OP_FUNCTOR(scalbn, short, number_kind_floating_point)
|
|
3921
|
+
HETERO_BINARY_OP_FUNCTOR(scalbln, short, number_kind_floating_point)
|
|
3922
|
+
HETERO_BINARY_OP_FUNCTOR_B(scalbn, int, number_kind_floating_point)
|
|
3923
|
+
HETERO_BINARY_OP_FUNCTOR_B(scalbln, int, number_kind_floating_point)
|
|
3924
|
+
HETERO_BINARY_OP_FUNCTOR_B(scalbn, long, number_kind_floating_point)
|
|
3925
|
+
HETERO_BINARY_OP_FUNCTOR_B(scalbln, long, number_kind_floating_point)
|
|
3926
|
+
HETERO_BINARY_OP_FUNCTOR_B(scalbn, long long, number_kind_floating_point)
|
|
3927
|
+
HETERO_BINARY_OP_FUNCTOR_B(scalbln, long long, number_kind_floating_point)
|
|
3928
|
+
|
|
3929
|
+
//
|
|
3930
|
+
// Complex functions:
|
|
3931
|
+
//
|
|
3932
|
+
UNARY_OP_FUNCTOR(exp, number_kind_complex)
|
|
3933
|
+
UNARY_OP_FUNCTOR(log, number_kind_complex)
|
|
3934
|
+
UNARY_OP_FUNCTOR(log10, number_kind_complex)
|
|
3935
|
+
BINARY_OP_FUNCTOR(pow, number_kind_complex)
|
|
3936
|
+
UNARY_OP_FUNCTOR(sqrt, number_kind_complex)
|
|
3937
|
+
UNARY_OP_FUNCTOR(sin, number_kind_complex)
|
|
3938
|
+
UNARY_OP_FUNCTOR(cos, number_kind_complex)
|
|
3939
|
+
UNARY_OP_FUNCTOR(tan, number_kind_complex)
|
|
3940
|
+
UNARY_OP_FUNCTOR(asin, number_kind_complex)
|
|
3941
|
+
UNARY_OP_FUNCTOR(acos, number_kind_complex)
|
|
3942
|
+
UNARY_OP_FUNCTOR(atan, number_kind_complex)
|
|
3943
|
+
UNARY_OP_FUNCTOR(sinh, number_kind_complex)
|
|
3944
|
+
UNARY_OP_FUNCTOR(cosh, number_kind_complex)
|
|
3945
|
+
UNARY_OP_FUNCTOR(tanh, number_kind_complex)
|
|
3946
|
+
UNARY_OP_FUNCTOR(asinh, number_kind_complex)
|
|
3947
|
+
UNARY_OP_FUNCTOR(acosh, number_kind_complex)
|
|
3948
|
+
UNARY_OP_FUNCTOR(atanh, number_kind_complex)
|
|
3949
|
+
|
|
3950
|
+
//
|
|
3951
|
+
// Integer functions:
|
|
3952
|
+
//
|
|
3953
|
+
BINARY_OP_FUNCTOR(gcd, number_kind_integer)
|
|
3954
|
+
BINARY_OP_FUNCTOR(lcm, number_kind_integer)
|
|
3955
|
+
HETERO_BINARY_OP_FUNCTOR(pow, unsigned, number_kind_integer)
|
|
3956
|
+
|
|
3957
|
+
#undef BINARY_OP_FUNCTOR
|
|
3958
|
+
#undef UNARY_OP_FUNCTOR
|
|
3959
|
+
|
|
3960
|
+
//
|
|
3961
|
+
// ilogb:
|
|
3962
|
+
//
|
|
3963
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
3964
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == number_kind_floating_point, typename Backend::exponent_type>::type
|
|
3965
|
+
ilogb(const multiprecision::number<Backend, ExpressionTemplates>& val)
|
|
3966
|
+
{
|
|
3967
|
+
using default_ops::eval_ilogb;
|
|
3968
|
+
return eval_ilogb(val.backend());
|
|
3969
|
+
}
|
|
3970
|
+
|
|
3971
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
3972
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == number_kind_floating_point, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type::backend_type::exponent_type>::type
|
|
3973
|
+
ilogb(const detail::expression<tag, A1, A2, A3, A4>& val)
|
|
3974
|
+
{
|
|
3975
|
+
using default_ops::eval_ilogb;
|
|
3976
|
+
typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type arg(val);
|
|
3977
|
+
return eval_ilogb(arg.backend());
|
|
3978
|
+
}
|
|
3979
|
+
|
|
3980
|
+
} //namespace multiprecision
|
|
3981
|
+
|
|
3982
|
+
namespace math {
|
|
3983
|
+
|
|
3984
|
+
|
|
3985
|
+
//
|
|
3986
|
+
// Overload of Boost.Math functions that find the wrong overload when used with number:
|
|
3987
|
+
//
|
|
3988
|
+
namespace detail {
|
|
3989
|
+
|
|
3990
|
+
template <class T>
|
|
3991
|
+
T sinc_pi_imp(T);
|
|
3992
|
+
template <class T, class Policy>
|
|
3993
|
+
T sinhc_pi_imp(T, const Policy&);
|
|
3994
|
+
|
|
3995
|
+
} // namespace detail
|
|
3996
|
+
|
|
3997
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
3998
|
+
inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
|
|
3999
|
+
{
|
|
4000
|
+
boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
|
|
4001
|
+
return detail::sinc_pi_imp(x);
|
|
4002
|
+
}
|
|
4003
|
+
|
|
4004
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
|
|
4005
|
+
inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
|
|
4006
|
+
{
|
|
4007
|
+
boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
|
|
4008
|
+
return detail::sinc_pi_imp(x);
|
|
4009
|
+
}
|
|
4010
|
+
|
|
4011
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
4012
|
+
inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
|
|
4013
|
+
{
|
|
4014
|
+
boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
|
|
4015
|
+
return detail::sinhc_pi_imp(x, boost::math::policies::policy<>());
|
|
4016
|
+
}
|
|
4017
|
+
|
|
4018
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
|
|
4019
|
+
inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy& pol)
|
|
4020
|
+
{
|
|
4021
|
+
boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x, pol);
|
|
4022
|
+
return detail::sinhc_pi_imp(x, pol);
|
|
4023
|
+
}
|
|
4024
|
+
|
|
4025
|
+
using boost::multiprecision::gcd;
|
|
4026
|
+
using boost::multiprecision::lcm;
|
|
4027
|
+
|
|
4028
|
+
#ifdef BOOST_MSVC
|
|
4029
|
+
#pragma warning(pop)
|
|
4030
|
+
#endif
|
|
4031
|
+
} // namespace math
|
|
4032
|
+
|
|
4033
|
+
namespace integer {
|
|
4034
|
+
|
|
4035
|
+
using boost::multiprecision::gcd;
|
|
4036
|
+
using boost::multiprecision::lcm;
|
|
4037
|
+
|
|
4038
|
+
} // namespace integer
|
|
4039
|
+
|
|
4040
|
+
} // namespace boost
|
|
4041
|
+
|
|
4042
|
+
//
|
|
4043
|
+
// This has to come last of all:
|
|
4044
|
+
//
|
|
4045
|
+
#include <boost/multiprecision/detail/no_et_ops.hpp>
|
|
4046
|
+
#include <boost/multiprecision/detail/et_ops.hpp>
|
|
4047
|
+
//
|
|
4048
|
+
// min/max overloads:
|
|
4049
|
+
//
|
|
4050
|
+
#include <boost/multiprecision/detail/min_max.hpp>
|
|
4051
|
+
|
|
4052
|
+
#endif
|