mqt-core 3.3.2__cp312-cp312-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.cp312-win_amd64.pyd +0 -0
- mqt/core/dd.pyi +1016 -0
- mqt/core/dd_evaluation.py +368 -0
- mqt/core/fomac.cp312-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.cp312-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.cp312-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,2500 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright 2011 John Maddock. Distributed under the Boost
|
|
3
|
+
// Software License, Version 1.0. (See accompanying file
|
|
4
|
+
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
5
|
+
|
|
6
|
+
#ifndef BOOST_MP_NUMBER_HPP
|
|
7
|
+
#define BOOST_MP_NUMBER_HPP
|
|
8
|
+
|
|
9
|
+
#include <cstdint>
|
|
10
|
+
#include <boost/multiprecision/detail/standalone_config.hpp>
|
|
11
|
+
#include <boost/multiprecision/detail/precision.hpp>
|
|
12
|
+
#include <boost/multiprecision/detail/generic_interconvert.hpp>
|
|
13
|
+
#include <boost/multiprecision/detail/number_compare.hpp>
|
|
14
|
+
#include <boost/multiprecision/traits/is_restricted_conversion.hpp>
|
|
15
|
+
#include <boost/multiprecision/traits/is_complex.hpp>
|
|
16
|
+
#include <boost/multiprecision/traits/is_convertible_arithmetic.hpp>
|
|
17
|
+
#include <boost/multiprecision/detail/hash.hpp>
|
|
18
|
+
#include <boost/multiprecision/detail/number_base.hpp>
|
|
19
|
+
#include <istream> // stream operators
|
|
20
|
+
#include <cstdio> // EOF
|
|
21
|
+
#include <cctype> // isspace
|
|
22
|
+
#include <functional> // std::hash
|
|
23
|
+
#include <type_traits>
|
|
24
|
+
#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
|
|
25
|
+
#include <string_view>
|
|
26
|
+
#endif
|
|
27
|
+
|
|
28
|
+
#ifndef BOOST_MP_STANDALONE
|
|
29
|
+
#include <boost/core/nvp.hpp>
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
namespace boost {
|
|
33
|
+
namespace multiprecision {
|
|
34
|
+
|
|
35
|
+
#ifdef BOOST_MSVC
|
|
36
|
+
// warning C4127: conditional expression is constant
|
|
37
|
+
// warning C4714: function marked as __forceinline not inlined
|
|
38
|
+
#pragma warning(push)
|
|
39
|
+
#pragma warning(disable : 4127 4714 6326)
|
|
40
|
+
#endif
|
|
41
|
+
|
|
42
|
+
template <class Backend, expression_template_option ExpressionTemplates>
|
|
43
|
+
class number
|
|
44
|
+
{
|
|
45
|
+
using self_type = number<Backend, ExpressionTemplates>;
|
|
46
|
+
|
|
47
|
+
public:
|
|
48
|
+
using backend_type = Backend ;
|
|
49
|
+
using value_type = typename component_type<self_type>::type;
|
|
50
|
+
|
|
51
|
+
static constexpr expression_template_option et = ExpressionTemplates;
|
|
52
|
+
|
|
53
|
+
BOOST_MP_FORCEINLINE constexpr number() noexcept(noexcept(Backend())) {}
|
|
54
|
+
BOOST_MP_FORCEINLINE constexpr number(const number& e) noexcept(noexcept(Backend(std::declval<Backend const&>()))) : m_backend(e.m_backend) {}
|
|
55
|
+
template <class V>
|
|
56
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v,
|
|
57
|
+
typename std::enable_if<
|
|
58
|
+
(boost::multiprecision::detail::is_convertible_arithmetic<V, Backend>::value
|
|
59
|
+
|| std::is_same<std::string, V>::value
|
|
60
|
+
|| std::is_convertible<V, const char*>::value)
|
|
61
|
+
&& !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
|
|
62
|
+
&& !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
|
|
63
|
+
{
|
|
64
|
+
m_backend = canonical_value(v);
|
|
65
|
+
}
|
|
66
|
+
template <class V>
|
|
67
|
+
BOOST_MP_FORCEINLINE constexpr number(const V& v, typename std::enable_if<
|
|
68
|
+
std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
|
|
69
|
+
#ifndef BOOST_INTEL
|
|
70
|
+
noexcept(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
|
|
71
|
+
#endif
|
|
72
|
+
: m_backend(canonical_value(v))
|
|
73
|
+
{}
|
|
74
|
+
template <class V, class U>
|
|
75
|
+
BOOST_MP_FORCEINLINE constexpr number(const V& v, U digits10,
|
|
76
|
+
typename std::enable_if<
|
|
77
|
+
(boost::multiprecision::detail::is_convertible_arithmetic<V, Backend>::value
|
|
78
|
+
|| std::is_same<std::string, V>::value
|
|
79
|
+
|| std::is_convertible<V, const char*>::value)
|
|
80
|
+
&& !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
|
|
81
|
+
&& (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_complex)
|
|
82
|
+
&& (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_rational)
|
|
83
|
+
&& std::is_same<self_type, value_type>::value
|
|
84
|
+
&& std::is_integral<U>::value
|
|
85
|
+
&& (std::numeric_limits<U>::digits <= std::numeric_limits<unsigned>::digits)
|
|
86
|
+
&& std::is_constructible<Backend, typename detail::canonical<V, Backend>::type const&, unsigned>::value>::type* = nullptr)
|
|
87
|
+
: m_backend(canonical_value(v), static_cast<unsigned>(digits10))
|
|
88
|
+
{}
|
|
89
|
+
//
|
|
90
|
+
// Conversions from unscoped enum's are implicit:
|
|
91
|
+
//
|
|
92
|
+
template <class V>
|
|
93
|
+
BOOST_MP_FORCEINLINE
|
|
94
|
+
#if !(defined(BOOST_MSVC) && (BOOST_MSVC <= 1900))
|
|
95
|
+
constexpr
|
|
96
|
+
#endif
|
|
97
|
+
number(const V& v, typename std::enable_if<
|
|
98
|
+
std::is_enum<V>::value && std::is_convertible<V, int>::value && !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
|
|
99
|
+
: number(static_cast<typename std::underlying_type<V>::type>(v))
|
|
100
|
+
{}
|
|
101
|
+
//
|
|
102
|
+
// Conversions from scoped enum's are explicit:
|
|
103
|
+
//
|
|
104
|
+
template <class V>
|
|
105
|
+
BOOST_MP_FORCEINLINE explicit
|
|
106
|
+
#if !(defined(BOOST_MSVC) && (BOOST_MSVC <= 1900))
|
|
107
|
+
constexpr
|
|
108
|
+
#endif
|
|
109
|
+
number(const V& v, typename std::enable_if<
|
|
110
|
+
std::is_enum<V>::value && !std::is_convertible<V, int>::value && !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
|
|
111
|
+
: number(static_cast<typename std::underlying_type<V>::type>(v))
|
|
112
|
+
{}
|
|
113
|
+
|
|
114
|
+
template <class U>
|
|
115
|
+
BOOST_MP_FORCEINLINE constexpr number(const number& e, U digits10, typename std::enable_if<std::is_constructible<Backend, const Backend&, unsigned>::value && std::is_integral<U>::value && (std::numeric_limits<U>::digits <= std::numeric_limits<unsigned>::digits)>::type* = nullptr)
|
|
116
|
+
noexcept(noexcept(Backend(std::declval<Backend const&>(), std::declval<unsigned>())))
|
|
117
|
+
: m_backend(e.m_backend, static_cast<unsigned>(digits10)) {}
|
|
118
|
+
template <class V>
|
|
119
|
+
explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v, typename std::enable_if<
|
|
120
|
+
(boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && !detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
|
|
121
|
+
noexcept(noexcept(std::declval<Backend&>() = std::declval<typename detail::canonical<V, Backend>::type const&>()))
|
|
122
|
+
{
|
|
123
|
+
m_backend = canonical_value(v);
|
|
124
|
+
}
|
|
125
|
+
template <class V>
|
|
126
|
+
explicit BOOST_MP_FORCEINLINE constexpr number(const V& v, typename std::enable_if<
|
|
127
|
+
detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && (detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value || !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value)>::type* = nullptr)
|
|
128
|
+
noexcept(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
|
|
129
|
+
: m_backend(canonical_value(v)) {}
|
|
130
|
+
template <class V>
|
|
131
|
+
explicit BOOST_MP_FORCEINLINE constexpr number(const V& v, unsigned digits10, typename std::enable_if<(boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_complex) && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_rational)>::type* = nullptr)
|
|
132
|
+
: m_backend(canonical_value(v), digits10) {}
|
|
133
|
+
|
|
134
|
+
template <expression_template_option ET>
|
|
135
|
+
BOOST_MP_FORCEINLINE constexpr number(const number<Backend, ET>& val)
|
|
136
|
+
noexcept(noexcept(Backend(std::declval<Backend const&>()))) : m_backend(val.backend()) {}
|
|
137
|
+
|
|
138
|
+
template <class Other, expression_template_option ET>
|
|
139
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val,
|
|
140
|
+
typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = nullptr)
|
|
141
|
+
noexcept(noexcept(Backend(std::declval<Other const&>())))
|
|
142
|
+
: m_backend(val.backend()) {}
|
|
143
|
+
|
|
144
|
+
template <class Other, expression_template_option ET>
|
|
145
|
+
explicit BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val, typename std::enable_if<
|
|
146
|
+
(!detail::is_explicitly_convertible<Other, Backend>::value)>::type* = nullptr)
|
|
147
|
+
{
|
|
148
|
+
//
|
|
149
|
+
// Attempt a generic interconvertion:
|
|
150
|
+
//
|
|
151
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard_1(val);
|
|
152
|
+
detail::scoped_default_precision<number<Other, ET> > precision_guard_2(val);
|
|
153
|
+
using detail::generic_interconvert;
|
|
154
|
+
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
|
|
155
|
+
{
|
|
156
|
+
if (precision_guard_1.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
|
|
157
|
+
{
|
|
158
|
+
self_type t;
|
|
159
|
+
generic_interconvert(t.backend(), val.backend(), number_category<Backend>(), number_category<Other>());
|
|
160
|
+
*this = std::move(t);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
generic_interconvert(backend(), val.backend(), number_category<Backend>(), number_category<Other>());
|
|
165
|
+
}
|
|
166
|
+
template <class Other, expression_template_option ET>
|
|
167
|
+
explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val, typename std::enable_if<
|
|
168
|
+
(detail::is_explicitly_convertible<Other, Backend>::value && (detail::is_restricted_conversion<Other, Backend>::value || !std::is_convertible<Other, Backend>::value))>::type* = nullptr) noexcept(noexcept(Backend(std::declval<Other const&>())))
|
|
169
|
+
: m_backend(val.backend()) {}
|
|
170
|
+
|
|
171
|
+
template <class V, class U>
|
|
172
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
|
|
173
|
+
typename std::enable_if<
|
|
174
|
+
(std::is_convertible<V, value_type>::value
|
|
175
|
+
&& std::is_convertible<U, value_type>::value
|
|
176
|
+
&& !std::is_same<value_type, self_type>::value
|
|
177
|
+
&& std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
|
|
178
|
+
&& !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
|
|
179
|
+
: m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)))
|
|
180
|
+
{
|
|
181
|
+
}
|
|
182
|
+
template <class V, class U>
|
|
183
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(V&& v1, const U& v2,
|
|
184
|
+
typename std::enable_if<
|
|
185
|
+
(std::is_convertible<V, value_type>::value
|
|
186
|
+
&& std::is_convertible<U, value_type>::value
|
|
187
|
+
&& !std::is_same<value_type, self_type>::value
|
|
188
|
+
&& std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
|
|
189
|
+
&& !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
|
|
190
|
+
: m_backend(canonical_value(detail::evaluate_if_expression(static_cast<V&&>(v1))), canonical_value(detail::evaluate_if_expression(v2)))
|
|
191
|
+
{
|
|
192
|
+
}
|
|
193
|
+
template <class V, class U>
|
|
194
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, U&& v2,
|
|
195
|
+
typename std::enable_if<
|
|
196
|
+
(std::is_convertible<V, value_type>::value
|
|
197
|
+
&& std::is_convertible<U, value_type>::value
|
|
198
|
+
&& !std::is_same<value_type, self_type>::value
|
|
199
|
+
&& std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
|
|
200
|
+
&& !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
|
|
201
|
+
: m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(static_cast<U&&>(v2))))
|
|
202
|
+
{
|
|
203
|
+
}
|
|
204
|
+
template <class V, class U>
|
|
205
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(V&& v1, U&& v2,
|
|
206
|
+
typename std::enable_if<
|
|
207
|
+
(std::is_convertible<V, value_type>::value
|
|
208
|
+
&& std::is_convertible<U, value_type>::value
|
|
209
|
+
&& !std::is_same<value_type, self_type>::value
|
|
210
|
+
&& std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
|
|
211
|
+
&& !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
|
|
212
|
+
: m_backend(canonical_value(detail::evaluate_if_expression(static_cast<V&&>(v1))), canonical_value(detail::evaluate_if_expression(static_cast<U&&>(v2))))
|
|
213
|
+
{
|
|
214
|
+
}
|
|
215
|
+
template <class V, class U>
|
|
216
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
|
|
217
|
+
typename std::enable_if<
|
|
218
|
+
(std::is_convertible<V, value_type>::value
|
|
219
|
+
&& std::is_convertible<U, value_type>::value
|
|
220
|
+
&& !std::is_same<value_type, self_type>::value
|
|
221
|
+
&& (!std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
|
|
222
|
+
|| boost::multiprecision::detail::is_variable_precision<Backend>::value))>::type* = nullptr)
|
|
223
|
+
{
|
|
224
|
+
using default_ops::assign_components;
|
|
225
|
+
// Copy precision options from this type to component_type:
|
|
226
|
+
boost::multiprecision::detail::scoped_precision_options<value_type> scoped_opts(*this);
|
|
227
|
+
// precision guards:
|
|
228
|
+
detail::scoped_default_precision<self_type> precision_guard(v1, v2, *this);
|
|
229
|
+
detail::scoped_default_precision<value_type> component_precision_guard(v1, v2, *this);
|
|
230
|
+
assign_components(m_backend, canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)));
|
|
231
|
+
}
|
|
232
|
+
template <class V, class U>
|
|
233
|
+
BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
|
|
234
|
+
typename std::enable_if<
|
|
235
|
+
(std::is_constructible<value_type, V>::value || std::is_convertible<V, std::string>::value) && (std::is_constructible<value_type, U>::value || std::is_convertible<U, std::string>::value) && !std::is_same<value_type, self_type>::value && !std::is_same<V, self_type>::value && !(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value)>::type* = nullptr)
|
|
236
|
+
{
|
|
237
|
+
using default_ops::assign_components;
|
|
238
|
+
// Copy precision options from this type to component_type:
|
|
239
|
+
boost::multiprecision::detail::scoped_precision_options<value_type> scoped_opts(*this);
|
|
240
|
+
// precision guards:
|
|
241
|
+
detail::scoped_default_precision<self_type> precision_guard(v1, v2, *this);
|
|
242
|
+
detail::scoped_default_precision<value_type> component_precision_guard(v1, v2, *this);
|
|
243
|
+
assign_components(m_backend, canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)));
|
|
244
|
+
}
|
|
245
|
+
#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
|
|
246
|
+
//
|
|
247
|
+
// Support for new types in C++17
|
|
248
|
+
//
|
|
249
|
+
template <class Traits>
|
|
250
|
+
explicit inline BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view<char, Traits>& view)
|
|
251
|
+
{
|
|
252
|
+
using default_ops::assign_from_string_view;
|
|
253
|
+
assign_from_string_view(this->backend(), view);
|
|
254
|
+
}
|
|
255
|
+
template <class Traits>
|
|
256
|
+
explicit inline BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view<char, Traits>& view_x, const std::basic_string_view<char, Traits>& view_y)
|
|
257
|
+
{
|
|
258
|
+
using default_ops::assign_from_string_view;
|
|
259
|
+
assign_from_string_view(this->backend(), view_x, view_y);
|
|
260
|
+
}
|
|
261
|
+
template <class Traits>
|
|
262
|
+
explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view<char, Traits>& v, unsigned digits10)
|
|
263
|
+
: m_backend(canonical_value(v), digits10) {}
|
|
264
|
+
template <class Traits>
|
|
265
|
+
BOOST_MP_CXX14_CONSTEXPR number& assign(const std::basic_string_view<char, Traits>& view)
|
|
266
|
+
{
|
|
267
|
+
using default_ops::assign_from_string_view;
|
|
268
|
+
assign_from_string_view(this->backend(), view);
|
|
269
|
+
return *this;
|
|
270
|
+
}
|
|
271
|
+
#endif
|
|
272
|
+
|
|
273
|
+
template <class V, class U>
|
|
274
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10,
|
|
275
|
+
typename std::enable_if<(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value && !std::is_same<value_type, self_type>::value)>::type* = nullptr)
|
|
276
|
+
: m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)), digits10)
|
|
277
|
+
{}
|
|
278
|
+
template <class V, class U>
|
|
279
|
+
BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10,
|
|
280
|
+
typename std::enable_if<((std::is_constructible<value_type, V>::value || std::is_convertible<V, std::string>::value) && (std::is_constructible<value_type, U>::value || std::is_convertible<U, std::string>::value) && !std::is_same<value_type, self_type>::value) && !(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value)>::type* = nullptr)
|
|
281
|
+
: m_backend(detail::evaluate_if_expression(v1), detail::evaluate_if_expression(v2), digits10) {}
|
|
282
|
+
|
|
283
|
+
template <class Other, expression_template_option ET>
|
|
284
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(
|
|
285
|
+
const number<Other, ET>& v1,
|
|
286
|
+
const number<Other, ET>& v2,
|
|
287
|
+
typename std::enable_if<
|
|
288
|
+
std::is_convertible<Other, Backend>::value
|
|
289
|
+
&& (!std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const number<Other, ET>&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const number<Other, ET>&>()))>::type>::type, Backend>::type const&>::value || boost::multiprecision::detail::is_variable_precision<Backend>::value) >::type* = nullptr)
|
|
290
|
+
{
|
|
291
|
+
using default_ops::assign_components;
|
|
292
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(v1, v2);
|
|
293
|
+
assign_components(m_backend, v1.backend(), v2.backend());
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
297
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
|
|
298
|
+
{
|
|
299
|
+
using tag_type = std::integral_constant<bool, is_equivalent_number_type<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>;
|
|
300
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(e);
|
|
301
|
+
//
|
|
302
|
+
// If the current precision of *this differs from that of expression e, then we
|
|
303
|
+
// create a temporary (which will have the correct precision thanks to precision_guard)
|
|
304
|
+
// and then move the result into *this. In C++17 we add a leading "if constexpr"
|
|
305
|
+
// which causes this code to be eliminated in the common case that this type is
|
|
306
|
+
// not actually variable precision. Pre C++17 this code should still be mostly
|
|
307
|
+
// optimised away, but we can't prevent instantiation of the dead code leading
|
|
308
|
+
// to longer build and possibly link times.
|
|
309
|
+
//
|
|
310
|
+
BOOST_IF_CONSTEXPR (std::is_same<self_type, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value)
|
|
311
|
+
{
|
|
312
|
+
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
|
|
313
|
+
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
|
|
314
|
+
{
|
|
315
|
+
number t(e);
|
|
316
|
+
return *this = std::move(t);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
do_assign(e, tag_type());
|
|
320
|
+
return *this;
|
|
321
|
+
}
|
|
322
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
323
|
+
BOOST_MP_CXX14_CONSTEXPR number& assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
|
|
324
|
+
{
|
|
325
|
+
using tag_type = std::integral_constant<bool, is_equivalent_number_type<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>;
|
|
326
|
+
|
|
327
|
+
//
|
|
328
|
+
// If the current precision of *this differs from that of expression e, then we
|
|
329
|
+
// create a temporary (which will have the correct precision thanks to precision_guard)
|
|
330
|
+
// and then move the result into *this. In C++17 we add a leading "if constexpr"
|
|
331
|
+
// which causes this code to be eliminated in the common case that this type is
|
|
332
|
+
// not actually variable precision. Pre C++17 this code should still be mostly
|
|
333
|
+
// optimised away, but we can't prevent instantiation of the dead code leading
|
|
334
|
+
// to longer build and possibly link times.
|
|
335
|
+
//
|
|
336
|
+
BOOST_IF_CONSTEXPR(std::is_same<self_type, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value)
|
|
337
|
+
{
|
|
338
|
+
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
|
|
339
|
+
{
|
|
340
|
+
const detail::scoped_default_precision<number<Backend, ExpressionTemplates>> precision_guard(e);
|
|
341
|
+
|
|
342
|
+
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
|
|
343
|
+
{
|
|
344
|
+
number t;
|
|
345
|
+
t.assign(e);
|
|
346
|
+
return *this = std::move(t);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
do_assign(e, tag_type());
|
|
351
|
+
return *this;
|
|
352
|
+
}
|
|
353
|
+
BOOST_MP_CXX14_CONSTEXPR number& assign(const value_type& a, const value_type& b)
|
|
354
|
+
{
|
|
355
|
+
assign_components(backend(), a.backend(), b.backend());
|
|
356
|
+
return *this;
|
|
357
|
+
}
|
|
358
|
+
template <class V, class U>
|
|
359
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(std::is_convertible<V, value_type>::value&& std::is_convertible<U, value_type>::value && !std::is_same<value_type, self_type>::value), number&>::type
|
|
360
|
+
assign(const V& v1, const U& v2, unsigned Digits)
|
|
361
|
+
{
|
|
362
|
+
self_type r(v1, v2, Digits);
|
|
363
|
+
boost::multiprecision::detail::scoped_source_precision<self_type> scope;
|
|
364
|
+
return *this = r;
|
|
365
|
+
}
|
|
366
|
+
BOOST_MP_CXX14_CONSTEXPR number& assign(const value_type & a, const value_type & b, unsigned Digits)
|
|
367
|
+
{
|
|
368
|
+
this->precision(Digits);
|
|
369
|
+
boost::multiprecision::detail::scoped_target_precision<self_type> scoped;
|
|
370
|
+
assign_components(backend(), canonical_value(detail::evaluate_if_expression(a)), canonical_value(detail::evaluate_if_expression(b)));
|
|
371
|
+
return *this;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator=(const number& e)
|
|
375
|
+
noexcept(noexcept(std::declval<Backend&>() = std::declval<Backend const&>()))
|
|
376
|
+
{
|
|
377
|
+
m_backend = e.m_backend;
|
|
378
|
+
return *this;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
template <class V>
|
|
382
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
|
|
383
|
+
operator=(const V& v)
|
|
384
|
+
noexcept(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
|
|
385
|
+
{
|
|
386
|
+
m_backend = canonical_value(v);
|
|
387
|
+
return *this;
|
|
388
|
+
}
|
|
389
|
+
template <class V>
|
|
390
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates>& assign(const V& v)
|
|
391
|
+
noexcept(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
|
|
392
|
+
{
|
|
393
|
+
m_backend = canonical_value(v);
|
|
394
|
+
return *this;
|
|
395
|
+
}
|
|
396
|
+
template <class V, class U>
|
|
397
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates>& assign(const V& v, const U& digits10_or_component)
|
|
398
|
+
noexcept(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
|
|
399
|
+
{
|
|
400
|
+
number t(v, digits10_or_component);
|
|
401
|
+
boost::multiprecision::detail::scoped_source_precision<self_type> scope;
|
|
402
|
+
static_cast<void>(scope);
|
|
403
|
+
return *this = t;
|
|
404
|
+
}
|
|
405
|
+
template <class Other, expression_template_option ET>
|
|
406
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!boost::multiprecision::detail::is_explicitly_convertible<Other, Backend>::value, number<Backend, ExpressionTemplates>&>::type
|
|
407
|
+
assign(const number<Other, ET>& v)
|
|
408
|
+
{
|
|
409
|
+
//
|
|
410
|
+
// Attempt a generic interconvertion:
|
|
411
|
+
//
|
|
412
|
+
using detail::generic_interconvert;
|
|
413
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, v);
|
|
414
|
+
detail::scoped_default_precision<number<Other, ET> > precision_guard2(*this, v);
|
|
415
|
+
//
|
|
416
|
+
// If the current precision of *this differs from that of value v, then we
|
|
417
|
+
// create a temporary (which will have the correct precision thanks to precision_guard)
|
|
418
|
+
// and then move the result into *this. In C++17 we add a leading "if constexpr"
|
|
419
|
+
// which causes this code to be eliminated in the common case that this type is
|
|
420
|
+
// not actually variable precision. Pre C++17 this code should still be mostly
|
|
421
|
+
// optimised away, but we can't prevent instantiation of the dead code leading
|
|
422
|
+
// to longer build and possibly link times.
|
|
423
|
+
//
|
|
424
|
+
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
|
|
425
|
+
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
|
|
426
|
+
{
|
|
427
|
+
number t(v);
|
|
428
|
+
return *this = std::move(t);
|
|
429
|
+
}
|
|
430
|
+
generic_interconvert(backend(), v.backend(), number_category<Backend>(), number_category<Other>());
|
|
431
|
+
return *this;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
435
|
+
BOOST_MP_CXX14_CONSTEXPR number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = nullptr)
|
|
436
|
+
{
|
|
437
|
+
//
|
|
438
|
+
// No preicsion guard here, we already have one in operator=
|
|
439
|
+
//
|
|
440
|
+
*this = e;
|
|
441
|
+
}
|
|
442
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
443
|
+
explicit BOOST_MP_CXX14_CONSTEXPR number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e,
|
|
444
|
+
typename std::enable_if<!std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value && boost::multiprecision::detail::is_explicitly_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = nullptr)
|
|
445
|
+
{
|
|
446
|
+
//
|
|
447
|
+
// No precision guard as assign has one already:
|
|
448
|
+
//
|
|
449
|
+
assign(e);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// rvalues:
|
|
453
|
+
BOOST_MP_FORCEINLINE constexpr number(number&& r)
|
|
454
|
+
noexcept(noexcept(Backend(std::declval<Backend>())))
|
|
455
|
+
: m_backend(static_cast<Backend&&>(r.m_backend))
|
|
456
|
+
{}
|
|
457
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator=(number&& r) noexcept(noexcept(std::declval<Backend&>() = std::declval<Backend>()))
|
|
458
|
+
{
|
|
459
|
+
m_backend = static_cast<Backend&&>(r.m_backend);
|
|
460
|
+
return *this;
|
|
461
|
+
}
|
|
462
|
+
template <class Other, expression_template_option ET>
|
|
463
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(number<Other, ET>&& val,
|
|
464
|
+
typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = nullptr)
|
|
465
|
+
noexcept(noexcept(Backend(std::declval<Other const&>())))
|
|
466
|
+
: m_backend(static_cast<number<Other, ET>&&>(val).backend()) {}
|
|
467
|
+
template <class Other, expression_template_option ET>
|
|
468
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value), number&>::type
|
|
469
|
+
operator=(number<Other, ET>&& val)
|
|
470
|
+
noexcept(noexcept(Backend(std::declval<Other const&>())))
|
|
471
|
+
{
|
|
472
|
+
m_backend = std::move(val).backend();
|
|
473
|
+
return *this;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
BOOST_MP_CXX14_CONSTEXPR number& operator+=(const self_type& val)
|
|
477
|
+
{
|
|
478
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, val);
|
|
479
|
+
//
|
|
480
|
+
// If the current precision of *this differs from that of expression e, then we
|
|
481
|
+
// create a temporary (which will have the correct precision thanks to precision_guard)
|
|
482
|
+
// and then move the result into *this. In C++17 we add a leading "if constexpr"
|
|
483
|
+
// which causes this code to be eliminated in the common case that this type is
|
|
484
|
+
// not actually variable precision. Pre C++17 this code should still be mostly
|
|
485
|
+
// optimised away, but we can't prevent instantiation of the dead code leading
|
|
486
|
+
// to longer build and possibly link times.
|
|
487
|
+
//
|
|
488
|
+
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
|
|
489
|
+
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
|
|
490
|
+
{
|
|
491
|
+
number t(*this + val);
|
|
492
|
+
return *this = std::move(t);
|
|
493
|
+
}
|
|
494
|
+
do_add(detail::expression<detail::terminal, self_type>(val), detail::terminal());
|
|
495
|
+
return *this;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
499
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator+=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
|
|
500
|
+
{
|
|
501
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
|
|
502
|
+
// Create a copy if e contains this, but not if we're just doing a
|
|
503
|
+
// x += x
|
|
504
|
+
if ((contains_self(e) && !is_self(e)))
|
|
505
|
+
{
|
|
506
|
+
self_type temp(e);
|
|
507
|
+
do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
|
|
508
|
+
}
|
|
509
|
+
else
|
|
510
|
+
{
|
|
511
|
+
do_add(e, tag());
|
|
512
|
+
}
|
|
513
|
+
return *this;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
template <class Arg1, class Arg2, class Arg3, class Arg4>
|
|
517
|
+
BOOST_MP_CXX14_CONSTEXPR number& operator+=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
|
|
518
|
+
{
|
|
519
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
|
|
520
|
+
//
|
|
521
|
+
// If the current precision of *this differs from that of expression e, then we
|
|
522
|
+
// create a temporary (which will have the correct precision thanks to precision_guard)
|
|
523
|
+
// and then move the result into *this. In C++17 we add a leading "if constexpr"
|
|
524
|
+
// which causes this code to be eliminated in the common case that this type is
|
|
525
|
+
// not actually variable precision. Pre C++17 this code should still be mostly
|
|
526
|
+
// optimised away, but we can't prevent instantiation of the dead code leading
|
|
527
|
+
// to longer build and possibly link times.
|
|
528
|
+
//
|
|
529
|
+
BOOST_IF_CONSTEXPR(std::is_same<self_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value)
|
|
530
|
+
{
|
|
531
|
+
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
|
|
532
|
+
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
|
|
533
|
+
{
|
|
534
|
+
number t(*this + e);
|
|
535
|
+
return *this = std::move(t);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
//
|
|
539
|
+
// Fused multiply-add:
|
|
540
|
+
//
|
|
541
|
+
using default_ops::eval_multiply_add;
|
|
542
|
+
eval_multiply_add(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));
|
|
543
|
+
return *this;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
template <class V>
|
|
547
|
+
typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
|
|
548
|
+
BOOST_MP_CXX14_CONSTEXPR operator+=(const V& v)
|
|
549
|
+
{
|
|
550
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, v);
|
|
551
|
+
//
|
|
552
|
+
// If the current precision of *this differs from that of value v, then we
|
|
553
|
+
// create a temporary (which will have the correct precision thanks to precision_guard)
|
|
554
|
+
// and then move the result into *this. In C++17 we add a leading "if constexpr"
|
|
555
|
+
// which causes this code to be eliminated in the common case that this type is
|
|
556
|
+
// not actually variable precision. Pre C++17 this code should still be mostly
|
|
557
|
+
// optimised away, but we can't prevent instantiation of the dead code leading
|
|
558
|
+
// to longer build and possibly link times.
|
|
559
|
+
//
|
|
560
|
+
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
|
|
561
|
+
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
|
|
562
|
+
{
|
|
563
|
+
number t(*this + v);
|
|
564
|
+
return *this = std::move(t);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
using default_ops::eval_add;
|
|
568
|
+
eval_add(m_backend, canonical_value(v));
|
|
569
|
+
return *this;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
BOOST_MP_CXX14_CONSTEXPR number& operator-=(const self_type& val)
|
|
573
|
+
{
|
|
574
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, val);
|
|
575
|
+
//
|
|
576
|
+
// If the current precision of *this differs from that of expression e, then we
|
|
577
|
+
// create a temporary (which will have the correct precision thanks to precision_guard)
|
|
578
|
+
// and then move the result into *this. In C++17 we add a leading "if constexpr"
|
|
579
|
+
// which causes this code to be eliminated in the common case that this type is
|
|
580
|
+
// not actually variable precision. Pre C++17 this code should still be mostly
|
|
581
|
+
// optimised away, but we can't prevent instantiation of the dead code leading
|
|
582
|
+
// to longer build and possibly link times.
|
|
583
|
+
//
|
|
584
|
+
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
|
|
585
|
+
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
|
|
586
|
+
{
|
|
587
|
+
number t(*this - val);
|
|
588
|
+
return *this = std::move(t);
|
|
589
|
+
}
|
|
590
|
+
do_subtract(detail::expression<detail::terminal, self_type>(val), detail::terminal());
|
|
591
|
+
return *this;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
595
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator-=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
|
|
596
|
+
{
|
|
597
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
|
|
598
|
+
// Create a copy if e contains this:
|
|
599
|
+
if (contains_self(e))
|
|
600
|
+
{
|
|
601
|
+
self_type temp(e);
|
|
602
|
+
do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
|
|
603
|
+
}
|
|
604
|
+
else
|
|
605
|
+
{
|
|
606
|
+
do_subtract(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
|
|
607
|
+
}
|
|
608
|
+
return *this;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
template <class V>
|
|
612
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
|
|
613
|
+
operator-=(const V& v)
|
|
614
|
+
{
|
|
615
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, v);
|
|
616
|
+
//
|
|
617
|
+
// If the current precision of *this differs from that of value v, then we
|
|
618
|
+
// create a temporary (which will have the correct precision thanks to precision_guard)
|
|
619
|
+
// and then move the result into *this. In C++17 we add a leading "if constexpr"
|
|
620
|
+
// which causes this code to be eliminated in the common case that this type is
|
|
621
|
+
// not actually variable precision. Pre C++17 this code should still be mostly
|
|
622
|
+
// optimised away, but we can't prevent instantiation of the dead code leading
|
|
623
|
+
// to longer build and possibly link times.
|
|
624
|
+
//
|
|
625
|
+
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
|
|
626
|
+
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
|
|
627
|
+
{
|
|
628
|
+
number t(*this - v);
|
|
629
|
+
return *this = std::move(t);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
using default_ops::eval_subtract;
|
|
633
|
+
eval_subtract(m_backend, canonical_value(v));
|
|
634
|
+
return *this;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
template <class Arg1, class Arg2, class Arg3, class Arg4>
|
|
638
|
+
BOOST_MP_CXX14_CONSTEXPR number& operator-=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
|
|
639
|
+
{
|
|
640
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
|
|
641
|
+
//
|
|
642
|
+
// If the current precision of *this differs from that of expression e, then we
|
|
643
|
+
// create a temporary (which will have the correct precision thanks to precision_guard)
|
|
644
|
+
// and then move the result into *this. In C++17 we add a leading "if constexpr"
|
|
645
|
+
// which causes this code to be eliminated in the common case that this type is
|
|
646
|
+
// not actually variable precision. Pre C++17 this code should still be mostly
|
|
647
|
+
// optimised away, but we can't prevent instantiation of the dead code leading
|
|
648
|
+
// to longer build and possibly link times.
|
|
649
|
+
//
|
|
650
|
+
BOOST_IF_CONSTEXPR(std::is_same<self_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value)
|
|
651
|
+
{
|
|
652
|
+
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
|
|
653
|
+
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
|
|
654
|
+
{
|
|
655
|
+
number t(*this - e);
|
|
656
|
+
return *this = std::move(t);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
//
|
|
660
|
+
// Fused multiply-subtract:
|
|
661
|
+
//
|
|
662
|
+
using default_ops::eval_multiply_subtract;
|
|
663
|
+
eval_multiply_subtract(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));
|
|
664
|
+
return *this;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
BOOST_MP_CXX14_CONSTEXPR number& operator*=(const self_type& e)
|
|
668
|
+
{
|
|
669
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
|
|
670
|
+
//
|
|
671
|
+
// If the current precision of *this differs from that of expression e, then we
|
|
672
|
+
// create a temporary (which will have the correct precision thanks to precision_guard)
|
|
673
|
+
// and then move the result into *this. In C++17 we add a leading "if constexpr"
|
|
674
|
+
// which causes this code to be eliminated in the common case that this type is
|
|
675
|
+
// not actually variable precision. Pre C++17 this code should still be mostly
|
|
676
|
+
// optimised away, but we can't prevent instantiation of the dead code leading
|
|
677
|
+
// to longer build and possibly link times.
|
|
678
|
+
//
|
|
679
|
+
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
|
|
680
|
+
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
|
|
681
|
+
{
|
|
682
|
+
number t(*this * e);
|
|
683
|
+
return *this = std::move(t);
|
|
684
|
+
}
|
|
685
|
+
do_multiplies(detail::expression<detail::terminal, self_type>(e), detail::terminal());
|
|
686
|
+
return *this;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
690
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator*=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
|
|
691
|
+
{
|
|
692
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
|
|
693
|
+
// Create a temporary if the RHS references *this, but not
|
|
694
|
+
// if we're just doing an x *= x;
|
|
695
|
+
if ((contains_self(e) && !is_self(e)))
|
|
696
|
+
{
|
|
697
|
+
self_type temp(e);
|
|
698
|
+
do_multiplies(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
|
|
699
|
+
}
|
|
700
|
+
else
|
|
701
|
+
{
|
|
702
|
+
do_multiplies(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
|
|
703
|
+
}
|
|
704
|
+
return *this;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
template <class V>
|
|
708
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
|
|
709
|
+
operator*=(const V& v)
|
|
710
|
+
{
|
|
711
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, v);
|
|
712
|
+
//
|
|
713
|
+
// If the current precision of *this differs from that of value v, then we
|
|
714
|
+
// create a temporary (which will have the correct precision thanks to precision_guard)
|
|
715
|
+
// and then move the result into *this. In C++17 we add a leading "if constexpr"
|
|
716
|
+
// which causes this code to be eliminated in the common case that this type is
|
|
717
|
+
// not actually variable precision. Pre C++17 this code should still be mostly
|
|
718
|
+
// optimised away, but we can't prevent instantiation of the dead code leading
|
|
719
|
+
// to longer build and possibly link times.
|
|
720
|
+
//
|
|
721
|
+
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
|
|
722
|
+
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
|
|
723
|
+
{
|
|
724
|
+
number t(*this * v);
|
|
725
|
+
return *this = std::move(t);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
using default_ops::eval_multiply;
|
|
729
|
+
eval_multiply(m_backend, canonical_value(v));
|
|
730
|
+
return *this;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
BOOST_MP_CXX14_CONSTEXPR number& operator%=(const self_type& e)
|
|
734
|
+
{
|
|
735
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
|
|
736
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
|
|
737
|
+
//
|
|
738
|
+
// If the current precision of *this differs from that of expression e, then we
|
|
739
|
+
// create a temporary (which will have the correct precision thanks to precision_guard)
|
|
740
|
+
// and then move the result into *this. In C++17 we add a leading "if constexpr"
|
|
741
|
+
// which causes this code to be eliminated in the common case that this type is
|
|
742
|
+
// not actually variable precision. Pre C++17 this code should still be mostly
|
|
743
|
+
// optimised away, but we can't prevent instantiation of the dead code leading
|
|
744
|
+
// to longer build and possibly link times.
|
|
745
|
+
//
|
|
746
|
+
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
|
|
747
|
+
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
|
|
748
|
+
{
|
|
749
|
+
number t(*this % e);
|
|
750
|
+
return *this = std::move(t);
|
|
751
|
+
}
|
|
752
|
+
do_modulus(detail::expression<detail::terminal, self_type>(e), detail::terminal());
|
|
753
|
+
return *this;
|
|
754
|
+
}
|
|
755
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
756
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator%=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
|
|
757
|
+
{
|
|
758
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
|
|
759
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
|
|
760
|
+
// Create a temporary if the RHS references *this:
|
|
761
|
+
if (contains_self(e))
|
|
762
|
+
{
|
|
763
|
+
self_type temp(e);
|
|
764
|
+
do_modulus(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
|
|
765
|
+
}
|
|
766
|
+
else
|
|
767
|
+
{
|
|
768
|
+
do_modulus(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
|
|
769
|
+
}
|
|
770
|
+
return *this;
|
|
771
|
+
}
|
|
772
|
+
template <class V>
|
|
773
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
|
|
774
|
+
operator%=(const V& v)
|
|
775
|
+
{
|
|
776
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
|
|
777
|
+
using default_ops::eval_modulus;
|
|
778
|
+
eval_modulus(m_backend, canonical_value(v));
|
|
779
|
+
return *this;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
//
|
|
783
|
+
// These operators are *not* proto-ized.
|
|
784
|
+
// The issue is that the increment/decrement must happen
|
|
785
|
+
// even if the result of the operator *is never used*.
|
|
786
|
+
// Possibly we could modify our expression wrapper to
|
|
787
|
+
// execute the increment/decrement on destruction, but
|
|
788
|
+
// correct implementation will be tricky, so defered for now...
|
|
789
|
+
//
|
|
790
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator++()
|
|
791
|
+
{
|
|
792
|
+
using default_ops::eval_increment;
|
|
793
|
+
eval_increment(m_backend);
|
|
794
|
+
return *this;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator--()
|
|
798
|
+
{
|
|
799
|
+
using default_ops::eval_decrement;
|
|
800
|
+
eval_decrement(m_backend);
|
|
801
|
+
return *this;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
inline BOOST_MP_CXX14_CONSTEXPR number operator++(int)
|
|
805
|
+
{
|
|
806
|
+
using default_ops::eval_increment;
|
|
807
|
+
self_type temp(*this);
|
|
808
|
+
eval_increment(m_backend);
|
|
809
|
+
return temp;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
inline BOOST_MP_CXX14_CONSTEXPR number operator--(int)
|
|
813
|
+
{
|
|
814
|
+
using default_ops::eval_decrement;
|
|
815
|
+
self_type temp(*this);
|
|
816
|
+
eval_decrement(m_backend);
|
|
817
|
+
return temp;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
template <class V>
|
|
821
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<V>::value, number&>::type operator<<=(V val)
|
|
822
|
+
{
|
|
823
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The left-shift operation is only valid for integer types");
|
|
824
|
+
detail::check_shift_range(val, std::integral_constant<bool, (sizeof(V) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<V>::value && boost::multiprecision::detail::is_integral<V>::value > ());
|
|
825
|
+
eval_left_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));
|
|
826
|
+
return *this;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
template <class V>
|
|
830
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<V>::value, number&>::type operator>>=(V val)
|
|
831
|
+
{
|
|
832
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The right-shift operation is only valid for integer types");
|
|
833
|
+
detail::check_shift_range(val, std::integral_constant<bool, (sizeof(V) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<V>::value && boost::multiprecision::detail::is_integral<V>::value>());
|
|
834
|
+
eval_right_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));
|
|
835
|
+
return *this;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator/=(const self_type& e)
|
|
839
|
+
{
|
|
840
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
|
|
841
|
+
//
|
|
842
|
+
// If the current precision of *this differs from that of expression e, then we
|
|
843
|
+
// create a temporary (which will have the correct precision thanks to precision_guard)
|
|
844
|
+
// and then move the result into *this. In C++17 we add a leading "if constexpr"
|
|
845
|
+
// which causes this code to be eliminated in the common case that this type is
|
|
846
|
+
// not actually variable precision. Pre C++17 this code should still be mostly
|
|
847
|
+
// optimised away, but we can't prevent instantiation of the dead code leading
|
|
848
|
+
// to longer build and possibly link times.
|
|
849
|
+
//
|
|
850
|
+
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
|
|
851
|
+
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
|
|
852
|
+
{
|
|
853
|
+
number t(*this / e);
|
|
854
|
+
return *this = std::move(t);
|
|
855
|
+
}
|
|
856
|
+
do_divide(detail::expression<detail::terminal, self_type>(e), detail::terminal());
|
|
857
|
+
return *this;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
861
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator/=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
|
|
862
|
+
{
|
|
863
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
|
|
864
|
+
// Create a temporary if the RHS references *this:
|
|
865
|
+
if (contains_self(e))
|
|
866
|
+
{
|
|
867
|
+
self_type temp(e);
|
|
868
|
+
do_divide(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
|
|
869
|
+
}
|
|
870
|
+
else
|
|
871
|
+
{
|
|
872
|
+
do_divide(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
|
|
873
|
+
}
|
|
874
|
+
return *this;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
template <class V>
|
|
878
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
|
|
879
|
+
operator/=(const V& v)
|
|
880
|
+
{
|
|
881
|
+
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, v);
|
|
882
|
+
//
|
|
883
|
+
// If the current precision of *this differs from that of value v, then we
|
|
884
|
+
// create a temporary (which will have the correct precision thanks to precision_guard)
|
|
885
|
+
// and then move the result into *this. In C++17 we add a leading "if constexpr"
|
|
886
|
+
// which causes this code to be eliminated in the common case that this type is
|
|
887
|
+
// not actually variable precision. Pre C++17 this code should still be mostly
|
|
888
|
+
// optimised away, but we can't prevent instantiation of the dead code leading
|
|
889
|
+
// to longer build and possibly link times.
|
|
890
|
+
//
|
|
891
|
+
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
|
|
892
|
+
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
|
|
893
|
+
{
|
|
894
|
+
number t(*this / v);
|
|
895
|
+
return *this = std::move(t);
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
using default_ops::eval_divide;
|
|
899
|
+
eval_divide(m_backend, canonical_value(v));
|
|
900
|
+
return *this;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator&=(const self_type& e)
|
|
904
|
+
{
|
|
905
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
|
|
906
|
+
do_bitwise_and(detail::expression<detail::terminal, self_type>(e), detail::terminal());
|
|
907
|
+
return *this;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
911
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator&=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
|
|
912
|
+
{
|
|
913
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
|
|
914
|
+
// Create a temporary if the RHS references *this, but not
|
|
915
|
+
// if we're just doing an x &= x;
|
|
916
|
+
if (contains_self(e) && !is_self(e))
|
|
917
|
+
{
|
|
918
|
+
self_type temp(e);
|
|
919
|
+
do_bitwise_and(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
|
|
920
|
+
}
|
|
921
|
+
else
|
|
922
|
+
{
|
|
923
|
+
do_bitwise_and(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
|
|
924
|
+
}
|
|
925
|
+
return *this;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
template <class V>
|
|
929
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
|
|
930
|
+
operator&=(const V& v)
|
|
931
|
+
{
|
|
932
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
|
|
933
|
+
using default_ops::eval_bitwise_and;
|
|
934
|
+
eval_bitwise_and(m_backend, canonical_value(v));
|
|
935
|
+
return *this;
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator|=(const self_type& e)
|
|
939
|
+
{
|
|
940
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
|
|
941
|
+
do_bitwise_or(detail::expression<detail::terminal, self_type>(e), detail::terminal());
|
|
942
|
+
return *this;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
946
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator|=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
|
|
947
|
+
{
|
|
948
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
|
|
949
|
+
// Create a temporary if the RHS references *this, but not
|
|
950
|
+
// if we're just doing an x |= x;
|
|
951
|
+
if (contains_self(e) && !is_self(e))
|
|
952
|
+
{
|
|
953
|
+
self_type temp(e);
|
|
954
|
+
do_bitwise_or(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
|
|
955
|
+
}
|
|
956
|
+
else
|
|
957
|
+
{
|
|
958
|
+
do_bitwise_or(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
|
|
959
|
+
}
|
|
960
|
+
return *this;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
template <class V>
|
|
964
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
|
|
965
|
+
operator|=(const V& v)
|
|
966
|
+
{
|
|
967
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
|
|
968
|
+
using default_ops::eval_bitwise_or;
|
|
969
|
+
eval_bitwise_or(m_backend, canonical_value(v));
|
|
970
|
+
return *this;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator^=(const self_type& e)
|
|
974
|
+
{
|
|
975
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
|
|
976
|
+
do_bitwise_xor(detail::expression<detail::terminal, self_type>(e), detail::terminal());
|
|
977
|
+
return *this;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
981
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator^=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
|
|
982
|
+
{
|
|
983
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
|
|
984
|
+
if (contains_self(e))
|
|
985
|
+
{
|
|
986
|
+
self_type temp(e);
|
|
987
|
+
do_bitwise_xor(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
|
|
988
|
+
}
|
|
989
|
+
else
|
|
990
|
+
{
|
|
991
|
+
do_bitwise_xor(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
|
|
992
|
+
}
|
|
993
|
+
return *this;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
template <class V>
|
|
997
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
|
|
998
|
+
operator^=(const V& v)
|
|
999
|
+
{
|
|
1000
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
|
|
1001
|
+
using default_ops::eval_bitwise_xor;
|
|
1002
|
+
eval_bitwise_xor(m_backend, canonical_value(v));
|
|
1003
|
+
return *this;
|
|
1004
|
+
}
|
|
1005
|
+
//
|
|
1006
|
+
// swap:
|
|
1007
|
+
//
|
|
1008
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void swap(self_type& other) noexcept(noexcept(std::declval<Backend>().swap(std::declval<Backend&>())))
|
|
1009
|
+
{
|
|
1010
|
+
m_backend.swap(other.backend());
|
|
1011
|
+
}
|
|
1012
|
+
//
|
|
1013
|
+
// Zero and sign:
|
|
1014
|
+
//
|
|
1015
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool is_zero() const
|
|
1016
|
+
{
|
|
1017
|
+
using default_ops::eval_is_zero;
|
|
1018
|
+
return eval_is_zero(m_backend);
|
|
1019
|
+
}
|
|
1020
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR int sign() const
|
|
1021
|
+
{
|
|
1022
|
+
using default_ops::eval_get_sign;
|
|
1023
|
+
return eval_get_sign(m_backend);
|
|
1024
|
+
}
|
|
1025
|
+
//
|
|
1026
|
+
// String conversion functions:
|
|
1027
|
+
//
|
|
1028
|
+
std::string str(std::streamsize digits = 0, std::ios_base::fmtflags f = std::ios_base::fmtflags(0)) const
|
|
1029
|
+
{
|
|
1030
|
+
return m_backend.str(digits, f);
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
#ifndef BOOST_MP_STANDALONE
|
|
1034
|
+
template <class Archive>
|
|
1035
|
+
void serialize(Archive& ar, const unsigned int /*version*/)
|
|
1036
|
+
{
|
|
1037
|
+
ar& boost::make_nvp("backend", m_backend);
|
|
1038
|
+
}
|
|
1039
|
+
#endif
|
|
1040
|
+
|
|
1041
|
+
private:
|
|
1042
|
+
template <class T>
|
|
1043
|
+
BOOST_MP_CXX14_CONSTEXPR void convert_to_imp(T* result) const
|
|
1044
|
+
{
|
|
1045
|
+
using default_ops::eval_convert_to;
|
|
1046
|
+
eval_convert_to(result, m_backend);
|
|
1047
|
+
}
|
|
1048
|
+
template <class B2, expression_template_option ET>
|
|
1049
|
+
BOOST_MP_CXX14_CONSTEXPR void convert_to_imp(number<B2, ET>* result) const
|
|
1050
|
+
{
|
|
1051
|
+
result->assign(*this);
|
|
1052
|
+
}
|
|
1053
|
+
BOOST_MP_CXX14_CONSTEXPR void convert_to_imp(std::string* result) const
|
|
1054
|
+
{
|
|
1055
|
+
*result = this->str();
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
public:
|
|
1059
|
+
template <class T>
|
|
1060
|
+
BOOST_MP_CXX14_CONSTEXPR T convert_to() const
|
|
1061
|
+
{
|
|
1062
|
+
T result = T();
|
|
1063
|
+
convert_to_imp(&result);
|
|
1064
|
+
return result;
|
|
1065
|
+
}
|
|
1066
|
+
//
|
|
1067
|
+
// Use in boolean context, and explicit conversion operators:
|
|
1068
|
+
//
|
|
1069
|
+
#if BOOST_WORKAROUND(BOOST_MSVC, < 1900) || (defined(__apple_build_version__) && BOOST_WORKAROUND(__clang_major__, < 9))
|
|
1070
|
+
template <class T>
|
|
1071
|
+
#else
|
|
1072
|
+
template <class T, class = typename std::enable_if<std::is_enum<T>::value || !(std::is_constructible<T, detail::convertible_to<self_type const&> >::value || !std::is_default_constructible<T>::value || (!boost::multiprecision::detail::is_arithmetic<T>::value && !boost::multiprecision::detail::is_complex<T>::value)), T>::type>
|
|
1073
|
+
#endif
|
|
1074
|
+
explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
|
|
1075
|
+
{
|
|
1076
|
+
return this->template convert_to<T>();
|
|
1077
|
+
}
|
|
1078
|
+
BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
|
|
1079
|
+
{
|
|
1080
|
+
return !is_zero();
|
|
1081
|
+
}
|
|
1082
|
+
//
|
|
1083
|
+
// Default precision:
|
|
1084
|
+
//
|
|
1085
|
+
static BOOST_MP_CXX14_CONSTEXPR unsigned default_precision() noexcept
|
|
1086
|
+
{
|
|
1087
|
+
return Backend::default_precision();
|
|
1088
|
+
}
|
|
1089
|
+
static BOOST_MP_CXX14_CONSTEXPR void default_precision(unsigned digits10)
|
|
1090
|
+
{
|
|
1091
|
+
Backend::default_precision(digits10);
|
|
1092
|
+
Backend::thread_default_precision(digits10);
|
|
1093
|
+
}
|
|
1094
|
+
static BOOST_MP_CXX14_CONSTEXPR unsigned thread_default_precision() noexcept
|
|
1095
|
+
{
|
|
1096
|
+
return Backend::thread_default_precision();
|
|
1097
|
+
}
|
|
1098
|
+
static BOOST_MP_CXX14_CONSTEXPR void thread_default_precision(unsigned digits10)
|
|
1099
|
+
{
|
|
1100
|
+
Backend::thread_default_precision(digits10);
|
|
1101
|
+
}
|
|
1102
|
+
BOOST_MP_CXX14_CONSTEXPR unsigned precision() const noexcept
|
|
1103
|
+
{
|
|
1104
|
+
return m_backend.precision();
|
|
1105
|
+
}
|
|
1106
|
+
BOOST_MP_CXX14_CONSTEXPR void precision(unsigned digits10)
|
|
1107
|
+
{
|
|
1108
|
+
m_backend.precision(digits10);
|
|
1109
|
+
}
|
|
1110
|
+
//
|
|
1111
|
+
// Variable precision options:
|
|
1112
|
+
//
|
|
1113
|
+
static constexpr variable_precision_options default_variable_precision_options()noexcept
|
|
1114
|
+
{
|
|
1115
|
+
return Backend::default_variable_precision_options();
|
|
1116
|
+
}
|
|
1117
|
+
static constexpr variable_precision_options thread_default_variable_precision_options()noexcept
|
|
1118
|
+
{
|
|
1119
|
+
return Backend::thread_default_variable_precision_options();
|
|
1120
|
+
}
|
|
1121
|
+
static BOOST_MP_CXX14_CONSTEXPR void default_variable_precision_options(variable_precision_options opts)
|
|
1122
|
+
{
|
|
1123
|
+
Backend::default_variable_precision_options(opts);
|
|
1124
|
+
Backend::thread_default_variable_precision_options(opts);
|
|
1125
|
+
}
|
|
1126
|
+
static BOOST_MP_CXX14_CONSTEXPR void thread_default_variable_precision_options(variable_precision_options opts)
|
|
1127
|
+
{
|
|
1128
|
+
Backend::thread_default_variable_precision_options(opts);
|
|
1129
|
+
}
|
|
1130
|
+
//
|
|
1131
|
+
// Comparison:
|
|
1132
|
+
//
|
|
1133
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR int compare(const number<Backend, ExpressionTemplates>& o) const
|
|
1134
|
+
noexcept(noexcept(std::declval<Backend>().compare(std::declval<Backend>())))
|
|
1135
|
+
{
|
|
1136
|
+
return m_backend.compare(o.m_backend);
|
|
1137
|
+
}
|
|
1138
|
+
template <class V>
|
|
1139
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<V>::value && (number_category<Backend>::value != number_kind_complex), int>::type compare(const V& o) const
|
|
1140
|
+
{
|
|
1141
|
+
using default_ops::eval_get_sign;
|
|
1142
|
+
if (o == 0)
|
|
1143
|
+
return eval_get_sign(m_backend);
|
|
1144
|
+
return m_backend.compare(canonical_value(o));
|
|
1145
|
+
}
|
|
1146
|
+
template <class V>
|
|
1147
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<V>::value && (number_category<Backend>::value == number_kind_complex), int>::type compare(const V& o) const
|
|
1148
|
+
{
|
|
1149
|
+
using default_ops::eval_get_sign;
|
|
1150
|
+
return m_backend.compare(canonical_value(o));
|
|
1151
|
+
}
|
|
1152
|
+
//
|
|
1153
|
+
// Direct access to the underlying backend:
|
|
1154
|
+
//
|
|
1155
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend& backend() & noexcept
|
|
1156
|
+
{
|
|
1157
|
+
return m_backend;
|
|
1158
|
+
}
|
|
1159
|
+
BOOST_MP_FORCEINLINE constexpr const Backend& backend() const& noexcept { return m_backend; }
|
|
1160
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend&& backend() && noexcept { return static_cast<Backend&&>(m_backend); }
|
|
1161
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend const&& backend() const&& noexcept { return static_cast<Backend const&&>(m_backend); }
|
|
1162
|
+
//
|
|
1163
|
+
// Complex number real and imag:
|
|
1164
|
+
//
|
|
1165
|
+
BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<number<Backend, ExpressionTemplates> >::type
|
|
1166
|
+
real() const
|
|
1167
|
+
{
|
|
1168
|
+
using default_ops::eval_real;
|
|
1169
|
+
detail::scoped_default_precision<typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type> precision_guard(*this);
|
|
1170
|
+
typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type result;
|
|
1171
|
+
eval_real(result.backend(), backend());
|
|
1172
|
+
return result;
|
|
1173
|
+
}
|
|
1174
|
+
BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<number<Backend, ExpressionTemplates> >::type
|
|
1175
|
+
imag() const
|
|
1176
|
+
{
|
|
1177
|
+
using default_ops::eval_imag;
|
|
1178
|
+
detail::scoped_default_precision<typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type> precision_guard(*this);
|
|
1179
|
+
typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type result;
|
|
1180
|
+
eval_imag(result.backend(), backend());
|
|
1181
|
+
return result;
|
|
1182
|
+
}
|
|
1183
|
+
template <class T>
|
|
1184
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T, self_type>::value, self_type&>::type real(const T& val)
|
|
1185
|
+
{
|
|
1186
|
+
using default_ops::eval_set_real;
|
|
1187
|
+
eval_set_real(backend(), canonical_value(val));
|
|
1188
|
+
return *this;
|
|
1189
|
+
}
|
|
1190
|
+
template <class T>
|
|
1191
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T, self_type>::value && number_category<self_type>::value == number_kind_complex, self_type&>::type imag(const T& val)
|
|
1192
|
+
{
|
|
1193
|
+
using default_ops::eval_set_imag;
|
|
1194
|
+
eval_set_imag(backend(), canonical_value(val));
|
|
1195
|
+
return *this;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
private:
|
|
1199
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
1200
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_assignable<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>::type
|
|
1201
|
+
do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const std::integral_constant<bool, false>&)
|
|
1202
|
+
{
|
|
1203
|
+
// The result of the expression isn't the same type as this -
|
|
1204
|
+
// create a temporary result and assign it to *this:
|
|
1205
|
+
using temp_type = typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type;
|
|
1206
|
+
temp_type t(e);
|
|
1207
|
+
*this = std::move(t);
|
|
1208
|
+
}
|
|
1209
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
1210
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_assignable<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>::type
|
|
1211
|
+
do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const std::integral_constant<bool, false>&)
|
|
1212
|
+
{
|
|
1213
|
+
// The result of the expression isn't the same type as this -
|
|
1214
|
+
// create a temporary result and assign it to *this:
|
|
1215
|
+
using temp_type = typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type;
|
|
1216
|
+
temp_type t(e);
|
|
1217
|
+
this->assign(t);
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
|
1221
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const std::integral_constant<bool, true>&)
|
|
1222
|
+
{
|
|
1223
|
+
do_assign(e, tag());
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
template <class Exp>
|
|
1227
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::add_immediates&)
|
|
1228
|
+
{
|
|
1229
|
+
using default_ops::eval_add;
|
|
1230
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1231
|
+
eval_add(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
|
|
1232
|
+
}
|
|
1233
|
+
template <class Exp>
|
|
1234
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::subtract_immediates&)
|
|
1235
|
+
{
|
|
1236
|
+
using default_ops::eval_subtract;
|
|
1237
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1238
|
+
eval_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
|
|
1239
|
+
}
|
|
1240
|
+
template <class Exp>
|
|
1241
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiply_immediates&)
|
|
1242
|
+
{
|
|
1243
|
+
using default_ops::eval_multiply;
|
|
1244
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1245
|
+
eval_multiply(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
|
|
1246
|
+
}
|
|
1247
|
+
template <class Exp>
|
|
1248
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiply_add&)
|
|
1249
|
+
{
|
|
1250
|
+
using default_ops::eval_multiply_add;
|
|
1251
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1252
|
+
eval_multiply_add(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value()));
|
|
1253
|
+
}
|
|
1254
|
+
template <class Exp>
|
|
1255
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiply_subtract&)
|
|
1256
|
+
{
|
|
1257
|
+
using default_ops::eval_multiply_subtract;
|
|
1258
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1259
|
+
eval_multiply_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value()));
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
template <class Exp>
|
|
1263
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::divide_immediates&)
|
|
1264
|
+
{
|
|
1265
|
+
using default_ops::eval_divide;
|
|
1266
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1267
|
+
eval_divide(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
template <class Exp>
|
|
1271
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::negate&)
|
|
1272
|
+
{
|
|
1273
|
+
using left_type = typename Exp::left_type;
|
|
1274
|
+
do_assign(e.left(), typename left_type::tag_type());
|
|
1275
|
+
m_backend.negate();
|
|
1276
|
+
}
|
|
1277
|
+
template <class Exp>
|
|
1278
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::plus&)
|
|
1279
|
+
{
|
|
1280
|
+
using left_type = typename Exp::left_type ;
|
|
1281
|
+
using right_type = typename Exp::right_type;
|
|
1282
|
+
|
|
1283
|
+
constexpr int const left_depth = left_type::depth;
|
|
1284
|
+
constexpr int const right_depth = right_type::depth;
|
|
1285
|
+
|
|
1286
|
+
bool bl = contains_self(e.left());
|
|
1287
|
+
bool br = contains_self(e.right());
|
|
1288
|
+
|
|
1289
|
+
if (bl && br)
|
|
1290
|
+
{
|
|
1291
|
+
self_type temp(e);
|
|
1292
|
+
temp.m_backend.swap(this->m_backend);
|
|
1293
|
+
}
|
|
1294
|
+
else if (bl && is_self(e.left()))
|
|
1295
|
+
{
|
|
1296
|
+
// Ignore the left node, it's *this, just add the right:
|
|
1297
|
+
do_add(e.right(), typename right_type::tag_type());
|
|
1298
|
+
}
|
|
1299
|
+
else if (br && is_self(e.right()))
|
|
1300
|
+
{
|
|
1301
|
+
// Ignore the right node, it's *this, just add the left:
|
|
1302
|
+
do_add(e.left(), typename left_type::tag_type());
|
|
1303
|
+
}
|
|
1304
|
+
else if (!br && (bl || (left_depth >= right_depth)))
|
|
1305
|
+
{ // br is always false, but if bl is true we must take the this branch:
|
|
1306
|
+
do_assign(e.left(), typename left_type::tag_type());
|
|
1307
|
+
do_add(e.right(), typename right_type::tag_type());
|
|
1308
|
+
}
|
|
1309
|
+
else
|
|
1310
|
+
{
|
|
1311
|
+
do_assign(e.right(), typename right_type::tag_type());
|
|
1312
|
+
do_add(e.left(), typename left_type::tag_type());
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
template <class Exp>
|
|
1316
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::minus&)
|
|
1317
|
+
{
|
|
1318
|
+
using left_type = typename Exp::left_type ;
|
|
1319
|
+
using right_type = typename Exp::right_type;
|
|
1320
|
+
|
|
1321
|
+
constexpr int const left_depth = left_type::depth;
|
|
1322
|
+
constexpr int const right_depth = right_type::depth;
|
|
1323
|
+
|
|
1324
|
+
bool bl = contains_self(e.left());
|
|
1325
|
+
bool br = contains_self(e.right());
|
|
1326
|
+
|
|
1327
|
+
if (bl && br)
|
|
1328
|
+
{
|
|
1329
|
+
self_type temp(e);
|
|
1330
|
+
temp.m_backend.swap(this->m_backend);
|
|
1331
|
+
}
|
|
1332
|
+
else if (bl && is_self(e.left()))
|
|
1333
|
+
{
|
|
1334
|
+
// Ignore the left node, it's *this, just subtract the right:
|
|
1335
|
+
do_subtract(e.right(), typename right_type::tag_type());
|
|
1336
|
+
}
|
|
1337
|
+
else if (br && is_self(e.right()))
|
|
1338
|
+
{
|
|
1339
|
+
// Ignore the right node, it's *this, just subtract the left and negate the result:
|
|
1340
|
+
do_subtract(e.left(), typename left_type::tag_type());
|
|
1341
|
+
m_backend.negate();
|
|
1342
|
+
}
|
|
1343
|
+
else if (!br && (bl || (left_depth >= right_depth)))
|
|
1344
|
+
{ // br is always false, but if bl is true we must take the this branch:
|
|
1345
|
+
do_assign(e.left(), typename left_type::tag_type());
|
|
1346
|
+
do_subtract(e.right(), typename right_type::tag_type());
|
|
1347
|
+
}
|
|
1348
|
+
else
|
|
1349
|
+
{
|
|
1350
|
+
do_assign(e.right(), typename right_type::tag_type());
|
|
1351
|
+
do_subtract(e.left(), typename left_type::tag_type());
|
|
1352
|
+
m_backend.negate();
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
template <class Exp>
|
|
1356
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiplies&)
|
|
1357
|
+
{
|
|
1358
|
+
using left_type = typename Exp::left_type ;
|
|
1359
|
+
using right_type = typename Exp::right_type;
|
|
1360
|
+
|
|
1361
|
+
constexpr int const left_depth = left_type::depth;
|
|
1362
|
+
constexpr int const right_depth = right_type::depth;
|
|
1363
|
+
|
|
1364
|
+
bool bl = contains_self(e.left());
|
|
1365
|
+
bool br = contains_self(e.right());
|
|
1366
|
+
|
|
1367
|
+
if (bl && br)
|
|
1368
|
+
{
|
|
1369
|
+
self_type temp(e);
|
|
1370
|
+
temp.m_backend.swap(this->m_backend);
|
|
1371
|
+
}
|
|
1372
|
+
else if (bl && is_self(e.left()))
|
|
1373
|
+
{
|
|
1374
|
+
// Ignore the left node, it's *this, just add the right:
|
|
1375
|
+
do_multiplies(e.right(), typename right_type::tag_type());
|
|
1376
|
+
}
|
|
1377
|
+
else if (br && is_self(e.right()))
|
|
1378
|
+
{
|
|
1379
|
+
// Ignore the right node, it's *this, just add the left:
|
|
1380
|
+
do_multiplies(e.left(), typename left_type::tag_type());
|
|
1381
|
+
}
|
|
1382
|
+
else if (!br && (bl || (left_depth >= right_depth)))
|
|
1383
|
+
{ // br is always false, but if bl is true we must take the this branch:
|
|
1384
|
+
do_assign(e.left(), typename left_type::tag_type());
|
|
1385
|
+
do_multiplies(e.right(), typename right_type::tag_type());
|
|
1386
|
+
}
|
|
1387
|
+
else
|
|
1388
|
+
{
|
|
1389
|
+
do_assign(e.right(), typename right_type::tag_type());
|
|
1390
|
+
do_multiplies(e.left(), typename left_type::tag_type());
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
template <class Exp>
|
|
1394
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::divides&)
|
|
1395
|
+
{
|
|
1396
|
+
using left_type = typename Exp::left_type ;
|
|
1397
|
+
using right_type = typename Exp::right_type;
|
|
1398
|
+
|
|
1399
|
+
bool bl = contains_self(e.left());
|
|
1400
|
+
bool br = contains_self(e.right());
|
|
1401
|
+
|
|
1402
|
+
if (bl && is_self(e.left()))
|
|
1403
|
+
{
|
|
1404
|
+
// Ignore the left node, it's *this, just add the right:
|
|
1405
|
+
do_divide(e.right(), typename right_type::tag_type());
|
|
1406
|
+
}
|
|
1407
|
+
else if (br)
|
|
1408
|
+
{
|
|
1409
|
+
self_type temp(e);
|
|
1410
|
+
temp.m_backend.swap(this->m_backend);
|
|
1411
|
+
}
|
|
1412
|
+
else
|
|
1413
|
+
{
|
|
1414
|
+
do_assign(e.left(), typename left_type::tag_type());
|
|
1415
|
+
do_divide(e.right(), typename right_type::tag_type());
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
template <class Exp>
|
|
1419
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::modulus&)
|
|
1420
|
+
{
|
|
1421
|
+
//
|
|
1422
|
+
// This operation is only valid for integer backends:
|
|
1423
|
+
//
|
|
1424
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
|
|
1425
|
+
|
|
1426
|
+
using left_type = typename Exp::left_type ;
|
|
1427
|
+
using right_type = typename Exp::right_type;
|
|
1428
|
+
|
|
1429
|
+
bool bl = contains_self(e.left());
|
|
1430
|
+
bool br = contains_self(e.right());
|
|
1431
|
+
|
|
1432
|
+
if (bl && is_self(e.left()))
|
|
1433
|
+
{
|
|
1434
|
+
// Ignore the left node, it's *this, just add the right:
|
|
1435
|
+
do_modulus(e.right(), typename right_type::tag_type());
|
|
1436
|
+
}
|
|
1437
|
+
else if (br)
|
|
1438
|
+
{
|
|
1439
|
+
self_type temp(e);
|
|
1440
|
+
temp.m_backend.swap(this->m_backend);
|
|
1441
|
+
}
|
|
1442
|
+
else
|
|
1443
|
+
{
|
|
1444
|
+
do_assign(e.left(), typename left_type::tag_type());
|
|
1445
|
+
do_modulus(e.right(), typename right_type::tag_type());
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
template <class Exp>
|
|
1449
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::modulus_immediates&)
|
|
1450
|
+
{
|
|
1451
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
|
|
1452
|
+
using default_ops::eval_modulus;
|
|
1453
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1454
|
+
eval_modulus(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
template <class Exp>
|
|
1458
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_and&)
|
|
1459
|
+
{
|
|
1460
|
+
//
|
|
1461
|
+
// This operation is only valid for integer backends:
|
|
1462
|
+
//
|
|
1463
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
|
|
1464
|
+
|
|
1465
|
+
using left_type = typename Exp::left_type ;
|
|
1466
|
+
using right_type = typename Exp::right_type;
|
|
1467
|
+
|
|
1468
|
+
constexpr int const left_depth = left_type::depth;
|
|
1469
|
+
constexpr int const right_depth = right_type::depth;
|
|
1470
|
+
|
|
1471
|
+
bool bl = contains_self(e.left());
|
|
1472
|
+
bool br = contains_self(e.right());
|
|
1473
|
+
|
|
1474
|
+
if (bl && is_self(e.left()))
|
|
1475
|
+
{
|
|
1476
|
+
// Ignore the left node, it's *this, just add the right:
|
|
1477
|
+
do_bitwise_and(e.right(), typename right_type::tag_type());
|
|
1478
|
+
}
|
|
1479
|
+
else if (br && is_self(e.right()))
|
|
1480
|
+
{
|
|
1481
|
+
do_bitwise_and(e.left(), typename left_type::tag_type());
|
|
1482
|
+
}
|
|
1483
|
+
else if (!br && (bl || (left_depth >= right_depth)))
|
|
1484
|
+
{
|
|
1485
|
+
do_assign(e.left(), typename left_type::tag_type());
|
|
1486
|
+
do_bitwise_and(e.right(), typename right_type::tag_type());
|
|
1487
|
+
}
|
|
1488
|
+
else
|
|
1489
|
+
{
|
|
1490
|
+
do_assign(e.right(), typename right_type::tag_type());
|
|
1491
|
+
do_bitwise_and(e.left(), typename left_type::tag_type());
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
template <class Exp>
|
|
1495
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_and_immediates&)
|
|
1496
|
+
{
|
|
1497
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
|
|
1498
|
+
using default_ops::eval_bitwise_and;
|
|
1499
|
+
eval_bitwise_and(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
template <class Exp>
|
|
1503
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_or&)
|
|
1504
|
+
{
|
|
1505
|
+
//
|
|
1506
|
+
// This operation is only valid for integer backends:
|
|
1507
|
+
//
|
|
1508
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
|
|
1509
|
+
|
|
1510
|
+
using left_type = typename Exp::left_type ;
|
|
1511
|
+
using right_type = typename Exp::right_type;
|
|
1512
|
+
|
|
1513
|
+
constexpr int const left_depth = left_type::depth;
|
|
1514
|
+
constexpr int const right_depth = right_type::depth;
|
|
1515
|
+
|
|
1516
|
+
bool bl = contains_self(e.left());
|
|
1517
|
+
bool br = contains_self(e.right());
|
|
1518
|
+
|
|
1519
|
+
if (bl && is_self(e.left()))
|
|
1520
|
+
{
|
|
1521
|
+
// Ignore the left node, it's *this, just add the right:
|
|
1522
|
+
do_bitwise_or(e.right(), typename right_type::tag_type());
|
|
1523
|
+
}
|
|
1524
|
+
else if (br && is_self(e.right()))
|
|
1525
|
+
{
|
|
1526
|
+
do_bitwise_or(e.left(), typename left_type::tag_type());
|
|
1527
|
+
}
|
|
1528
|
+
else if (!br && (bl || (left_depth >= right_depth)))
|
|
1529
|
+
{
|
|
1530
|
+
do_assign(e.left(), typename left_type::tag_type());
|
|
1531
|
+
do_bitwise_or(e.right(), typename right_type::tag_type());
|
|
1532
|
+
}
|
|
1533
|
+
else
|
|
1534
|
+
{
|
|
1535
|
+
do_assign(e.right(), typename right_type::tag_type());
|
|
1536
|
+
do_bitwise_or(e.left(), typename left_type::tag_type());
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
template <class Exp>
|
|
1540
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_or_immediates&)
|
|
1541
|
+
{
|
|
1542
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
|
|
1543
|
+
using default_ops::eval_bitwise_or;
|
|
1544
|
+
eval_bitwise_or(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
template <class Exp>
|
|
1548
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_xor&)
|
|
1549
|
+
{
|
|
1550
|
+
//
|
|
1551
|
+
// This operation is only valid for integer backends:
|
|
1552
|
+
//
|
|
1553
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
|
|
1554
|
+
|
|
1555
|
+
using left_type = typename Exp::left_type ;
|
|
1556
|
+
using right_type = typename Exp::right_type;
|
|
1557
|
+
|
|
1558
|
+
constexpr int const left_depth = left_type::depth;
|
|
1559
|
+
constexpr int const right_depth = right_type::depth;
|
|
1560
|
+
|
|
1561
|
+
bool bl = contains_self(e.left());
|
|
1562
|
+
bool br = contains_self(e.right());
|
|
1563
|
+
|
|
1564
|
+
if (bl && is_self(e.left()))
|
|
1565
|
+
{
|
|
1566
|
+
// Ignore the left node, it's *this, just add the right:
|
|
1567
|
+
do_bitwise_xor(e.right(), typename right_type::tag_type());
|
|
1568
|
+
}
|
|
1569
|
+
else if (br && is_self(e.right()))
|
|
1570
|
+
{
|
|
1571
|
+
do_bitwise_xor(e.left(), typename left_type::tag_type());
|
|
1572
|
+
}
|
|
1573
|
+
else if (!br && (bl || (left_depth >= right_depth)))
|
|
1574
|
+
{
|
|
1575
|
+
do_assign(e.left(), typename left_type::tag_type());
|
|
1576
|
+
do_bitwise_xor(e.right(), typename right_type::tag_type());
|
|
1577
|
+
}
|
|
1578
|
+
else
|
|
1579
|
+
{
|
|
1580
|
+
do_assign(e.right(), typename right_type::tag_type());
|
|
1581
|
+
do_bitwise_xor(e.left(), typename left_type::tag_type());
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
template <class Exp>
|
|
1585
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_xor_immediates&)
|
|
1586
|
+
{
|
|
1587
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
|
|
1588
|
+
using default_ops::eval_bitwise_xor;
|
|
1589
|
+
eval_bitwise_xor(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
|
|
1590
|
+
}
|
|
1591
|
+
template <class Exp>
|
|
1592
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::terminal&)
|
|
1593
|
+
{
|
|
1594
|
+
if (!is_self(e))
|
|
1595
|
+
{
|
|
1596
|
+
m_backend = canonical_value(e.value());
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
template <class Exp>
|
|
1600
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::function&)
|
|
1601
|
+
{
|
|
1602
|
+
using tag_type = typename Exp::arity;
|
|
1603
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1604
|
+
do_assign_function(e, tag_type());
|
|
1605
|
+
}
|
|
1606
|
+
template <class Exp>
|
|
1607
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::shift_left&)
|
|
1608
|
+
{
|
|
1609
|
+
// We can only shift by an integer value, not an arbitrary expression:
|
|
1610
|
+
using left_type = typename Exp::left_type ;
|
|
1611
|
+
using right_type = typename Exp::right_type ;
|
|
1612
|
+
using right_arity = typename right_type::arity;
|
|
1613
|
+
static_assert(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");
|
|
1614
|
+
using right_value_type = typename right_type::result_type;
|
|
1615
|
+
static_assert(boost::multiprecision::detail::is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");
|
|
1616
|
+
using tag_type = typename left_type::tag_type;
|
|
1617
|
+
do_assign_left_shift(e.left(), canonical_value(e.right().value()), tag_type());
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
template <class Exp>
|
|
1621
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::shift_right&)
|
|
1622
|
+
{
|
|
1623
|
+
// We can only shift by an integer value, not an arbitrary expression:
|
|
1624
|
+
using left_type = typename Exp::left_type ;
|
|
1625
|
+
using right_type = typename Exp::right_type ;
|
|
1626
|
+
using right_arity = typename right_type::arity;
|
|
1627
|
+
static_assert(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");
|
|
1628
|
+
using right_value_type = typename right_type::result_type;
|
|
1629
|
+
static_assert(boost::multiprecision::detail::is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");
|
|
1630
|
+
using tag_type = typename left_type::tag_type;
|
|
1631
|
+
do_assign_right_shift(e.left(), canonical_value(e.right().value()), tag_type());
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
template <class Exp>
|
|
1635
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_complement&)
|
|
1636
|
+
{
|
|
1637
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");
|
|
1638
|
+
using default_ops::eval_complement;
|
|
1639
|
+
self_type temp(e.left());
|
|
1640
|
+
eval_complement(m_backend, temp.backend());
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
template <class Exp>
|
|
1644
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::complement_immediates&)
|
|
1645
|
+
{
|
|
1646
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");
|
|
1647
|
+
using default_ops::eval_complement;
|
|
1648
|
+
eval_complement(m_backend, canonical_value(e.left().value()));
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
template <class Exp, class Val>
|
|
1652
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_right_shift(const Exp& e, const Val& val, const detail::terminal&)
|
|
1653
|
+
{
|
|
1654
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");
|
|
1655
|
+
using default_ops::eval_right_shift;
|
|
1656
|
+
detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
|
|
1657
|
+
eval_right_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
template <class Exp, class Val>
|
|
1661
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_left_shift(const Exp& e, const Val& val, const detail::terminal&)
|
|
1662
|
+
{
|
|
1663
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");
|
|
1664
|
+
using default_ops::eval_left_shift;
|
|
1665
|
+
detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
|
|
1666
|
+
eval_left_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
template <class Exp, class Val, class Tag>
|
|
1670
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_right_shift(const Exp& e, const Val& val, const Tag&)
|
|
1671
|
+
{
|
|
1672
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");
|
|
1673
|
+
using default_ops::eval_right_shift;
|
|
1674
|
+
self_type temp(e);
|
|
1675
|
+
detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
|
|
1676
|
+
eval_right_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
template <class Exp, class Val, class Tag>
|
|
1680
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_left_shift(const Exp& e, const Val& val, const Tag&)
|
|
1681
|
+
{
|
|
1682
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");
|
|
1683
|
+
using default_ops::eval_left_shift;
|
|
1684
|
+
self_type temp(e);
|
|
1685
|
+
detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
|
|
1686
|
+
eval_left_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
template <class Exp>
|
|
1690
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 1>&)
|
|
1691
|
+
{
|
|
1692
|
+
e.left().value()(&m_backend);
|
|
1693
|
+
}
|
|
1694
|
+
template <class Exp>
|
|
1695
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 2>&)
|
|
1696
|
+
{
|
|
1697
|
+
using right_type = typename Exp::right_type ;
|
|
1698
|
+
using tag_type = typename right_type::tag_type;
|
|
1699
|
+
do_assign_function_1(e.left().value(), e.right_ref(), tag_type());
|
|
1700
|
+
}
|
|
1701
|
+
template <class F, class Exp>
|
|
1702
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function_1(const F& f, const Exp& val, const detail::terminal&)
|
|
1703
|
+
{
|
|
1704
|
+
f(m_backend, function_arg_value(val));
|
|
1705
|
+
}
|
|
1706
|
+
template <class F, class Exp, class Tag>
|
|
1707
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function_1(const F& f, const Exp& val, const Tag&)
|
|
1708
|
+
{
|
|
1709
|
+
typename Exp::result_type t(val);
|
|
1710
|
+
f(m_backend, t.backend());
|
|
1711
|
+
}
|
|
1712
|
+
template <class Exp>
|
|
1713
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 3>&)
|
|
1714
|
+
{
|
|
1715
|
+
using middle_type = typename Exp::middle_type ;
|
|
1716
|
+
using tag_type = typename middle_type::tag_type;
|
|
1717
|
+
using end_type = typename Exp::right_type ;
|
|
1718
|
+
using end_tag = typename end_type::tag_type ;
|
|
1719
|
+
do_assign_function_2(e.left().value(), e.middle_ref(), e.right_ref(), tag_type(), end_tag());
|
|
1720
|
+
}
|
|
1721
|
+
template <class F, class Exp1, class Exp2>
|
|
1722
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const detail::terminal&)
|
|
1723
|
+
{
|
|
1724
|
+
f(m_backend, function_arg_value(val1), function_arg_value(val2));
|
|
1725
|
+
}
|
|
1726
|
+
template <class F, class Exp1, class Exp2, class Tag1>
|
|
1727
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const detail::terminal&)
|
|
1728
|
+
{
|
|
1729
|
+
typename Exp1::result_type temp1(val1);
|
|
1730
|
+
f(m_backend, std::move(temp1.backend()), function_arg_value(val2));
|
|
1731
|
+
}
|
|
1732
|
+
template <class F, class Exp1, class Exp2, class Tag2>
|
|
1733
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const Tag2&)
|
|
1734
|
+
{
|
|
1735
|
+
typename Exp2::result_type temp2(val2);
|
|
1736
|
+
f(m_backend, function_arg_value(val1), std::move(temp2.backend()));
|
|
1737
|
+
}
|
|
1738
|
+
template <class F, class Exp1, class Exp2, class Tag1, class Tag2>
|
|
1739
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const Tag2&)
|
|
1740
|
+
{
|
|
1741
|
+
typename Exp1::result_type temp1(val1);
|
|
1742
|
+
typename Exp2::result_type temp2(val2);
|
|
1743
|
+
f(m_backend, std::move(temp1.backend()), std::move(temp2.backend()));
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
template <class Exp>
|
|
1747
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 4>&)
|
|
1748
|
+
{
|
|
1749
|
+
using left_type = typename Exp::left_middle_type ;
|
|
1750
|
+
using left_tag_type = typename left_type::tag_type ;
|
|
1751
|
+
using middle_type = typename Exp::right_middle_type;
|
|
1752
|
+
using middle_tag_type = typename middle_type::tag_type ;
|
|
1753
|
+
using right_type = typename Exp::right_type ;
|
|
1754
|
+
using right_tag_type = typename right_type::tag_type ;
|
|
1755
|
+
do_assign_function_3a(e.left().value(), e.left_middle_ref(), e.right_middle_ref(), e.right_ref(), left_tag_type(), middle_tag_type(), right_tag_type());
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
template <class F, class Exp1, class Exp2, class Exp3, class Tag2, class Tag3>
|
|
1759
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag2& t2, const Tag3& t3)
|
|
1760
|
+
{
|
|
1761
|
+
do_assign_function_3b(f, val1, val2, val3, t2, t3);
|
|
1762
|
+
}
|
|
1763
|
+
template <class F, class Exp1, class Exp2, class Exp3, class Tag1, class Tag2, class Tag3>
|
|
1764
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag1&, const Tag2& t2, const Tag3& t3)
|
|
1765
|
+
{
|
|
1766
|
+
typename Exp1::result_type t(val1);
|
|
1767
|
+
do_assign_function_3b(f, std::move(t), val2, val3, t2, t3);
|
|
1768
|
+
}
|
|
1769
|
+
template <class F, class Exp1, class Exp2, class Exp3, class Tag3>
|
|
1770
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag3& t3)
|
|
1771
|
+
{
|
|
1772
|
+
do_assign_function_3c(f, val1, val2, val3, t3);
|
|
1773
|
+
}
|
|
1774
|
+
template <class F, class Exp1, class Exp2, class Exp3, class Tag2, class Tag3>
|
|
1775
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag2& /*t2*/, const Tag3& t3)
|
|
1776
|
+
{
|
|
1777
|
+
typename Exp2::result_type t(val2);
|
|
1778
|
+
do_assign_function_3c(f, val1, std::move(t), val3, t3);
|
|
1779
|
+
}
|
|
1780
|
+
template <class F, class Exp1, class Exp2, class Exp3>
|
|
1781
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&)
|
|
1782
|
+
{
|
|
1783
|
+
f(m_backend, function_arg_value(val1), function_arg_value(val2), function_arg_value(val3));
|
|
1784
|
+
}
|
|
1785
|
+
template <class F, class Exp1, class Exp2, class Exp3, class Tag3>
|
|
1786
|
+
BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag3& /*t3*/)
|
|
1787
|
+
{
|
|
1788
|
+
typename Exp3::result_type t(val3);
|
|
1789
|
+
do_assign_function_3c(f, val1, val2, std::move(t), detail::terminal());
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
template <class Exp>
|
|
1793
|
+
BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::terminal&)
|
|
1794
|
+
{
|
|
1795
|
+
using default_ops::eval_add;
|
|
1796
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1797
|
+
eval_add(m_backend, canonical_value(e.value()));
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
template <class Exp>
|
|
1801
|
+
BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::negate&)
|
|
1802
|
+
{
|
|
1803
|
+
using left_type = typename Exp::left_type;
|
|
1804
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1805
|
+
do_subtract(e.left(), typename left_type::tag_type());
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
template <class Exp>
|
|
1809
|
+
BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::plus&)
|
|
1810
|
+
{
|
|
1811
|
+
using left_type = typename Exp::left_type ;
|
|
1812
|
+
using right_type = typename Exp::right_type;
|
|
1813
|
+
do_add(e.left(), typename left_type::tag_type());
|
|
1814
|
+
do_add(e.right(), typename right_type::tag_type());
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
template <class Exp>
|
|
1818
|
+
BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::minus&)
|
|
1819
|
+
{
|
|
1820
|
+
using left_type = typename Exp::left_type ;
|
|
1821
|
+
using right_type = typename Exp::right_type;
|
|
1822
|
+
do_add(e.left(), typename left_type::tag_type());
|
|
1823
|
+
do_subtract(e.right(), typename right_type::tag_type());
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
template <class Exp, class unknown>
|
|
1827
|
+
BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const unknown&)
|
|
1828
|
+
{
|
|
1829
|
+
self_type temp(e);
|
|
1830
|
+
do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
template <class Exp>
|
|
1834
|
+
BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::add_immediates&)
|
|
1835
|
+
{
|
|
1836
|
+
using default_ops::eval_add;
|
|
1837
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1838
|
+
eval_add(m_backend, canonical_value(e.left().value()));
|
|
1839
|
+
eval_add(m_backend, canonical_value(e.right().value()));
|
|
1840
|
+
}
|
|
1841
|
+
template <class Exp>
|
|
1842
|
+
BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::subtract_immediates&)
|
|
1843
|
+
{
|
|
1844
|
+
using default_ops::eval_add;
|
|
1845
|
+
using default_ops::eval_subtract;
|
|
1846
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1847
|
+
eval_add(m_backend, canonical_value(e.left().value()));
|
|
1848
|
+
eval_subtract(m_backend, canonical_value(e.right().value()));
|
|
1849
|
+
}
|
|
1850
|
+
template <class Exp>
|
|
1851
|
+
BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::terminal&)
|
|
1852
|
+
{
|
|
1853
|
+
using default_ops::eval_subtract;
|
|
1854
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1855
|
+
eval_subtract(m_backend, canonical_value(e.value()));
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
template <class Exp>
|
|
1859
|
+
BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::negate&)
|
|
1860
|
+
{
|
|
1861
|
+
using left_type = typename Exp::left_type;
|
|
1862
|
+
do_add(e.left(), typename left_type::tag_type());
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
template <class Exp>
|
|
1866
|
+
BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::plus&)
|
|
1867
|
+
{
|
|
1868
|
+
using left_type = typename Exp::left_type ;
|
|
1869
|
+
using right_type = typename Exp::right_type;
|
|
1870
|
+
do_subtract(e.left(), typename left_type::tag_type());
|
|
1871
|
+
do_subtract(e.right(), typename right_type::tag_type());
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
template <class Exp>
|
|
1875
|
+
BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::minus&)
|
|
1876
|
+
{
|
|
1877
|
+
using left_type = typename Exp::left_type ;
|
|
1878
|
+
using right_type = typename Exp::right_type;
|
|
1879
|
+
do_subtract(e.left(), typename left_type::tag_type());
|
|
1880
|
+
do_add(e.right(), typename right_type::tag_type());
|
|
1881
|
+
}
|
|
1882
|
+
template <class Exp>
|
|
1883
|
+
BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::add_immediates&)
|
|
1884
|
+
{
|
|
1885
|
+
using default_ops::eval_subtract;
|
|
1886
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1887
|
+
eval_subtract(m_backend, canonical_value(e.left().value()));
|
|
1888
|
+
eval_subtract(m_backend, canonical_value(e.right().value()));
|
|
1889
|
+
}
|
|
1890
|
+
template <class Exp>
|
|
1891
|
+
BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::subtract_immediates&)
|
|
1892
|
+
{
|
|
1893
|
+
using default_ops::eval_add;
|
|
1894
|
+
using default_ops::eval_subtract;
|
|
1895
|
+
eval_subtract(m_backend, canonical_value(e.left().value()));
|
|
1896
|
+
eval_add(m_backend, canonical_value(e.right().value()));
|
|
1897
|
+
}
|
|
1898
|
+
template <class Exp, class unknown>
|
|
1899
|
+
BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const unknown&)
|
|
1900
|
+
{
|
|
1901
|
+
self_type temp(e);
|
|
1902
|
+
do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
template <class Exp>
|
|
1906
|
+
BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::terminal&)
|
|
1907
|
+
{
|
|
1908
|
+
using default_ops::eval_multiply;
|
|
1909
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1910
|
+
eval_multiply(m_backend, canonical_value(e.value()));
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
template <class Exp>
|
|
1914
|
+
BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::negate&)
|
|
1915
|
+
{
|
|
1916
|
+
using left_type = typename Exp::left_type;
|
|
1917
|
+
do_multiplies(e.left(), typename left_type::tag_type());
|
|
1918
|
+
m_backend.negate();
|
|
1919
|
+
}
|
|
1920
|
+
|
|
1921
|
+
template <class Exp>
|
|
1922
|
+
BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::multiplies&)
|
|
1923
|
+
{
|
|
1924
|
+
using left_type = typename Exp::left_type ;
|
|
1925
|
+
using right_type = typename Exp::right_type;
|
|
1926
|
+
do_multiplies(e.left(), typename left_type::tag_type());
|
|
1927
|
+
do_multiplies(e.right(), typename right_type::tag_type());
|
|
1928
|
+
}
|
|
1929
|
+
//
|
|
1930
|
+
// This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
|
|
1931
|
+
// the disable_if dependent on the template argument (the size of 1 can never occur in practice).
|
|
1932
|
+
//
|
|
1933
|
+
template <class Exp>
|
|
1934
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
|
|
1935
|
+
do_multiplies(const Exp& e, const detail::divides&)
|
|
1936
|
+
{
|
|
1937
|
+
using left_type = typename Exp::left_type ;
|
|
1938
|
+
using right_type = typename Exp::right_type;
|
|
1939
|
+
do_multiplies(e.left(), typename left_type::tag_type());
|
|
1940
|
+
do_divide(e.right(), typename right_type::tag_type());
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
template <class Exp>
|
|
1944
|
+
BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::multiply_immediates&)
|
|
1945
|
+
{
|
|
1946
|
+
using default_ops::eval_multiply;
|
|
1947
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1948
|
+
eval_multiply(m_backend, canonical_value(e.left().value()));
|
|
1949
|
+
eval_multiply(m_backend, canonical_value(e.right().value()));
|
|
1950
|
+
}
|
|
1951
|
+
//
|
|
1952
|
+
// This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
|
|
1953
|
+
// the disable_if dependent on the template argument (the size of 1 can never occur in practice).
|
|
1954
|
+
//
|
|
1955
|
+
template <class Exp>
|
|
1956
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
|
|
1957
|
+
do_multiplies(const Exp& e, const detail::divide_immediates&)
|
|
1958
|
+
{
|
|
1959
|
+
using default_ops::eval_divide;
|
|
1960
|
+
using default_ops::eval_multiply;
|
|
1961
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1962
|
+
eval_multiply(m_backend, canonical_value(e.left().value()));
|
|
1963
|
+
eval_divide(m_backend, canonical_value(e.right().value()));
|
|
1964
|
+
}
|
|
1965
|
+
template <class Exp, class unknown>
|
|
1966
|
+
BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const unknown&)
|
|
1967
|
+
{
|
|
1968
|
+
using default_ops::eval_multiply;
|
|
1969
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1970
|
+
self_type temp(e);
|
|
1971
|
+
eval_multiply(m_backend, temp.m_backend);
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
template <class Exp>
|
|
1975
|
+
BOOST_MP_CXX14_CONSTEXPR void do_divide(const Exp& e, const detail::terminal&)
|
|
1976
|
+
{
|
|
1977
|
+
using default_ops::eval_divide;
|
|
1978
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
1979
|
+
eval_divide(m_backend, canonical_value(e.value()));
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1982
|
+
template <class Exp>
|
|
1983
|
+
BOOST_MP_CXX14_CONSTEXPR void do_divide(const Exp& e, const detail::negate&)
|
|
1984
|
+
{
|
|
1985
|
+
using left_type = typename Exp::left_type;
|
|
1986
|
+
do_divide(e.left(), typename left_type::tag_type());
|
|
1987
|
+
m_backend.negate();
|
|
1988
|
+
}
|
|
1989
|
+
//
|
|
1990
|
+
// This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
|
|
1991
|
+
// the disable_if dependent on the template argument (the size of 1 can never occur in practice).
|
|
1992
|
+
//
|
|
1993
|
+
template <class Exp>
|
|
1994
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
|
|
1995
|
+
do_divide(const Exp& e, const detail::multiplies&)
|
|
1996
|
+
{
|
|
1997
|
+
using left_type = typename Exp::left_type ;
|
|
1998
|
+
using right_type = typename Exp::right_type;
|
|
1999
|
+
do_divide(e.left(), typename left_type::tag_type());
|
|
2000
|
+
do_divide(e.right(), typename right_type::tag_type());
|
|
2001
|
+
}
|
|
2002
|
+
//
|
|
2003
|
+
// This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
|
|
2004
|
+
// the disable_if dependent on the template argument (the size of 1 can never occur in practice).
|
|
2005
|
+
//
|
|
2006
|
+
template <class Exp>
|
|
2007
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
|
|
2008
|
+
do_divide(const Exp& e, const detail::divides&)
|
|
2009
|
+
{
|
|
2010
|
+
using left_type = typename Exp::left_type ;
|
|
2011
|
+
using right_type = typename Exp::right_type;
|
|
2012
|
+
do_divide(e.left(), typename left_type::tag_type());
|
|
2013
|
+
do_multiplies(e.right(), typename right_type::tag_type());
|
|
2014
|
+
}
|
|
2015
|
+
//
|
|
2016
|
+
// This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
|
|
2017
|
+
// the disable_if dependent on the template argument (the size of 1 can never occur in practice).
|
|
2018
|
+
//
|
|
2019
|
+
template <class Exp>
|
|
2020
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
|
|
2021
|
+
do_divides(const Exp& e, const detail::multiply_immediates&)
|
|
2022
|
+
{
|
|
2023
|
+
using default_ops::eval_divide;
|
|
2024
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
2025
|
+
eval_divide(m_backend, canonical_value(e.left().value()));
|
|
2026
|
+
eval_divide(m_backend, canonical_value(e.right().value()));
|
|
2027
|
+
}
|
|
2028
|
+
//
|
|
2029
|
+
// This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
|
|
2030
|
+
// the disable_if dependent on the template argument (the size of 1 can never occur in practice).
|
|
2031
|
+
//
|
|
2032
|
+
template <class Exp>
|
|
2033
|
+
BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
|
|
2034
|
+
do_divides(const Exp& e, const detail::divide_immediates&)
|
|
2035
|
+
{
|
|
2036
|
+
using default_ops::eval_divide;
|
|
2037
|
+
using default_ops::eval_multiply;
|
|
2038
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
2039
|
+
eval_divide(m_backend, canonical_value(e.left().value()));
|
|
2040
|
+
mutiply(m_backend, canonical_value(e.right().value()));
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
template <class Exp, class unknown>
|
|
2044
|
+
BOOST_MP_CXX14_CONSTEXPR void do_divide(const Exp& e, const unknown&)
|
|
2045
|
+
{
|
|
2046
|
+
using default_ops::eval_multiply;
|
|
2047
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
2048
|
+
self_type temp(e);
|
|
2049
|
+
eval_divide(m_backend, temp.m_backend);
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
template <class Exp>
|
|
2053
|
+
BOOST_MP_CXX14_CONSTEXPR void do_modulus(const Exp& e, const detail::terminal&)
|
|
2054
|
+
{
|
|
2055
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
|
|
2056
|
+
using default_ops::eval_modulus;
|
|
2057
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
2058
|
+
eval_modulus(m_backend, canonical_value(e.value()));
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
template <class Exp, class Unknown>
|
|
2062
|
+
BOOST_MP_CXX14_CONSTEXPR void do_modulus(const Exp& e, const Unknown&)
|
|
2063
|
+
{
|
|
2064
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
|
|
2065
|
+
using default_ops::eval_modulus;
|
|
2066
|
+
boost::multiprecision::detail::maybe_promote_precision(this);
|
|
2067
|
+
self_type temp(e);
|
|
2068
|
+
eval_modulus(m_backend, canonical_value(temp));
|
|
2069
|
+
}
|
|
2070
|
+
|
|
2071
|
+
template <class Exp>
|
|
2072
|
+
BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const detail::terminal&)
|
|
2073
|
+
{
|
|
2074
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
|
|
2075
|
+
using default_ops::eval_bitwise_and;
|
|
2076
|
+
eval_bitwise_and(m_backend, canonical_value(e.value()));
|
|
2077
|
+
}
|
|
2078
|
+
template <class Exp>
|
|
2079
|
+
BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const detail::bitwise_and&)
|
|
2080
|
+
{
|
|
2081
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
|
|
2082
|
+
using left_type = typename Exp::left_type ;
|
|
2083
|
+
using right_type = typename Exp::right_type;
|
|
2084
|
+
do_bitwise_and(e.left(), typename left_type::tag_type());
|
|
2085
|
+
do_bitwise_and(e.right(), typename right_type::tag_type());
|
|
2086
|
+
}
|
|
2087
|
+
template <class Exp, class unknown>
|
|
2088
|
+
BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const unknown&)
|
|
2089
|
+
{
|
|
2090
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
|
|
2091
|
+
using default_ops::eval_bitwise_and;
|
|
2092
|
+
self_type temp(e);
|
|
2093
|
+
eval_bitwise_and(m_backend, temp.m_backend);
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
template <class Exp>
|
|
2097
|
+
BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const detail::terminal&)
|
|
2098
|
+
{
|
|
2099
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
|
|
2100
|
+
using default_ops::eval_bitwise_or;
|
|
2101
|
+
eval_bitwise_or(m_backend, canonical_value(e.value()));
|
|
2102
|
+
}
|
|
2103
|
+
template <class Exp>
|
|
2104
|
+
BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const detail::bitwise_or&)
|
|
2105
|
+
{
|
|
2106
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
|
|
2107
|
+
using left_type = typename Exp::left_type ;
|
|
2108
|
+
using right_type = typename Exp::right_type;
|
|
2109
|
+
do_bitwise_or(e.left(), typename left_type::tag_type());
|
|
2110
|
+
do_bitwise_or(e.right(), typename right_type::tag_type());
|
|
2111
|
+
}
|
|
2112
|
+
template <class Exp, class unknown>
|
|
2113
|
+
BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const unknown&)
|
|
2114
|
+
{
|
|
2115
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
|
|
2116
|
+
using default_ops::eval_bitwise_or;
|
|
2117
|
+
self_type temp(e);
|
|
2118
|
+
eval_bitwise_or(m_backend, temp.m_backend);
|
|
2119
|
+
}
|
|
2120
|
+
|
|
2121
|
+
template <class Exp>
|
|
2122
|
+
BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const detail::terminal&)
|
|
2123
|
+
{
|
|
2124
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
|
|
2125
|
+
using default_ops::eval_bitwise_xor;
|
|
2126
|
+
eval_bitwise_xor(m_backend, canonical_value(e.value()));
|
|
2127
|
+
}
|
|
2128
|
+
template <class Exp>
|
|
2129
|
+
BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const detail::bitwise_xor&)
|
|
2130
|
+
{
|
|
2131
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
|
|
2132
|
+
using left_type = typename Exp::left_type ;
|
|
2133
|
+
using right_type = typename Exp::right_type;
|
|
2134
|
+
do_bitwise_xor(e.left(), typename left_type::tag_type());
|
|
2135
|
+
do_bitwise_xor(e.right(), typename right_type::tag_type());
|
|
2136
|
+
}
|
|
2137
|
+
template <class Exp, class unknown>
|
|
2138
|
+
BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const unknown&)
|
|
2139
|
+
{
|
|
2140
|
+
static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
|
|
2141
|
+
using default_ops::eval_bitwise_xor;
|
|
2142
|
+
self_type temp(e);
|
|
2143
|
+
eval_bitwise_xor(m_backend, temp.m_backend);
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
// Tests if the expression contains a reference to *this:
|
|
2147
|
+
template <class Exp>
|
|
2148
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e) const noexcept
|
|
2149
|
+
{
|
|
2150
|
+
return contains_self(e, typename Exp::arity());
|
|
2151
|
+
}
|
|
2152
|
+
template <class Exp>
|
|
2153
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 0> const&) const noexcept
|
|
2154
|
+
{
|
|
2155
|
+
return is_realy_self(e.value());
|
|
2156
|
+
}
|
|
2157
|
+
template <class Exp>
|
|
2158
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 1> const&) const noexcept
|
|
2159
|
+
{
|
|
2160
|
+
using child_type = typename Exp::left_type;
|
|
2161
|
+
return contains_self(e.left(), typename child_type::arity());
|
|
2162
|
+
}
|
|
2163
|
+
template <class Exp>
|
|
2164
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 2> const&) const noexcept
|
|
2165
|
+
{
|
|
2166
|
+
using child0_type = typename Exp::left_type ;
|
|
2167
|
+
using child1_type = typename Exp::right_type;
|
|
2168
|
+
return contains_self(e.left(), typename child0_type::arity()) || contains_self(e.right(), typename child1_type::arity());
|
|
2169
|
+
}
|
|
2170
|
+
template <class Exp>
|
|
2171
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 3> const&) const noexcept
|
|
2172
|
+
{
|
|
2173
|
+
using child0_type = typename Exp::left_type ;
|
|
2174
|
+
using child1_type = typename Exp::middle_type;
|
|
2175
|
+
using child2_type = typename Exp::right_type ;
|
|
2176
|
+
return contains_self(e.left(), typename child0_type::arity()) || contains_self(e.middle(), typename child1_type::arity()) || contains_self(e.right(), typename child2_type::arity());
|
|
2177
|
+
}
|
|
2178
|
+
template <class Exp>
|
|
2179
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 4> const&) const noexcept
|
|
2180
|
+
{
|
|
2181
|
+
using child0_type = typename Exp::left_type;
|
|
2182
|
+
using child1_type = typename Exp::left_middle_type;
|
|
2183
|
+
using child2_type = typename Exp::right_middle_type;
|
|
2184
|
+
using child3_type = typename Exp::right_type;
|
|
2185
|
+
return contains_self(e.left(), typename child0_type::arity()) || contains_self(e.left_middle(), typename child1_type::arity()) || contains_self(e.right_middle(), typename child2_type::arity()) || contains_self(e.right(), typename child3_type::arity());
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
// Test if the expression is a reference to *this:
|
|
2189
|
+
template <class Exp>
|
|
2190
|
+
BOOST_MP_FORCEINLINE constexpr bool is_self(const Exp& e) const noexcept
|
|
2191
|
+
{
|
|
2192
|
+
return is_self(e, typename Exp::arity());
|
|
2193
|
+
}
|
|
2194
|
+
template <class Exp>
|
|
2195
|
+
BOOST_MP_FORCEINLINE constexpr bool is_self(const Exp& e, std::integral_constant<int, 0> const&) const noexcept
|
|
2196
|
+
{
|
|
2197
|
+
return is_realy_self(e.value());
|
|
2198
|
+
}
|
|
2199
|
+
template <class Exp, int v>
|
|
2200
|
+
BOOST_MP_FORCEINLINE constexpr bool is_self(const Exp&, std::integral_constant<int, v> const&) const noexcept
|
|
2201
|
+
{
|
|
2202
|
+
return false;
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
template <class Val>
|
|
2206
|
+
BOOST_MP_FORCEINLINE constexpr bool is_realy_self(const Val&) const noexcept { return false; }
|
|
2207
|
+
BOOST_MP_FORCEINLINE constexpr bool is_realy_self(const self_type& v) const noexcept { return &v == this; }
|
|
2208
|
+
|
|
2209
|
+
static BOOST_MP_FORCEINLINE constexpr const Backend& function_arg_value(const self_type& v) noexcept { return v.backend(); }
|
|
2210
|
+
template <class Other, expression_template_option ET2>
|
|
2211
|
+
static BOOST_MP_FORCEINLINE constexpr const Other& function_arg_value(const number<Other, ET2>& v) noexcept { return v.backend(); }
|
|
2212
|
+
template <class V>
|
|
2213
|
+
static BOOST_MP_FORCEINLINE constexpr const V& function_arg_value(const V& v) noexcept { return v; }
|
|
2214
|
+
template <class A1, class A2, class A3, class A4>
|
|
2215
|
+
static BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR const A1& function_arg_value(const detail::expression<detail::terminal, A1, A2, A3, A4>& exp) noexcept { return exp.value(); }
|
|
2216
|
+
template <class A2, class A3, class A4>
|
|
2217
|
+
static BOOST_MP_FORCEINLINE constexpr const Backend& function_arg_value(const detail::expression<detail::terminal, number<Backend>, A2, A3, A4>& exp) noexcept { return exp.value().backend(); }
|
|
2218
|
+
Backend m_backend;
|
|
2219
|
+
|
|
2220
|
+
public:
|
|
2221
|
+
//
|
|
2222
|
+
// These shouldn't really need to be public, or even member functions, but it makes implementing
|
|
2223
|
+
// the non-member operators way easier if they are:
|
|
2224
|
+
//
|
|
2225
|
+
static BOOST_MP_FORCEINLINE constexpr const Backend& canonical_value(const self_type& v) noexcept { return v.m_backend; }
|
|
2226
|
+
template <class B2, expression_template_option ET>
|
|
2227
|
+
static BOOST_MP_FORCEINLINE constexpr const B2& canonical_value(const number<B2, ET>& v) noexcept { return v.backend(); }
|
|
2228
|
+
template <class B2, expression_template_option ET>
|
|
2229
|
+
static BOOST_MP_FORCEINLINE constexpr B2&& canonical_value(number<B2, ET>&& v) noexcept { return static_cast<number<B2, ET>&&>(v).backend(); }
|
|
2230
|
+
template <class V>
|
|
2231
|
+
static BOOST_MP_FORCEINLINE constexpr typename std::enable_if<!std::is_same<typename detail::canonical<V, Backend>::type, V>::value, typename detail::canonical<V, Backend>::type>::type
|
|
2232
|
+
canonical_value(const V& v) noexcept { return static_cast<typename detail::canonical<V, Backend>::type>(v); }
|
|
2233
|
+
template <class V>
|
|
2234
|
+
static BOOST_MP_FORCEINLINE constexpr typename std::enable_if<std::is_same<typename detail::canonical<V, Backend>::type, V>::value, const V&>::type
|
|
2235
|
+
canonical_value(const V& v) noexcept { return v; }
|
|
2236
|
+
static BOOST_MP_FORCEINLINE typename detail::canonical<std::string, Backend>::type canonical_value(const std::string& v) noexcept { return v.c_str(); }
|
|
2237
|
+
};
|
|
2238
|
+
|
|
2239
|
+
template <class Backend, expression_template_option ExpressionTemplates>
|
|
2240
|
+
inline std::ostream& operator<<(std::ostream& os, const number<Backend, ExpressionTemplates>& r)
|
|
2241
|
+
{
|
|
2242
|
+
std::streamsize d = os.precision();
|
|
2243
|
+
std::string s = r.str(d, os.flags());
|
|
2244
|
+
std::streamsize ss = os.width();
|
|
2245
|
+
if (ss > static_cast<std::streamsize>(s.size()))
|
|
2246
|
+
{
|
|
2247
|
+
char fill = os.fill();
|
|
2248
|
+
if ((os.flags() & std::ios_base::left) == std::ios_base::left)
|
|
2249
|
+
s.append(static_cast<std::string::size_type>(ss - static_cast<std::streamsize>(s.size())), fill);
|
|
2250
|
+
else
|
|
2251
|
+
s.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(ss - static_cast<std::streamsize>(s.size())), fill);
|
|
2252
|
+
}
|
|
2253
|
+
return os << s;
|
|
2254
|
+
}
|
|
2255
|
+
|
|
2256
|
+
template <class Backend, expression_template_option ExpressionTemplates>
|
|
2257
|
+
std::string to_string(const number<Backend, ExpressionTemplates>& val)
|
|
2258
|
+
{
|
|
2259
|
+
return val.str(6, std::ios_base::fixed|std::ios_base::showpoint);
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
namespace detail {
|
|
2263
|
+
|
|
2264
|
+
template <class tag, class A1, class A2, class A3, class A4>
|
|
2265
|
+
inline std::ostream& operator<<(std::ostream& os, const expression<tag, A1, A2, A3, A4>& r)
|
|
2266
|
+
{
|
|
2267
|
+
using value_type = typename expression<tag, A1, A2, A3, A4>::result_type;
|
|
2268
|
+
value_type temp(r);
|
|
2269
|
+
return os << temp;
|
|
2270
|
+
}
|
|
2271
|
+
//
|
|
2272
|
+
// What follows is the input streaming code: this is not "proper" iostream code at all
|
|
2273
|
+
// but that's fiendishly hard to write when dealing with multiple backends all
|
|
2274
|
+
// with different requirements... yes we could deligate this to the backend author...
|
|
2275
|
+
// but we really want backends to be EASY to write!
|
|
2276
|
+
// For now just pull in all the characters that could possibly form the number
|
|
2277
|
+
// and let the backend's string parser make use of it. This fixes most use cases
|
|
2278
|
+
// including CSV type formats such as those used by the Random lib.
|
|
2279
|
+
//
|
|
2280
|
+
inline std::string read_string_while(std::istream& is, std::string const& permitted_chars)
|
|
2281
|
+
{
|
|
2282
|
+
std::ios_base::iostate state = std::ios_base::goodbit;
|
|
2283
|
+
const std::istream::sentry sentry_check(is);
|
|
2284
|
+
std::string result;
|
|
2285
|
+
|
|
2286
|
+
if (sentry_check)
|
|
2287
|
+
{
|
|
2288
|
+
int c = is.rdbuf()->sgetc();
|
|
2289
|
+
|
|
2290
|
+
for (;; c = is.rdbuf()->snextc())
|
|
2291
|
+
if (std::istream::traits_type::eq_int_type(std::istream::traits_type::eof(), c))
|
|
2292
|
+
{ // end of file:
|
|
2293
|
+
state |= std::ios_base::eofbit;
|
|
2294
|
+
break;
|
|
2295
|
+
}
|
|
2296
|
+
else if (permitted_chars.find_first_of(std::istream::traits_type::to_char_type(c)) == std::string::npos)
|
|
2297
|
+
{
|
|
2298
|
+
// Invalid numeric character, stop reading:
|
|
2299
|
+
//is.rdbuf()->sputbackc(static_cast<char>(c));
|
|
2300
|
+
break;
|
|
2301
|
+
}
|
|
2302
|
+
else
|
|
2303
|
+
{
|
|
2304
|
+
result.append(1, std::istream::traits_type::to_char_type(c));
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
if (!result.size())
|
|
2309
|
+
state |= std::ios_base::failbit;
|
|
2310
|
+
is.setstate(state);
|
|
2311
|
+
return result;
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
} // namespace detail
|
|
2315
|
+
|
|
2316
|
+
template <class Backend, expression_template_option ExpressionTemplates>
|
|
2317
|
+
inline std::istream& operator>>(std::istream& is, number<Backend, ExpressionTemplates>& r)
|
|
2318
|
+
{
|
|
2319
|
+
bool hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;
|
|
2320
|
+
bool oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;
|
|
2321
|
+
std::string s;
|
|
2322
|
+
switch (boost::multiprecision::number_category<number<Backend, ExpressionTemplates> >::value)
|
|
2323
|
+
{
|
|
2324
|
+
case boost::multiprecision::number_kind_integer:
|
|
2325
|
+
if (oct_format)
|
|
2326
|
+
s = detail::read_string_while(is, "+-01234567");
|
|
2327
|
+
else if (hex_format)
|
|
2328
|
+
s = detail::read_string_while(is, "+-xXabcdefABCDEF0123456789");
|
|
2329
|
+
else
|
|
2330
|
+
s = detail::read_string_while(is, "+-0123456789");
|
|
2331
|
+
break;
|
|
2332
|
+
case boost::multiprecision::number_kind_rational:
|
|
2333
|
+
if (oct_format)
|
|
2334
|
+
s = detail::read_string_while(is, "+-01234567/");
|
|
2335
|
+
else if (hex_format)
|
|
2336
|
+
s = detail::read_string_while(is, "+-xXabcdefABCDEF0123456789/");
|
|
2337
|
+
else
|
|
2338
|
+
s = detail::read_string_while(is, "+-0123456789/");
|
|
2339
|
+
break;
|
|
2340
|
+
case boost::multiprecision::number_kind_floating_point:
|
|
2341
|
+
BOOST_IF_CONSTEXPR(std::is_same<number<Backend, ExpressionTemplates>, typename number<Backend, ExpressionTemplates>::value_type>::value)
|
|
2342
|
+
s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY");
|
|
2343
|
+
else
|
|
2344
|
+
// Interval:
|
|
2345
|
+
s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY{,}");
|
|
2346
|
+
break;
|
|
2347
|
+
case boost::multiprecision::number_kind_complex:
|
|
2348
|
+
s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY,()");
|
|
2349
|
+
break;
|
|
2350
|
+
default:
|
|
2351
|
+
is >> s;
|
|
2352
|
+
}
|
|
2353
|
+
if (s.size())
|
|
2354
|
+
{
|
|
2355
|
+
if (hex_format && (number_category<Backend>::value == number_kind_integer) && ((s[0] != '0') || (s[1] != 'x')))
|
|
2356
|
+
s.insert(s.find_first_not_of("+-"), "0x");
|
|
2357
|
+
if (oct_format && (number_category<Backend>::value == number_kind_integer) && (s[0] != '0'))
|
|
2358
|
+
s.insert(s.find_first_not_of("+-"), "0");
|
|
2359
|
+
r.assign(s);
|
|
2360
|
+
}
|
|
2361
|
+
else if (!is.fail())
|
|
2362
|
+
is.setstate(std::istream::failbit);
|
|
2363
|
+
return is;
|
|
2364
|
+
}
|
|
2365
|
+
|
|
2366
|
+
template <class Backend, expression_template_option ExpressionTemplates>
|
|
2367
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void swap(number<Backend, ExpressionTemplates>& a, number<Backend, ExpressionTemplates>& b)
|
|
2368
|
+
noexcept(noexcept(std::declval<number<Backend, ExpressionTemplates>&>() = std::declval<number<Backend, ExpressionTemplates>&>()))
|
|
2369
|
+
{
|
|
2370
|
+
a.swap(b);
|
|
2371
|
+
}
|
|
2372
|
+
//
|
|
2373
|
+
// Boost.Hash support, just call hash_value for the backend, which may or may not be supported:
|
|
2374
|
+
//
|
|
2375
|
+
template <class Backend, expression_template_option ExpressionTemplates>
|
|
2376
|
+
inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const number<Backend, ExpressionTemplates>& val)
|
|
2377
|
+
{
|
|
2378
|
+
return hash_value(val.backend());
|
|
2379
|
+
}
|
|
2380
|
+
|
|
2381
|
+
namespace detail {
|
|
2382
|
+
|
|
2383
|
+
BOOST_MP_FORCEINLINE bool istream_peek(std::istream& is, char& c, bool have_hex)
|
|
2384
|
+
{
|
|
2385
|
+
int i = is.peek();
|
|
2386
|
+
c = static_cast<char>(i);
|
|
2387
|
+
return (EOF != i) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F')));
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
} // namespace detail
|
|
2391
|
+
|
|
2392
|
+
} // namespace multiprecision
|
|
2393
|
+
|
|
2394
|
+
template <class T>
|
|
2395
|
+
class rational;
|
|
2396
|
+
|
|
2397
|
+
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
|
2398
|
+
inline std::istream& operator>>(std::istream& is, rational<multiprecision::number<Backend, ExpressionTemplates> >& r)
|
|
2399
|
+
{
|
|
2400
|
+
std::string s1;
|
|
2401
|
+
multiprecision::number<Backend, ExpressionTemplates> v1, v2;
|
|
2402
|
+
char c;
|
|
2403
|
+
bool have_hex = false;
|
|
2404
|
+
bool hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;
|
|
2405
|
+
bool oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;
|
|
2406
|
+
|
|
2407
|
+
while (multiprecision::detail::istream_peek(is, c, have_hex))
|
|
2408
|
+
{
|
|
2409
|
+
if (c == 'x' || c == 'X')
|
|
2410
|
+
have_hex = true;
|
|
2411
|
+
s1.append(1, c);
|
|
2412
|
+
is.get();
|
|
2413
|
+
}
|
|
2414
|
+
if (hex_format && ((s1[0] != '0') || (s1[1] != 'x')))
|
|
2415
|
+
s1.insert(static_cast<std::string::size_type>(0), "0x");
|
|
2416
|
+
if (oct_format && (s1[0] != '0'))
|
|
2417
|
+
s1.insert(static_cast<std::string::size_type>(0), "0");
|
|
2418
|
+
v1.assign(s1);
|
|
2419
|
+
s1.erase();
|
|
2420
|
+
if (c == '/')
|
|
2421
|
+
{
|
|
2422
|
+
is.get();
|
|
2423
|
+
while (multiprecision::detail::istream_peek(is, c, have_hex))
|
|
2424
|
+
{
|
|
2425
|
+
if (c == 'x' || c == 'X')
|
|
2426
|
+
have_hex = true;
|
|
2427
|
+
s1.append(1, c);
|
|
2428
|
+
is.get();
|
|
2429
|
+
}
|
|
2430
|
+
if (hex_format && ((s1[0] != '0') || (s1[1] != 'x')))
|
|
2431
|
+
s1.insert(static_cast<std::string::size_type>(0), "0x");
|
|
2432
|
+
if (oct_format && (s1[0] != '0'))
|
|
2433
|
+
s1.insert(static_cast<std::string::size_type>(0), "0");
|
|
2434
|
+
v2.assign(s1);
|
|
2435
|
+
}
|
|
2436
|
+
else
|
|
2437
|
+
v2 = 1;
|
|
2438
|
+
r.assign(v1, v2);
|
|
2439
|
+
return is;
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
template <class T, multiprecision::expression_template_option ExpressionTemplates>
|
|
2443
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<T, ExpressionTemplates> numerator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
|
|
2444
|
+
{
|
|
2445
|
+
return a.numerator();
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2448
|
+
template <class T, multiprecision::expression_template_option ExpressionTemplates>
|
|
2449
|
+
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<T, ExpressionTemplates> denominator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
|
|
2450
|
+
{
|
|
2451
|
+
return a.denominator();
|
|
2452
|
+
}
|
|
2453
|
+
|
|
2454
|
+
template <class T, multiprecision::expression_template_option ExpressionTemplates>
|
|
2455
|
+
inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const rational<multiprecision::number<T, ExpressionTemplates> >& val)
|
|
2456
|
+
{
|
|
2457
|
+
std::size_t result = hash_value(val.numerator());
|
|
2458
|
+
boost::multiprecision::detail::hash_combine(result, hash_value(val.denominator()));
|
|
2459
|
+
return result;
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
namespace multiprecision {
|
|
2463
|
+
|
|
2464
|
+
template <class I>
|
|
2465
|
+
struct component_type<boost::rational<I> >
|
|
2466
|
+
{
|
|
2467
|
+
using type = I;
|
|
2468
|
+
};
|
|
2469
|
+
|
|
2470
|
+
} // namespace multiprecision
|
|
2471
|
+
|
|
2472
|
+
#ifdef BOOST_MSVC
|
|
2473
|
+
#pragma warning(pop)
|
|
2474
|
+
#endif
|
|
2475
|
+
|
|
2476
|
+
} // namespace boost
|
|
2477
|
+
|
|
2478
|
+
namespace std {
|
|
2479
|
+
|
|
2480
|
+
template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2481
|
+
struct hash<boost::multiprecision::number<Backend, ExpressionTemplates> >
|
|
2482
|
+
{
|
|
2483
|
+
BOOST_MP_CXX14_CONSTEXPR std::size_t operator()(const boost::multiprecision::number<Backend, ExpressionTemplates>& val) const { return hash_value(val); }
|
|
2484
|
+
};
|
|
2485
|
+
template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2486
|
+
struct hash<boost::rational<boost::multiprecision::number<Backend, ExpressionTemplates> > >
|
|
2487
|
+
{
|
|
2488
|
+
BOOST_MP_CXX14_CONSTEXPR std::size_t operator()(const boost::rational<boost::multiprecision::number<Backend, ExpressionTemplates> >& val) const
|
|
2489
|
+
{
|
|
2490
|
+
std::size_t result = hash_value(val.numerator());
|
|
2491
|
+
boost::multiprecision::detail::hash_combine(result, hash_value(val.denominator()));
|
|
2492
|
+
return result;
|
|
2493
|
+
}
|
|
2494
|
+
};
|
|
2495
|
+
|
|
2496
|
+
} // namespace std
|
|
2497
|
+
|
|
2498
|
+
#include <boost/multiprecision/detail/ublas_interop.hpp>
|
|
2499
|
+
|
|
2500
|
+
#endif
|