mqt-core 3.3.2__cp314-cp314t-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mqt/core/__init__.py +89 -0
- mqt/core/__main__.py +55 -0
- mqt/core/_commands.py +52 -0
- mqt/core/_compat/__init__.py +11 -0
- mqt/core/_compat/typing.py +29 -0
- mqt/core/_version.py +34 -0
- mqt/core/_version.pyi +12 -0
- mqt/core/bin/mqt-core-algorithms.dll +0 -0
- mqt/core/bin/mqt-core-circuit-optimizer.dll +0 -0
- mqt/core/bin/mqt-core-dd.dll +0 -0
- mqt/core/bin/mqt-core-ds.dll +0 -0
- mqt/core/bin/mqt-core-fomac.dll +0 -0
- mqt/core/bin/mqt-core-ir.dll +0 -0
- mqt/core/bin/mqt-core-na-fomac.dll +0 -0
- mqt/core/bin/mqt-core-na.dll +0 -0
- mqt/core/bin/mqt-core-qasm.dll +0 -0
- mqt/core/bin/mqt-core-qdmi-driver.dll +0 -0
- mqt/core/bin/mqt-core-qdmi-na-device.dll +0 -0
- mqt/core/bin/mqt-core-zx.dll +0 -0
- mqt/core/dd.cp314t-win_amd64.pyd +0 -0
- mqt/core/dd.pyi +1016 -0
- mqt/core/dd_evaluation.py +368 -0
- mqt/core/fomac.cp314t-win_amd64.pyd +0 -0
- mqt/core/fomac.pyi +125 -0
- mqt/core/include/mqt-core/algorithms/BernsteinVazirani.hpp +39 -0
- mqt/core/include/mqt-core/algorithms/GHZState.hpp +18 -0
- mqt/core/include/mqt-core/algorithms/Grover.hpp +33 -0
- mqt/core/include/mqt-core/algorithms/QFT.hpp +21 -0
- mqt/core/include/mqt-core/algorithms/QPE.hpp +30 -0
- mqt/core/include/mqt-core/algorithms/RandomCliffordCircuit.hpp +22 -0
- mqt/core/include/mqt-core/algorithms/StatePreparation.hpp +43 -0
- mqt/core/include/mqt-core/algorithms/WState.hpp +18 -0
- mqt/core/include/mqt-core/algorithms/mqt_core_algorithms_export.h +43 -0
- mqt/core/include/mqt-core/boost/config/abi/borland_prefix.hpp +27 -0
- mqt/core/include/mqt-core/boost/config/abi/borland_suffix.hpp +12 -0
- mqt/core/include/mqt-core/boost/config/abi/msvc_prefix.hpp +22 -0
- mqt/core/include/mqt-core/boost/config/abi/msvc_suffix.hpp +8 -0
- mqt/core/include/mqt-core/boost/config/abi_prefix.hpp +25 -0
- mqt/core/include/mqt-core/boost/config/abi_suffix.hpp +25 -0
- mqt/core/include/mqt-core/boost/config/assert_cxx03.hpp +211 -0
- mqt/core/include/mqt-core/boost/config/assert_cxx11.hpp +212 -0
- mqt/core/include/mqt-core/boost/config/assert_cxx14.hpp +47 -0
- mqt/core/include/mqt-core/boost/config/assert_cxx17.hpp +65 -0
- mqt/core/include/mqt-core/boost/config/assert_cxx20.hpp +59 -0
- mqt/core/include/mqt-core/boost/config/assert_cxx23.hpp +41 -0
- mqt/core/include/mqt-core/boost/config/assert_cxx98.hpp +23 -0
- mqt/core/include/mqt-core/boost/config/auto_link.hpp +525 -0
- mqt/core/include/mqt-core/boost/config/compiler/borland.hpp +342 -0
- mqt/core/include/mqt-core/boost/config/compiler/clang.hpp +370 -0
- mqt/core/include/mqt-core/boost/config/compiler/clang_version.hpp +89 -0
- mqt/core/include/mqt-core/boost/config/compiler/codegear.hpp +389 -0
- mqt/core/include/mqt-core/boost/config/compiler/comeau.hpp +59 -0
- mqt/core/include/mqt-core/boost/config/compiler/common_edg.hpp +185 -0
- mqt/core/include/mqt-core/boost/config/compiler/compaq_cxx.hpp +19 -0
- mqt/core/include/mqt-core/boost/config/compiler/cray.hpp +446 -0
- mqt/core/include/mqt-core/boost/config/compiler/diab.hpp +26 -0
- mqt/core/include/mqt-core/boost/config/compiler/digitalmars.hpp +146 -0
- mqt/core/include/mqt-core/boost/config/compiler/gcc.hpp +386 -0
- mqt/core/include/mqt-core/boost/config/compiler/gcc_xml.hpp +115 -0
- mqt/core/include/mqt-core/boost/config/compiler/greenhills.hpp +28 -0
- mqt/core/include/mqt-core/boost/config/compiler/hp_acc.hpp +153 -0
- mqt/core/include/mqt-core/boost/config/compiler/intel.hpp +577 -0
- mqt/core/include/mqt-core/boost/config/compiler/kai.hpp +33 -0
- mqt/core/include/mqt-core/boost/config/compiler/metrowerks.hpp +201 -0
- mqt/core/include/mqt-core/boost/config/compiler/mpw.hpp +143 -0
- mqt/core/include/mqt-core/boost/config/compiler/nvcc.hpp +64 -0
- mqt/core/include/mqt-core/boost/config/compiler/pathscale.hpp +141 -0
- mqt/core/include/mqt-core/boost/config/compiler/pgi.hpp +23 -0
- mqt/core/include/mqt-core/boost/config/compiler/sgi_mipspro.hpp +29 -0
- mqt/core/include/mqt-core/boost/config/compiler/sunpro_cc.hpp +225 -0
- mqt/core/include/mqt-core/boost/config/compiler/vacpp.hpp +189 -0
- mqt/core/include/mqt-core/boost/config/compiler/visualc.hpp +398 -0
- mqt/core/include/mqt-core/boost/config/compiler/xlcpp.hpp +303 -0
- mqt/core/include/mqt-core/boost/config/compiler/xlcpp_zos.hpp +174 -0
- mqt/core/include/mqt-core/boost/config/detail/cxx_composite.hpp +218 -0
- mqt/core/include/mqt-core/boost/config/detail/posix_features.hpp +95 -0
- mqt/core/include/mqt-core/boost/config/detail/select_compiler_config.hpp +157 -0
- mqt/core/include/mqt-core/boost/config/detail/select_platform_config.hpp +147 -0
- mqt/core/include/mqt-core/boost/config/detail/select_stdlib_config.hpp +121 -0
- mqt/core/include/mqt-core/boost/config/detail/suffix.hpp +1334 -0
- mqt/core/include/mqt-core/boost/config/header_deprecated.hpp +26 -0
- mqt/core/include/mqt-core/boost/config/helper_macros.hpp +37 -0
- mqt/core/include/mqt-core/boost/config/no_tr1/cmath.hpp +28 -0
- mqt/core/include/mqt-core/boost/config/no_tr1/complex.hpp +28 -0
- mqt/core/include/mqt-core/boost/config/no_tr1/functional.hpp +28 -0
- mqt/core/include/mqt-core/boost/config/no_tr1/memory.hpp +28 -0
- mqt/core/include/mqt-core/boost/config/no_tr1/utility.hpp +28 -0
- mqt/core/include/mqt-core/boost/config/platform/aix.hpp +33 -0
- mqt/core/include/mqt-core/boost/config/platform/amigaos.hpp +15 -0
- mqt/core/include/mqt-core/boost/config/platform/beos.hpp +26 -0
- mqt/core/include/mqt-core/boost/config/platform/bsd.hpp +83 -0
- mqt/core/include/mqt-core/boost/config/platform/cloudabi.hpp +18 -0
- mqt/core/include/mqt-core/boost/config/platform/cray.hpp +18 -0
- mqt/core/include/mqt-core/boost/config/platform/cygwin.hpp +71 -0
- mqt/core/include/mqt-core/boost/config/platform/haiku.hpp +31 -0
- mqt/core/include/mqt-core/boost/config/platform/hpux.hpp +87 -0
- mqt/core/include/mqt-core/boost/config/platform/irix.hpp +31 -0
- mqt/core/include/mqt-core/boost/config/platform/linux.hpp +106 -0
- mqt/core/include/mqt-core/boost/config/platform/macos.hpp +87 -0
- mqt/core/include/mqt-core/boost/config/platform/qnxnto.hpp +31 -0
- mqt/core/include/mqt-core/boost/config/platform/solaris.hpp +31 -0
- mqt/core/include/mqt-core/boost/config/platform/symbian.hpp +97 -0
- mqt/core/include/mqt-core/boost/config/platform/vms.hpp +25 -0
- mqt/core/include/mqt-core/boost/config/platform/vxworks.hpp +422 -0
- mqt/core/include/mqt-core/boost/config/platform/wasm.hpp +23 -0
- mqt/core/include/mqt-core/boost/config/platform/win32.hpp +90 -0
- mqt/core/include/mqt-core/boost/config/platform/zos.hpp +32 -0
- mqt/core/include/mqt-core/boost/config/pragma_message.hpp +31 -0
- mqt/core/include/mqt-core/boost/config/requires_threads.hpp +92 -0
- mqt/core/include/mqt-core/boost/config/stdlib/dinkumware.hpp +324 -0
- mqt/core/include/mqt-core/boost/config/stdlib/libcomo.hpp +93 -0
- mqt/core/include/mqt-core/boost/config/stdlib/libcpp.hpp +180 -0
- mqt/core/include/mqt-core/boost/config/stdlib/libstdcpp3.hpp +482 -0
- mqt/core/include/mqt-core/boost/config/stdlib/modena.hpp +79 -0
- mqt/core/include/mqt-core/boost/config/stdlib/msl.hpp +98 -0
- mqt/core/include/mqt-core/boost/config/stdlib/roguewave.hpp +208 -0
- mqt/core/include/mqt-core/boost/config/stdlib/sgi.hpp +168 -0
- mqt/core/include/mqt-core/boost/config/stdlib/stlport.hpp +258 -0
- mqt/core/include/mqt-core/boost/config/stdlib/vacpp.hpp +74 -0
- mqt/core/include/mqt-core/boost/config/stdlib/xlcpp_zos.hpp +61 -0
- mqt/core/include/mqt-core/boost/config/user.hpp +133 -0
- mqt/core/include/mqt-core/boost/config/warning_disable.hpp +47 -0
- mqt/core/include/mqt-core/boost/config/workaround.hpp +305 -0
- mqt/core/include/mqt-core/boost/config.hpp +67 -0
- mqt/core/include/mqt-core/boost/cstdint.hpp +556 -0
- mqt/core/include/mqt-core/boost/cxx11_char_types.hpp +70 -0
- mqt/core/include/mqt-core/boost/detail/workaround.hpp +10 -0
- mqt/core/include/mqt-core/boost/limits.hpp +146 -0
- mqt/core/include/mqt-core/boost/multiprecision/complex128.hpp +24 -0
- mqt/core/include/mqt-core/boost/multiprecision/complex_adaptor.hpp +1046 -0
- mqt/core/include/mqt-core/boost/multiprecision/concepts/mp_number_archetypes.hpp +257 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_bin_float/io.hpp +698 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_bin_float/transcendental.hpp +157 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_bin_float.hpp +2297 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_complex.hpp +12 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_dec_float.hpp +3690 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/add.hpp +368 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/add_unsigned.hpp +387 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/bitwise.hpp +889 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/checked.hpp +178 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/comparison.hpp +374 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/cpp_int_config.hpp +161 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/divide.hpp +703 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/import_export.hpp +248 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/intel_intrinsics.hpp +138 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/limits.hpp +282 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/literals.hpp +295 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/misc.hpp +1457 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/multiply.hpp +848 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/serialize.hpp +211 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int/value_pack.hpp +42 -0
- mqt/core/include/mqt-core/boost/multiprecision/cpp_int.hpp +2360 -0
- mqt/core/include/mqt-core/boost/multiprecision/debug_adaptor.hpp +760 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/assert.hpp +29 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/atomic.hpp +62 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/bitscan.hpp +317 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/check_cpp11_config.hpp +64 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/constexpr.hpp +88 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/default_ops.hpp +4052 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/digits.hpp +49 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/dynamic_array.hpp +44 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/empty_value.hpp +87 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/endian.hpp +35 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/et_ops.hpp +1831 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/float128_functions.hpp +95 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/float_string_cvt.hpp +333 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/fpclassify.hpp +101 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/functions/constants.hpp +288 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/functions/pow.hpp +905 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/functions/trig.hpp +1058 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/functions/trunc.hpp +82 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/generic_interconvert.hpp +687 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/hash.hpp +56 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/integer_ops.hpp +474 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/itos.hpp +39 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/min_max.hpp +106 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/no_et_ops.hpp +661 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/no_exceptions_support.hpp +55 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/number_base.hpp +1656 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/number_compare.hpp +848 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/precision.hpp +313 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/rebind.hpp +19 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/standalone_config.hpp +148 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/static_array.hpp +42 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/string_helpers.hpp +48 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/tables.hpp +80 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/ublas_interop.hpp +75 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/uniform_int_distribution.hpp +212 -0
- mqt/core/include/mqt-core/boost/multiprecision/detail/utype_helper.hpp +374 -0
- mqt/core/include/mqt-core/boost/multiprecision/eigen.hpp +248 -0
- mqt/core/include/mqt-core/boost/multiprecision/float128.hpp +920 -0
- mqt/core/include/mqt-core/boost/multiprecision/fwd.hpp +268 -0
- mqt/core/include/mqt-core/boost/multiprecision/gmp.hpp +4060 -0
- mqt/core/include/mqt-core/boost/multiprecision/integer.hpp +363 -0
- mqt/core/include/mqt-core/boost/multiprecision/logged_adaptor.hpp +834 -0
- mqt/core/include/mqt-core/boost/multiprecision/miller_rabin.hpp +221 -0
- mqt/core/include/mqt-core/boost/multiprecision/mpc.hpp +1721 -0
- mqt/core/include/mqt-core/boost/multiprecision/mpfi.hpp +2559 -0
- mqt/core/include/mqt-core/boost/multiprecision/mpfr.hpp +3644 -0
- mqt/core/include/mqt-core/boost/multiprecision/number.hpp +2500 -0
- mqt/core/include/mqt-core/boost/multiprecision/random.hpp +23 -0
- mqt/core/include/mqt-core/boost/multiprecision/rational_adaptor.hpp +1289 -0
- mqt/core/include/mqt-core/boost/multiprecision/tommath.hpp +1034 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/explicit_conversion.hpp +67 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/extract_exponent_type.hpp +28 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/is_backend.hpp +91 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/is_byte_container.hpp +51 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/is_complex.hpp +22 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/is_convertible_arithmetic.hpp +51 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/is_restricted_conversion.hpp +47 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/is_variable_precision.hpp +25 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/max_digits10.hpp +79 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/std_integer_traits.hpp +90 -0
- mqt/core/include/mqt-core/boost/multiprecision/traits/transcendental_reduction_type.hpp +21 -0
- mqt/core/include/mqt-core/boost/version.hpp +32 -0
- mqt/core/include/mqt-core/circuit_optimizer/CircuitOptimizer.hpp +119 -0
- mqt/core/include/mqt-core/circuit_optimizer/mqt_core_circuit_optimizer_export.h +43 -0
- mqt/core/include/mqt-core/datastructures/DirectedAcyclicGraph.hpp +117 -0
- mqt/core/include/mqt-core/datastructures/DirectedGraph.hpp +158 -0
- mqt/core/include/mqt-core/datastructures/DisjointSet.hpp +50 -0
- mqt/core/include/mqt-core/datastructures/Layer.hpp +172 -0
- mqt/core/include/mqt-core/datastructures/SymmetricMatrix.hpp +57 -0
- mqt/core/include/mqt-core/datastructures/UndirectedGraph.hpp +227 -0
- mqt/core/include/mqt-core/datastructures/mqt_core_ds_export.h +43 -0
- mqt/core/include/mqt-core/dd/Approximation.hpp +45 -0
- mqt/core/include/mqt-core/dd/CachedEdge.hpp +174 -0
- mqt/core/include/mqt-core/dd/Complex.hpp +165 -0
- mqt/core/include/mqt-core/dd/ComplexNumbers.hpp +150 -0
- mqt/core/include/mqt-core/dd/ComplexValue.hpp +184 -0
- mqt/core/include/mqt-core/dd/ComputeTable.hpp +183 -0
- mqt/core/include/mqt-core/dd/DDDefinitions.hpp +139 -0
- mqt/core/include/mqt-core/dd/DDpackageConfig.hpp +104 -0
- mqt/core/include/mqt-core/dd/DensityNoiseTable.hpp +114 -0
- mqt/core/include/mqt-core/dd/Edge.hpp +416 -0
- mqt/core/include/mqt-core/dd/Export.hpp +438 -0
- mqt/core/include/mqt-core/dd/FunctionalityConstruction.hpp +75 -0
- mqt/core/include/mqt-core/dd/GateMatrixDefinitions.hpp +43 -0
- mqt/core/include/mqt-core/dd/LinkedListBase.hpp +45 -0
- mqt/core/include/mqt-core/dd/MemoryManager.hpp +193 -0
- mqt/core/include/mqt-core/dd/Node.hpp +223 -0
- mqt/core/include/mqt-core/dd/NoiseFunctionality.hpp +144 -0
- mqt/core/include/mqt-core/dd/Operations.hpp +306 -0
- mqt/core/include/mqt-core/dd/Package.hpp +2036 -0
- mqt/core/include/mqt-core/dd/Package_fwd.hpp +22 -0
- mqt/core/include/mqt-core/dd/RealNumber.hpp +255 -0
- mqt/core/include/mqt-core/dd/RealNumberUniqueTable.hpp +217 -0
- mqt/core/include/mqt-core/dd/Simulation.hpp +98 -0
- mqt/core/include/mqt-core/dd/StateGeneration.hpp +143 -0
- mqt/core/include/mqt-core/dd/StochasticNoiseOperationTable.hpp +88 -0
- mqt/core/include/mqt-core/dd/UnaryComputeTable.hpp +121 -0
- mqt/core/include/mqt-core/dd/UniqueTable.hpp +243 -0
- mqt/core/include/mqt-core/dd/mqt_core_dd_export.h +43 -0
- mqt/core/include/mqt-core/dd/statistics/MemoryManagerStatistics.hpp +84 -0
- mqt/core/include/mqt-core/dd/statistics/PackageStatistics.hpp +55 -0
- mqt/core/include/mqt-core/dd/statistics/Statistics.hpp +48 -0
- mqt/core/include/mqt-core/dd/statistics/TableStatistics.hpp +79 -0
- mqt/core/include/mqt-core/dd/statistics/UniqueTableStatistics.hpp +31 -0
- mqt/core/include/mqt-core/fomac/FoMaC.hpp +568 -0
- mqt/core/include/mqt-core/ir/Definitions.hpp +108 -0
- mqt/core/include/mqt-core/ir/Permutation.hpp +213 -0
- mqt/core/include/mqt-core/ir/QuantumComputation.hpp +596 -0
- mqt/core/include/mqt-core/ir/Register.hpp +125 -0
- mqt/core/include/mqt-core/ir/mqt_core_ir_export.h +43 -0
- mqt/core/include/mqt-core/ir/operations/AodOperation.hpp +92 -0
- mqt/core/include/mqt-core/ir/operations/CompoundOperation.hpp +212 -0
- mqt/core/include/mqt-core/ir/operations/Control.hpp +142 -0
- mqt/core/include/mqt-core/ir/operations/Expression.hpp +847 -0
- mqt/core/include/mqt-core/ir/operations/IfElseOperation.hpp +169 -0
- mqt/core/include/mqt-core/ir/operations/NonUnitaryOperation.hpp +118 -0
- mqt/core/include/mqt-core/ir/operations/OpType.hpp +120 -0
- mqt/core/include/mqt-core/ir/operations/OpType.inc +76 -0
- mqt/core/include/mqt-core/ir/operations/Operation.hpp +247 -0
- mqt/core/include/mqt-core/ir/operations/StandardOperation.hpp +140 -0
- mqt/core/include/mqt-core/ir/operations/SymbolicOperation.hpp +144 -0
- mqt/core/include/mqt-core/mqt_na_qdmi/device.h +602 -0
- mqt/core/include/mqt-core/mqt_na_qdmi/types.h +78 -0
- mqt/core/include/mqt-core/na/NAComputation.hpp +185 -0
- mqt/core/include/mqt-core/na/device/Device.hpp +410 -0
- mqt/core/include/mqt-core/na/device/DeviceMemberInitializers.hpp +724 -0
- mqt/core/include/mqt-core/na/device/Generator.hpp +447 -0
- mqt/core/include/mqt-core/na/entities/Atom.hpp +62 -0
- mqt/core/include/mqt-core/na/entities/Location.hpp +154 -0
- mqt/core/include/mqt-core/na/entities/Zone.hpp +95 -0
- mqt/core/include/mqt-core/na/fomac/Device.hpp +169 -0
- mqt/core/include/mqt-core/na/mqt_core_na_export.h +43 -0
- mqt/core/include/mqt-core/na/operations/GlobalCZOp.hpp +38 -0
- mqt/core/include/mqt-core/na/operations/GlobalOp.hpp +58 -0
- mqt/core/include/mqt-core/na/operations/GlobalRYOp.hpp +42 -0
- mqt/core/include/mqt-core/na/operations/LoadOp.hpp +89 -0
- mqt/core/include/mqt-core/na/operations/LocalOp.hpp +56 -0
- mqt/core/include/mqt-core/na/operations/LocalRZOp.hpp +42 -0
- mqt/core/include/mqt-core/na/operations/LocalUOp.hpp +49 -0
- mqt/core/include/mqt-core/na/operations/MoveOp.hpp +66 -0
- mqt/core/include/mqt-core/na/operations/Op.hpp +62 -0
- mqt/core/include/mqt-core/na/operations/ShuttlingOp.hpp +51 -0
- mqt/core/include/mqt-core/na/operations/StoreOp.hpp +87 -0
- mqt/core/include/mqt-core/qasm3/Exception.hpp +85 -0
- mqt/core/include/mqt-core/qasm3/Gate.hpp +65 -0
- mqt/core/include/mqt-core/qasm3/Importer.hpp +192 -0
- mqt/core/include/mqt-core/qasm3/InstVisitor.hpp +145 -0
- mqt/core/include/mqt-core/qasm3/NestedEnvironment.hpp +41 -0
- mqt/core/include/mqt-core/qasm3/Parser.hpp +170 -0
- mqt/core/include/mqt-core/qasm3/Scanner.hpp +73 -0
- mqt/core/include/mqt-core/qasm3/Statement.hpp +486 -0
- mqt/core/include/mqt-core/qasm3/Statement_fwd.hpp +39 -0
- mqt/core/include/mqt-core/qasm3/StdGates.hpp +232 -0
- mqt/core/include/mqt-core/qasm3/Token.hpp +198 -0
- mqt/core/include/mqt-core/qasm3/Types.hpp +238 -0
- mqt/core/include/mqt-core/qasm3/Types_fwd.hpp +22 -0
- mqt/core/include/mqt-core/qasm3/mqt_core_qasm_export.h +43 -0
- mqt/core/include/mqt-core/qasm3/passes/CompilerPass.hpp +22 -0
- mqt/core/include/mqt-core/qasm3/passes/ConstEvalPass.hpp +102 -0
- mqt/core/include/mqt-core/qasm3/passes/TypeCheckPass.hpp +124 -0
- mqt/core/include/mqt-core/qdmi/Driver.hpp +431 -0
- mqt/core/include/mqt-core/zx/FunctionalityConstruction.hpp +125 -0
- mqt/core/include/mqt-core/zx/Rational.hpp +318 -0
- mqt/core/include/mqt-core/zx/Rules.hpp +132 -0
- mqt/core/include/mqt-core/zx/Simplify.hpp +182 -0
- mqt/core/include/mqt-core/zx/Utils.hpp +212 -0
- mqt/core/include/mqt-core/zx/ZXDefinitions.hpp +93 -0
- mqt/core/include/mqt-core/zx/ZXDiagram.hpp +480 -0
- mqt/core/include/mqt-core/zx/mqt_core_zx_export.h +43 -0
- mqt/core/include/nlohmann/adl_serializer.hpp +55 -0
- mqt/core/include/nlohmann/byte_container_with_subtype.hpp +103 -0
- mqt/core/include/nlohmann/detail/abi_macros.hpp +111 -0
- mqt/core/include/nlohmann/detail/conversions/from_json.hpp +577 -0
- mqt/core/include/nlohmann/detail/conversions/to_chars.hpp +1118 -0
- mqt/core/include/nlohmann/detail/conversions/to_json.hpp +479 -0
- mqt/core/include/nlohmann/detail/exceptions.hpp +291 -0
- mqt/core/include/nlohmann/detail/hash.hpp +129 -0
- mqt/core/include/nlohmann/detail/input/binary_reader.hpp +3068 -0
- mqt/core/include/nlohmann/detail/input/input_adapters.hpp +549 -0
- mqt/core/include/nlohmann/detail/input/json_sax.hpp +986 -0
- mqt/core/include/nlohmann/detail/input/lexer.hpp +1643 -0
- mqt/core/include/nlohmann/detail/input/parser.hpp +519 -0
- mqt/core/include/nlohmann/detail/input/position_t.hpp +37 -0
- mqt/core/include/nlohmann/detail/iterators/internal_iterator.hpp +35 -0
- mqt/core/include/nlohmann/detail/iterators/iter_impl.hpp +760 -0
- mqt/core/include/nlohmann/detail/iterators/iteration_proxy.hpp +235 -0
- mqt/core/include/nlohmann/detail/iterators/iterator_traits.hpp +61 -0
- mqt/core/include/nlohmann/detail/iterators/json_reverse_iterator.hpp +130 -0
- mqt/core/include/nlohmann/detail/iterators/primitive_iterator.hpp +132 -0
- mqt/core/include/nlohmann/detail/json_custom_base_class.hpp +39 -0
- mqt/core/include/nlohmann/detail/json_pointer.hpp +988 -0
- mqt/core/include/nlohmann/detail/json_ref.hpp +78 -0
- mqt/core/include/nlohmann/detail/macro_scope.hpp +595 -0
- mqt/core/include/nlohmann/detail/macro_unscope.hpp +46 -0
- mqt/core/include/nlohmann/detail/meta/call_std/begin.hpp +17 -0
- mqt/core/include/nlohmann/detail/meta/call_std/end.hpp +17 -0
- mqt/core/include/nlohmann/detail/meta/cpp_future.hpp +171 -0
- mqt/core/include/nlohmann/detail/meta/detected.hpp +70 -0
- mqt/core/include/nlohmann/detail/meta/identity_tag.hpp +21 -0
- mqt/core/include/nlohmann/detail/meta/is_sax.hpp +159 -0
- mqt/core/include/nlohmann/detail/meta/std_fs.hpp +29 -0
- mqt/core/include/nlohmann/detail/meta/type_traits.hpp +795 -0
- mqt/core/include/nlohmann/detail/meta/void_t.hpp +24 -0
- mqt/core/include/nlohmann/detail/output/binary_writer.hpp +1850 -0
- mqt/core/include/nlohmann/detail/output/output_adapters.hpp +147 -0
- mqt/core/include/nlohmann/detail/output/serializer.hpp +988 -0
- mqt/core/include/nlohmann/detail/string_concat.hpp +146 -0
- mqt/core/include/nlohmann/detail/string_escape.hpp +72 -0
- mqt/core/include/nlohmann/detail/string_utils.hpp +37 -0
- mqt/core/include/nlohmann/detail/value_t.hpp +118 -0
- mqt/core/include/nlohmann/json.hpp +5306 -0
- mqt/core/include/nlohmann/json_fwd.hpp +75 -0
- mqt/core/include/nlohmann/ordered_map.hpp +359 -0
- mqt/core/include/nlohmann/thirdparty/hedley/hedley.hpp +2045 -0
- mqt/core/include/nlohmann/thirdparty/hedley/hedley_undef.hpp +158 -0
- mqt/core/include/qdmi/qdmi/client.h +990 -0
- mqt/core/include/qdmi/qdmi/constants.h +1139 -0
- mqt/core/include/qdmi/qdmi/device.h +602 -0
- mqt/core/include/qdmi/qdmi/types.h +78 -0
- mqt/core/include/spdlog/async.h +99 -0
- mqt/core/include/spdlog/async_logger-inl.h +84 -0
- mqt/core/include/spdlog/async_logger.h +74 -0
- mqt/core/include/spdlog/cfg/argv.h +40 -0
- mqt/core/include/spdlog/cfg/env.h +36 -0
- mqt/core/include/spdlog/cfg/helpers-inl.h +107 -0
- mqt/core/include/spdlog/cfg/helpers.h +29 -0
- mqt/core/include/spdlog/common-inl.h +68 -0
- mqt/core/include/spdlog/common.h +406 -0
- mqt/core/include/spdlog/details/backtracer-inl.h +63 -0
- mqt/core/include/spdlog/details/backtracer.h +45 -0
- mqt/core/include/spdlog/details/circular_q.h +115 -0
- mqt/core/include/spdlog/details/console_globals.h +28 -0
- mqt/core/include/spdlog/details/file_helper-inl.h +153 -0
- mqt/core/include/spdlog/details/file_helper.h +61 -0
- mqt/core/include/spdlog/details/fmt_helper.h +141 -0
- mqt/core/include/spdlog/details/log_msg-inl.h +44 -0
- mqt/core/include/spdlog/details/log_msg.h +40 -0
- mqt/core/include/spdlog/details/log_msg_buffer-inl.h +54 -0
- mqt/core/include/spdlog/details/log_msg_buffer.h +32 -0
- mqt/core/include/spdlog/details/mpmc_blocking_q.h +177 -0
- mqt/core/include/spdlog/details/null_mutex.h +35 -0
- mqt/core/include/spdlog/details/os-inl.h +606 -0
- mqt/core/include/spdlog/details/os.h +127 -0
- mqt/core/include/spdlog/details/periodic_worker-inl.h +26 -0
- mqt/core/include/spdlog/details/periodic_worker.h +58 -0
- mqt/core/include/spdlog/details/registry-inl.h +270 -0
- mqt/core/include/spdlog/details/registry.h +131 -0
- mqt/core/include/spdlog/details/synchronous_factory.h +22 -0
- mqt/core/include/spdlog/details/tcp_client-windows.h +135 -0
- mqt/core/include/spdlog/details/tcp_client.h +127 -0
- mqt/core/include/spdlog/details/thread_pool-inl.h +126 -0
- mqt/core/include/spdlog/details/thread_pool.h +117 -0
- mqt/core/include/spdlog/details/udp_client-windows.h +98 -0
- mqt/core/include/spdlog/details/udp_client.h +81 -0
- mqt/core/include/spdlog/details/windows_include.h +11 -0
- mqt/core/include/spdlog/fmt/bin_to_hex.h +224 -0
- mqt/core/include/spdlog/fmt/bundled/args.h +220 -0
- mqt/core/include/spdlog/fmt/bundled/base.h +2989 -0
- mqt/core/include/spdlog/fmt/bundled/chrono.h +2330 -0
- mqt/core/include/spdlog/fmt/bundled/color.h +637 -0
- mqt/core/include/spdlog/fmt/bundled/compile.h +539 -0
- mqt/core/include/spdlog/fmt/bundled/core.h +5 -0
- mqt/core/include/spdlog/fmt/bundled/fmt.license.rst +27 -0
- mqt/core/include/spdlog/fmt/bundled/format-inl.h +1948 -0
- mqt/core/include/spdlog/fmt/bundled/format.h +4244 -0
- mqt/core/include/spdlog/fmt/bundled/os.h +427 -0
- mqt/core/include/spdlog/fmt/bundled/ostream.h +167 -0
- mqt/core/include/spdlog/fmt/bundled/printf.h +633 -0
- mqt/core/include/spdlog/fmt/bundled/ranges.h +850 -0
- mqt/core/include/spdlog/fmt/bundled/std.h +728 -0
- mqt/core/include/spdlog/fmt/bundled/xchar.h +369 -0
- mqt/core/include/spdlog/fmt/chrono.h +23 -0
- mqt/core/include/spdlog/fmt/compile.h +23 -0
- mqt/core/include/spdlog/fmt/fmt.h +30 -0
- mqt/core/include/spdlog/fmt/ostr.h +23 -0
- mqt/core/include/spdlog/fmt/ranges.h +23 -0
- mqt/core/include/spdlog/fmt/std.h +24 -0
- mqt/core/include/spdlog/fmt/xchar.h +23 -0
- mqt/core/include/spdlog/formatter.h +17 -0
- mqt/core/include/spdlog/fwd.h +18 -0
- mqt/core/include/spdlog/logger-inl.h +198 -0
- mqt/core/include/spdlog/logger.h +379 -0
- mqt/core/include/spdlog/mdc.h +52 -0
- mqt/core/include/spdlog/pattern_formatter-inl.h +1340 -0
- mqt/core/include/spdlog/pattern_formatter.h +118 -0
- mqt/core/include/spdlog/sinks/android_sink.h +137 -0
- mqt/core/include/spdlog/sinks/ansicolor_sink-inl.h +142 -0
- mqt/core/include/spdlog/sinks/ansicolor_sink.h +116 -0
- mqt/core/include/spdlog/sinks/base_sink-inl.h +59 -0
- mqt/core/include/spdlog/sinks/base_sink.h +51 -0
- mqt/core/include/spdlog/sinks/basic_file_sink-inl.h +48 -0
- mqt/core/include/spdlog/sinks/basic_file_sink.h +66 -0
- mqt/core/include/spdlog/sinks/callback_sink.h +56 -0
- mqt/core/include/spdlog/sinks/daily_file_sink.h +254 -0
- mqt/core/include/spdlog/sinks/dist_sink.h +81 -0
- mqt/core/include/spdlog/sinks/dup_filter_sink.h +91 -0
- mqt/core/include/spdlog/sinks/hourly_file_sink.h +193 -0
- mqt/core/include/spdlog/sinks/kafka_sink.h +119 -0
- mqt/core/include/spdlog/sinks/mongo_sink.h +108 -0
- mqt/core/include/spdlog/sinks/msvc_sink.h +68 -0
- mqt/core/include/spdlog/sinks/null_sink.h +41 -0
- mqt/core/include/spdlog/sinks/ostream_sink.h +43 -0
- mqt/core/include/spdlog/sinks/qt_sinks.h +304 -0
- mqt/core/include/spdlog/sinks/ringbuffer_sink.h +67 -0
- mqt/core/include/spdlog/sinks/rotating_file_sink-inl.h +179 -0
- mqt/core/include/spdlog/sinks/rotating_file_sink.h +93 -0
- mqt/core/include/spdlog/sinks/sink-inl.h +22 -0
- mqt/core/include/spdlog/sinks/sink.h +34 -0
- mqt/core/include/spdlog/sinks/stdout_color_sinks-inl.h +38 -0
- mqt/core/include/spdlog/sinks/stdout_color_sinks.h +49 -0
- mqt/core/include/spdlog/sinks/stdout_sinks-inl.h +127 -0
- mqt/core/include/spdlog/sinks/stdout_sinks.h +84 -0
- mqt/core/include/spdlog/sinks/syslog_sink.h +104 -0
- mqt/core/include/spdlog/sinks/systemd_sink.h +121 -0
- mqt/core/include/spdlog/sinks/tcp_sink.h +75 -0
- mqt/core/include/spdlog/sinks/udp_sink.h +69 -0
- mqt/core/include/spdlog/sinks/win_eventlog_sink.h +260 -0
- mqt/core/include/spdlog/sinks/wincolor_sink-inl.h +172 -0
- mqt/core/include/spdlog/sinks/wincolor_sink.h +82 -0
- mqt/core/include/spdlog/spdlog-inl.h +96 -0
- mqt/core/include/spdlog/spdlog.h +357 -0
- mqt/core/include/spdlog/stopwatch.h +66 -0
- mqt/core/include/spdlog/tweakme.h +148 -0
- mqt/core/include/spdlog/version.h +11 -0
- mqt/core/ir/__init__.pyi +2078 -0
- mqt/core/ir/operations.pyi +1011 -0
- mqt/core/ir/registers.pyi +91 -0
- mqt/core/ir/symbolic.pyi +177 -0
- mqt/core/ir.cp314t-win_amd64.pyd +0 -0
- mqt/core/lib/mqt-core-algorithms.lib +0 -0
- mqt/core/lib/mqt-core-circuit-optimizer.lib +0 -0
- mqt/core/lib/mqt-core-dd.lib +0 -0
- mqt/core/lib/mqt-core-ds.lib +0 -0
- mqt/core/lib/mqt-core-fomac.lib +0 -0
- mqt/core/lib/mqt-core-ir.lib +0 -0
- mqt/core/lib/mqt-core-na-fomac.lib +0 -0
- mqt/core/lib/mqt-core-na.lib +0 -0
- mqt/core/lib/mqt-core-qasm.lib +0 -0
- mqt/core/lib/mqt-core-qdmi-driver.lib +0 -0
- mqt/core/lib/mqt-core-qdmi-na-device-gen.lib +0 -0
- mqt/core/lib/mqt-core-qdmi-na-device.lib +0 -0
- mqt/core/lib/mqt-core-zx.lib +0 -0
- mqt/core/lib/pkgconfig/spdlog.pc +13 -0
- mqt/core/lib/spdlog.lib +0 -0
- mqt/core/na/__init__.py +12 -0
- mqt/core/na/fomac.cp314t-win_amd64.pyd +0 -0
- mqt/core/na/fomac.pyi +117 -0
- mqt/core/nlohmann_json.natvis +278 -0
- mqt/core/plugins/__init__.py +9 -0
- mqt/core/plugins/qiskit/__init__.py +19 -0
- mqt/core/plugins/qiskit/mqt_to_qiskit.py +420 -0
- mqt/core/plugins/qiskit/qiskit_to_mqt.py +562 -0
- mqt/core/py.typed +2 -0
- mqt/core/share/cmake/mqt-core/AddMQTPythonBinding.cmake +55 -0
- mqt/core/share/cmake/mqt-core/Cache.cmake +33 -0
- mqt/core/share/cmake/mqt-core/FindGMP.cmake +103 -0
- mqt/core/share/cmake/mqt-core/PackageAddTest.cmake +46 -0
- mqt/core/share/cmake/mqt-core/PreventInSourceBuilds.cmake +25 -0
- mqt/core/share/cmake/mqt-core/StandardProjectSettings.cmake +87 -0
- mqt/core/share/cmake/mqt-core/mqt-core-config-version.cmake +85 -0
- mqt/core/share/cmake/mqt-core/mqt-core-config.cmake +52 -0
- mqt/core/share/cmake/mqt-core/mqt-core-targets-release.cmake +141 -0
- mqt/core/share/cmake/mqt-core/mqt-core-targets.cmake +445 -0
- mqt/core/share/cmake/nlohmann_json/nlohmann_jsonConfig.cmake +15 -0
- mqt/core/share/cmake/nlohmann_json/nlohmann_jsonConfigVersion.cmake +20 -0
- mqt/core/share/cmake/nlohmann_json/nlohmann_jsonTargets.cmake +110 -0
- mqt/core/share/cmake/qdmi/Cache.cmake +44 -0
- mqt/core/share/cmake/qdmi/PrefixHandling.cmake +78 -0
- mqt/core/share/cmake/qdmi/prefix_defs.txt +26 -0
- mqt/core/share/cmake/qdmi/qdmi-config-version.cmake +85 -0
- mqt/core/share/cmake/qdmi/qdmi-config.cmake +42 -0
- mqt/core/share/cmake/qdmi/qdmi-targets.cmake +129 -0
- mqt/core/share/cmake/spdlog/spdlogConfig.cmake +44 -0
- mqt/core/share/cmake/spdlog/spdlogConfigTargets-release.cmake +19 -0
- mqt/core/share/cmake/spdlog/spdlogConfigTargets.cmake +121 -0
- mqt/core/share/cmake/spdlog/spdlogConfigVersion.cmake +65 -0
- mqt/core/share/pkgconfig/nlohmann_json.pc +7 -0
- mqt_core-3.3.2.dist-info/DELVEWHEEL +2 -0
- mqt_core-3.3.2.dist-info/METADATA +210 -0
- mqt_core-3.3.2.dist-info/RECORD +537 -0
- mqt_core-3.3.2.dist-info/WHEEL +5 -0
- mqt_core-3.3.2.dist-info/entry_points.txt +4 -0
- mqt_core-3.3.2.dist-info/licenses/LICENSE.md +22 -0
- mqt_core.libs/msvcp140.dll +0 -0
|
@@ -0,0 +1,1457 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright 2012-2020 John Maddock.
|
|
3
|
+
// Copyright 2020 Madhur Chauhan.
|
|
4
|
+
// Copyright 2021 Matt Borland.
|
|
5
|
+
// Distributed under the Boost Software License, Version 1.0.
|
|
6
|
+
// (See accompanying file LICENSE_1_0.txt or copy at
|
|
7
|
+
// https://www.boost.org/LICENSE_1_0.txt)
|
|
8
|
+
//
|
|
9
|
+
// Comparison operators for cpp_int_backend:
|
|
10
|
+
//
|
|
11
|
+
#ifndef BOOST_MP_CPP_INT_MISC_HPP
|
|
12
|
+
#define BOOST_MP_CPP_INT_MISC_HPP
|
|
13
|
+
|
|
14
|
+
#include <boost/multiprecision/detail/standalone_config.hpp>
|
|
15
|
+
#include <boost/multiprecision/detail/number_base.hpp>
|
|
16
|
+
#include <boost/multiprecision/cpp_int/cpp_int_config.hpp>
|
|
17
|
+
#include <boost/multiprecision/detail/float128_functions.hpp>
|
|
18
|
+
#include <boost/multiprecision/detail/assert.hpp>
|
|
19
|
+
#include <boost/multiprecision/detail/constexpr.hpp>
|
|
20
|
+
#include <boost/multiprecision/detail/bitscan.hpp> // lsb etc
|
|
21
|
+
#include <boost/multiprecision/detail/hash.hpp>
|
|
22
|
+
#include <boost/multiprecision/detail/no_exceptions_support.hpp>
|
|
23
|
+
#include <numeric> // std::gcd
|
|
24
|
+
#include <type_traits>
|
|
25
|
+
#include <stdexcept>
|
|
26
|
+
#include <cmath>
|
|
27
|
+
|
|
28
|
+
#ifndef BOOST_MP_STANDALONE
|
|
29
|
+
#include <boost/integer/common_factor_rt.hpp>
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
#ifdef BOOST_MP_MATH_AVAILABLE
|
|
33
|
+
#include <boost/math/special_functions/next.hpp>
|
|
34
|
+
#endif
|
|
35
|
+
|
|
36
|
+
#ifdef BOOST_MSVC
|
|
37
|
+
#pragma warning(push)
|
|
38
|
+
#pragma warning(disable : 4702)
|
|
39
|
+
#pragma warning(disable : 4127) // conditional expression is constant
|
|
40
|
+
#pragma warning(disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
|
|
41
|
+
#endif
|
|
42
|
+
|
|
43
|
+
// Forward decleration of gcd and lcm functions
|
|
44
|
+
namespace boost { namespace multiprecision { namespace detail {
|
|
45
|
+
|
|
46
|
+
template <typename T>
|
|
47
|
+
inline BOOST_CXX14_CONSTEXPR T constexpr_gcd(T a, T b) noexcept;
|
|
48
|
+
|
|
49
|
+
template <typename T>
|
|
50
|
+
inline BOOST_CXX14_CONSTEXPR T constexpr_lcm(T a, T b) noexcept;
|
|
51
|
+
|
|
52
|
+
}}} // namespace boost::multiprecision::detail
|
|
53
|
+
|
|
54
|
+
namespace boost { namespace multiprecision { namespace backends {
|
|
55
|
+
|
|
56
|
+
template <class T, bool has_limits = std::numeric_limits<T>::is_specialized>
|
|
57
|
+
struct numeric_limits_workaround : public std::numeric_limits<T>
|
|
58
|
+
{
|
|
59
|
+
};
|
|
60
|
+
template <class R>
|
|
61
|
+
struct numeric_limits_workaround<R, false>
|
|
62
|
+
{
|
|
63
|
+
static constexpr unsigned digits = ~static_cast<R>(0) < 0 ? sizeof(R) * CHAR_BIT - 1 : sizeof(R) * CHAR_BIT;
|
|
64
|
+
static constexpr R (min)(){ return (static_cast<R>(-1) < 0) ? static_cast<R>(1) << digits : 0; }
|
|
65
|
+
static constexpr R (max)() { return (static_cast<R>(-1) < 0) ? ~(static_cast<R>(1) << digits) : ~static_cast<R>(0); }
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
template <class R, class CppInt>
|
|
69
|
+
BOOST_MP_CXX14_CONSTEXPR void check_in_range(const CppInt& val, const std::integral_constant<int, checked>&)
|
|
70
|
+
{
|
|
71
|
+
using cast_type = typename boost::multiprecision::detail::canonical<R, CppInt>::type;
|
|
72
|
+
|
|
73
|
+
if (val.sign())
|
|
74
|
+
{
|
|
75
|
+
BOOST_IF_CONSTEXPR (boost::multiprecision::detail::is_signed<R>::value == false)
|
|
76
|
+
BOOST_MP_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));
|
|
77
|
+
if (val.compare(static_cast<cast_type>((numeric_limits_workaround<R>::min)())) < 0)
|
|
78
|
+
BOOST_MP_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
|
|
79
|
+
}
|
|
80
|
+
else
|
|
81
|
+
{
|
|
82
|
+
if (val.compare(static_cast<cast_type>((numeric_limits_workaround<R>::max)())) > 0)
|
|
83
|
+
BOOST_MP_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
template <class R, class CppInt>
|
|
87
|
+
inline BOOST_MP_CXX14_CONSTEXPR void check_in_range(const CppInt& /*val*/, const std::integral_constant<int, unchecked>&) noexcept {}
|
|
88
|
+
|
|
89
|
+
inline BOOST_MP_CXX14_CONSTEXPR void check_is_negative(const std::integral_constant<bool, true>&) noexcept {}
|
|
90
|
+
inline void check_is_negative(const std::integral_constant<bool, false>&)
|
|
91
|
+
{
|
|
92
|
+
BOOST_MP_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
template <class Integer>
|
|
96
|
+
inline BOOST_MP_CXX14_CONSTEXPR Integer negate_integer(Integer i, const std::integral_constant<bool, true>&) noexcept
|
|
97
|
+
{
|
|
98
|
+
return -i;
|
|
99
|
+
}
|
|
100
|
+
template <class Integer>
|
|
101
|
+
inline BOOST_MP_CXX14_CONSTEXPR Integer negate_integer(Integer i, const std::integral_constant<bool, false>&) noexcept
|
|
102
|
+
{
|
|
103
|
+
return ~(i - 1);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
template <class R, std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
107
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type
|
|
108
|
+
eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend)
|
|
109
|
+
{
|
|
110
|
+
using checked_type = std::integral_constant<int, Checked1>;
|
|
111
|
+
check_in_range<R>(backend, checked_type());
|
|
112
|
+
|
|
113
|
+
BOOST_IF_CONSTEXPR(numeric_limits_workaround<R>::digits < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
|
|
114
|
+
{
|
|
115
|
+
if ((backend.sign() && boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value) && (1 + static_cast<boost::multiprecision::limb_type>((std::numeric_limits<R>::max)()) <= backend.limbs()[0]))
|
|
116
|
+
{
|
|
117
|
+
*result = (numeric_limits_workaround<R>::min)();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
else if (boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value && !backend.sign() && static_cast<boost::multiprecision::limb_type>((std::numeric_limits<R>::max)()) <= backend.limbs()[0])
|
|
121
|
+
{
|
|
122
|
+
*result = (numeric_limits_workaround<R>::max)();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
else
|
|
126
|
+
*result = static_cast<R>(backend.limbs()[0]);
|
|
127
|
+
}
|
|
128
|
+
else
|
|
129
|
+
*result = static_cast<R>(backend.limbs()[0]);
|
|
130
|
+
|
|
131
|
+
BOOST_IF_CONSTEXPR(numeric_limits_workaround<R>::digits > cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
|
|
132
|
+
{
|
|
133
|
+
std::size_t shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
|
|
134
|
+
std::size_t i = 1u;
|
|
135
|
+
|
|
136
|
+
while ((i < backend.size()) && (shift < static_cast<unsigned>(numeric_limits_workaround<R>::digits - cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)))
|
|
137
|
+
{
|
|
138
|
+
*result += static_cast<R>(backend.limbs()[i]) << shift;
|
|
139
|
+
shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
|
|
140
|
+
++i;
|
|
141
|
+
}
|
|
142
|
+
//
|
|
143
|
+
// We have one more limb to extract, but may not need all the bits, so treat this as a special case:
|
|
144
|
+
//
|
|
145
|
+
if (i < backend.size())
|
|
146
|
+
{
|
|
147
|
+
const limb_type mask = ((numeric_limits_workaround<R>::digits - shift) == cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits) ? ~static_cast<limb_type>(0) : static_cast<limb_type>(static_cast<limb_type>(1u) << (numeric_limits_workaround<R>::digits - shift)) - 1u;
|
|
148
|
+
const limb_type limb_at_index_masked = static_cast<limb_type>(backend.limbs()[i] & mask);
|
|
149
|
+
|
|
150
|
+
*result = static_cast<R>(*result + static_cast<R>(static_cast<R>(limb_at_index_masked) << shift));
|
|
151
|
+
|
|
152
|
+
if ((backend.limbs()[i] & static_cast<limb_type>(~mask)) || (i + 1 < backend.size()))
|
|
153
|
+
{
|
|
154
|
+
// Overflow:
|
|
155
|
+
if (backend.sign())
|
|
156
|
+
{
|
|
157
|
+
check_is_negative(boost::multiprecision::detail::is_signed<R>());
|
|
158
|
+
*result = (numeric_limits_workaround<R>::min)();
|
|
159
|
+
}
|
|
160
|
+
else if (boost::multiprecision::detail::is_signed<R>::value)
|
|
161
|
+
*result = (numeric_limits_workaround<R>::max)();
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else if (backend.size() > 1)
|
|
167
|
+
{
|
|
168
|
+
// Overflow:
|
|
169
|
+
if (backend.sign())
|
|
170
|
+
{
|
|
171
|
+
check_is_negative(boost::multiprecision::detail::is_signed<R>());
|
|
172
|
+
*result = (numeric_limits_workaround<R>::min)();
|
|
173
|
+
}
|
|
174
|
+
else if (boost::multiprecision::detail::is_signed<R>::value)
|
|
175
|
+
*result = (numeric_limits_workaround<R>::max)();
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (backend.sign())
|
|
179
|
+
{
|
|
180
|
+
check_is_negative(std::integral_constant<bool, boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value>());
|
|
181
|
+
*result = negate_integer(*result, std::integral_constant<bool, boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value>());
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
template <class R, std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
186
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_floating_point<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type
|
|
187
|
+
eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend) noexcept(boost::multiprecision::detail::is_arithmetic<R>::value &&
|
|
188
|
+
(std::numeric_limits<R>::has_infinity ||
|
|
189
|
+
std::numeric_limits<R>::has_quiet_NaN))
|
|
190
|
+
{
|
|
191
|
+
BOOST_MP_FLOAT128_USING using std::ldexp;
|
|
192
|
+
if (eval_is_zero(backend))
|
|
193
|
+
{
|
|
194
|
+
*result = 0.0f;
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
#ifdef BOOST_HAS_FLOAT128
|
|
199
|
+
std::ptrdiff_t bits_to_keep = static_cast<std::ptrdiff_t>(std::is_same<R, float128_type>::value ? 113 : std::numeric_limits<R>::digits);
|
|
200
|
+
#else
|
|
201
|
+
std::ptrdiff_t bits_to_keep = static_cast<std::ptrdiff_t>(std::numeric_limits<R>::digits);
|
|
202
|
+
#endif
|
|
203
|
+
std::ptrdiff_t bits = static_cast<std::ptrdiff_t>(eval_msb_imp(backend) + 1);
|
|
204
|
+
|
|
205
|
+
if (bits > bits_to_keep)
|
|
206
|
+
{
|
|
207
|
+
// Extract the bits we need, and then manually round the result:
|
|
208
|
+
*result = 0.0f;
|
|
209
|
+
typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::const_limb_pointer p = backend.limbs();
|
|
210
|
+
limb_type mask = ~static_cast<limb_type>(0u);
|
|
211
|
+
std::size_t index = backend.size() - 1;
|
|
212
|
+
std::size_t shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits * index;
|
|
213
|
+
while (bits_to_keep > 0)
|
|
214
|
+
{
|
|
215
|
+
if (bits_to_keep < (std::ptrdiff_t)cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
|
|
216
|
+
{
|
|
217
|
+
if(index != backend.size() - 1)
|
|
218
|
+
{
|
|
219
|
+
const std::ptrdiff_t left_shift_amount = static_cast<std::ptrdiff_t>(static_cast<std::ptrdiff_t>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits) - bits_to_keep);
|
|
220
|
+
|
|
221
|
+
mask <<= left_shift_amount;
|
|
222
|
+
}
|
|
223
|
+
else
|
|
224
|
+
{
|
|
225
|
+
std::ptrdiff_t bits_in_first_limb = static_cast<std::ptrdiff_t>(bits % static_cast<std::ptrdiff_t>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits));
|
|
226
|
+
if (bits_in_first_limb == 0)
|
|
227
|
+
bits_in_first_limb = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
|
|
228
|
+
if (bits_in_first_limb > bits_to_keep)
|
|
229
|
+
mask <<= bits_in_first_limb - bits_to_keep;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
*result += ldexp(static_cast<R>(p[index] & mask), static_cast<int>(shift));
|
|
233
|
+
shift -= cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
|
|
234
|
+
|
|
235
|
+
const bool bits_has_non_zero_remainder = (bits % static_cast<std::ptrdiff_t>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits) != 0);
|
|
236
|
+
|
|
237
|
+
bits_to_keep -= ((index == backend.size() - 1) && bits_has_non_zero_remainder)
|
|
238
|
+
? bits % static_cast<std::ptrdiff_t>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
|
|
239
|
+
: static_cast<std::ptrdiff_t>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits);
|
|
240
|
+
--index;
|
|
241
|
+
}
|
|
242
|
+
// Perform rounding:
|
|
243
|
+
bits -= 1 + std::numeric_limits<R>::digits;
|
|
244
|
+
if (eval_bit_test(backend, static_cast<unsigned>(bits)))
|
|
245
|
+
{
|
|
246
|
+
if ((eval_lsb_imp(backend) < static_cast<std::size_t>(bits)) || eval_bit_test(backend, static_cast<std::size_t>(bits + 1)))
|
|
247
|
+
{
|
|
248
|
+
#ifdef BOOST_MP_MATH_AVAILABLE
|
|
249
|
+
BOOST_IF_CONSTEXPR(std::numeric_limits<R>::has_infinity || std::numeric_limits<R>::has_quiet_NaN)
|
|
250
|
+
{
|
|
251
|
+
// Must NOT throw:
|
|
252
|
+
*result = boost::math::float_next(*result, boost::math::policies::make_policy(boost::math::policies::overflow_error<boost::math::policies::ignore_error>(),
|
|
253
|
+
boost::math::policies::domain_error<boost::math::policies::ignore_error>()));
|
|
254
|
+
}
|
|
255
|
+
else
|
|
256
|
+
{
|
|
257
|
+
*result = boost::math::float_next(*result);
|
|
258
|
+
}
|
|
259
|
+
#else
|
|
260
|
+
using std::nextafter; BOOST_MP_FLOAT128_USING
|
|
261
|
+
*result = nextafter(*result, *result * 2);
|
|
262
|
+
#endif
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
else
|
|
267
|
+
{
|
|
268
|
+
typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::const_limb_pointer p = backend.limbs();
|
|
269
|
+
std::size_t shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
|
|
270
|
+
*result = static_cast<R>(*p);
|
|
271
|
+
for (std::size_t i = 1; i < backend.size(); ++i)
|
|
272
|
+
{
|
|
273
|
+
*result += static_cast<R>(ldexp(static_cast<long double>(p[i]), static_cast<int>(shift)));
|
|
274
|
+
shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (backend.sign())
|
|
278
|
+
*result = -*result;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
282
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type
|
|
283
|
+
eval_is_zero(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) noexcept
|
|
284
|
+
{
|
|
285
|
+
return (val.size() == 1) && (val.limbs()[0] == 0);
|
|
286
|
+
}
|
|
287
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
288
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, int>::type
|
|
289
|
+
eval_get_sign(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) noexcept
|
|
290
|
+
{
|
|
291
|
+
return eval_is_zero(val) ? 0 : val.sign() ? -1 : 1;
|
|
292
|
+
}
|
|
293
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
294
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
|
|
295
|
+
eval_abs(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
|
|
296
|
+
{
|
|
297
|
+
result = val;
|
|
298
|
+
result.sign(false);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
//
|
|
302
|
+
// Get the location of the least-significant-bit:
|
|
303
|
+
//
|
|
304
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
305
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
|
|
306
|
+
eval_lsb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
|
|
307
|
+
{
|
|
308
|
+
//
|
|
309
|
+
// Find the index of the least significant limb that is non-zero:
|
|
310
|
+
//
|
|
311
|
+
std::size_t index = 0;
|
|
312
|
+
while (!a.limbs()[index] && (index < a.size()))
|
|
313
|
+
++index;
|
|
314
|
+
//
|
|
315
|
+
// Find the index of the least significant bit within that limb:
|
|
316
|
+
//
|
|
317
|
+
std::size_t result = boost::multiprecision::detail::find_lsb(a.limbs()[index]);
|
|
318
|
+
|
|
319
|
+
return result + index * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
323
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
|
|
324
|
+
eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
|
|
325
|
+
{
|
|
326
|
+
using default_ops::eval_get_sign;
|
|
327
|
+
if (eval_get_sign(a) == 0)
|
|
328
|
+
{
|
|
329
|
+
BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
|
|
330
|
+
}
|
|
331
|
+
if (a.sign())
|
|
332
|
+
{
|
|
333
|
+
BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
|
|
334
|
+
}
|
|
335
|
+
return eval_lsb_imp(a);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
//
|
|
339
|
+
// Get the location of the most-significant-bit:
|
|
340
|
+
//
|
|
341
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
342
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
|
|
343
|
+
eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
|
|
344
|
+
{
|
|
345
|
+
//
|
|
346
|
+
// Find the index of the most significant bit that is non-zero:
|
|
347
|
+
//
|
|
348
|
+
return (a.size() - 1) * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits + boost::multiprecision::detail::find_msb(a.limbs()[a.size() - 1]);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
352
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
|
|
353
|
+
eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
|
|
354
|
+
{
|
|
355
|
+
using default_ops::eval_get_sign;
|
|
356
|
+
if (eval_get_sign(a) == 0)
|
|
357
|
+
{
|
|
358
|
+
BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
|
|
359
|
+
}
|
|
360
|
+
if (a.sign())
|
|
361
|
+
{
|
|
362
|
+
BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
|
|
363
|
+
}
|
|
364
|
+
return eval_msb_imp(a);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
#ifdef BOOST_GCC
|
|
368
|
+
//
|
|
369
|
+
// We really shouldn't need to be disabling this warning, but it really does appear to be
|
|
370
|
+
// spurious. The warning appears only when in release mode, and asserts are on.
|
|
371
|
+
//
|
|
372
|
+
#pragma GCC diagnostic push
|
|
373
|
+
#pragma GCC diagnostic ignored "-Warray-bounds"
|
|
374
|
+
#endif
|
|
375
|
+
|
|
376
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
377
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type
|
|
378
|
+
eval_bit_test(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, std::size_t index) noexcept
|
|
379
|
+
{
|
|
380
|
+
std::size_t offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
|
|
381
|
+
std::size_t shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
|
|
382
|
+
limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
|
|
383
|
+
if (offset >= val.size())
|
|
384
|
+
return false;
|
|
385
|
+
return val.limbs()[offset] & mask ? true : false;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
#ifdef BOOST_GCC
|
|
389
|
+
#pragma GCC diagnostic pop
|
|
390
|
+
#endif
|
|
391
|
+
|
|
392
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
393
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
|
|
394
|
+
eval_bit_set(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, std::size_t index)
|
|
395
|
+
{
|
|
396
|
+
std::size_t offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
|
|
397
|
+
std::size_t shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
|
|
398
|
+
limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
|
|
399
|
+
if (offset >= val.size())
|
|
400
|
+
{
|
|
401
|
+
std::size_t os = val.size();
|
|
402
|
+
val.resize(offset + 1, offset + 1);
|
|
403
|
+
if (offset >= val.size())
|
|
404
|
+
return; // fixed precision overflow
|
|
405
|
+
for (std::size_t i = os; i <= offset; ++i)
|
|
406
|
+
val.limbs()[i] = 0;
|
|
407
|
+
}
|
|
408
|
+
val.limbs()[offset] |= mask;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
412
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
|
|
413
|
+
eval_bit_unset(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, std::size_t index) noexcept
|
|
414
|
+
{
|
|
415
|
+
std::size_t offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
|
|
416
|
+
std::size_t shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
|
|
417
|
+
limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
|
|
418
|
+
if (offset >= val.size())
|
|
419
|
+
return;
|
|
420
|
+
val.limbs()[offset] &= ~mask;
|
|
421
|
+
val.normalize();
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
425
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
|
|
426
|
+
eval_bit_flip(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, std::size_t index)
|
|
427
|
+
{
|
|
428
|
+
std::size_t offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
|
|
429
|
+
std::size_t shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
|
|
430
|
+
limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
|
|
431
|
+
if (offset >= val.size())
|
|
432
|
+
{
|
|
433
|
+
std::size_t os = val.size();
|
|
434
|
+
val.resize(offset + 1, offset + 1);
|
|
435
|
+
if (offset >= val.size())
|
|
436
|
+
return; // fixed precision overflow
|
|
437
|
+
for (std::size_t i = os; i <= offset; ++i)
|
|
438
|
+
val.limbs()[i] = 0;
|
|
439
|
+
}
|
|
440
|
+
val.limbs()[offset] ^= mask;
|
|
441
|
+
val.normalize();
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
445
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
|
|
446
|
+
eval_qr(
|
|
447
|
+
const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
|
|
448
|
+
const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& y,
|
|
449
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
|
|
450
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
|
|
451
|
+
{
|
|
452
|
+
divide_unsigned_helper(&q, x, y, r);
|
|
453
|
+
q.sign(x.sign() != y.sign());
|
|
454
|
+
r.sign(x.sign());
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
458
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
|
|
459
|
+
eval_qr(
|
|
460
|
+
const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
|
|
461
|
+
limb_type y,
|
|
462
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
|
|
463
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
|
|
464
|
+
{
|
|
465
|
+
divide_unsigned_helper(&q, x, y, r);
|
|
466
|
+
q.sign(x.sign());
|
|
467
|
+
r.sign(x.sign());
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class U>
|
|
471
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<U>::value>::type eval_qr(
|
|
472
|
+
const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
|
|
473
|
+
U y,
|
|
474
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
|
|
475
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
|
|
476
|
+
{
|
|
477
|
+
using default_ops::eval_qr;
|
|
478
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
|
|
479
|
+
t = y;
|
|
480
|
+
eval_qr(x, t, q, r);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
|
|
484
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_unsigned<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::type
|
|
485
|
+
eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, Integer mod)
|
|
486
|
+
{
|
|
487
|
+
BOOST_IF_CONSTEXPR (sizeof(Integer) <= sizeof(limb_type))
|
|
488
|
+
{
|
|
489
|
+
if (mod <= (std::numeric_limits<limb_type>::max)())
|
|
490
|
+
{
|
|
491
|
+
const std::ptrdiff_t n = a.size();
|
|
492
|
+
const double_limb_type two_n_mod = static_cast<limb_type>(1u) + (~static_cast<limb_type>(0u) - mod) % mod;
|
|
493
|
+
limb_type res = a.limbs()[n - 1] % mod;
|
|
494
|
+
|
|
495
|
+
for (std::ptrdiff_t i = n - 2; i >= 0; --i)
|
|
496
|
+
res = static_cast<limb_type>((res * two_n_mod + a.limbs()[i]) % mod);
|
|
497
|
+
return res;
|
|
498
|
+
}
|
|
499
|
+
else
|
|
500
|
+
return default_ops::eval_integer_modulus(a, mod);
|
|
501
|
+
}
|
|
502
|
+
else
|
|
503
|
+
{
|
|
504
|
+
return default_ops::eval_integer_modulus(a, mod);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
|
|
509
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_signed<Integer>::value && boost::multiprecision::detail::is_integral<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::type
|
|
510
|
+
eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val)
|
|
511
|
+
{
|
|
512
|
+
return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val));
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR limb_type eval_gcd(limb_type u, limb_type v)
|
|
516
|
+
{
|
|
517
|
+
// boundary cases
|
|
518
|
+
if (!u || !v)
|
|
519
|
+
return u | v;
|
|
520
|
+
#if (defined(__cpp_lib_gcd_lcm) && (__cpp_lib_gcd_lcm >= 201606L))
|
|
521
|
+
return std::gcd(u, v);
|
|
522
|
+
#else
|
|
523
|
+
std::size_t shift = boost::multiprecision::detail::find_lsb(u | v);
|
|
524
|
+
u >>= boost::multiprecision::detail::find_lsb(u);
|
|
525
|
+
do
|
|
526
|
+
{
|
|
527
|
+
v >>= boost::multiprecision::detail::find_lsb(v);
|
|
528
|
+
if (u > v)
|
|
529
|
+
std_constexpr::swap(u, v);
|
|
530
|
+
v -= u;
|
|
531
|
+
} while (v);
|
|
532
|
+
return u << shift;
|
|
533
|
+
#endif
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
inline BOOST_MP_CXX14_CONSTEXPR double_limb_type eval_gcd(double_limb_type u, double_limb_type v)
|
|
537
|
+
{
|
|
538
|
+
#if (defined(__cpp_lib_gcd_lcm) && (__cpp_lib_gcd_lcm >= 201606L)) && (!defined(BOOST_HAS_INT128) || !defined(__STRICT_ANSI__))
|
|
539
|
+
return std::gcd(u, v);
|
|
540
|
+
#else
|
|
541
|
+
if (u == 0)
|
|
542
|
+
return v;
|
|
543
|
+
|
|
544
|
+
std::size_t shift = boost::multiprecision::detail::find_lsb(u | v);
|
|
545
|
+
u >>= boost::multiprecision::detail::find_lsb(u);
|
|
546
|
+
do
|
|
547
|
+
{
|
|
548
|
+
v >>= boost::multiprecision::detail::find_lsb(v);
|
|
549
|
+
if (u > v)
|
|
550
|
+
std_constexpr::swap(u, v);
|
|
551
|
+
v -= u;
|
|
552
|
+
} while (v);
|
|
553
|
+
return u << shift;
|
|
554
|
+
#endif
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
558
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
|
|
559
|
+
eval_gcd(
|
|
560
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
|
|
561
|
+
const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
|
|
562
|
+
limb_type b)
|
|
563
|
+
{
|
|
564
|
+
int s = eval_get_sign(a);
|
|
565
|
+
if (!b || !s)
|
|
566
|
+
{
|
|
567
|
+
result = a;
|
|
568
|
+
*result.limbs() |= b;
|
|
569
|
+
}
|
|
570
|
+
else
|
|
571
|
+
{
|
|
572
|
+
eval_modulus(result, a, b);
|
|
573
|
+
limb_type& res = *result.limbs();
|
|
574
|
+
res = eval_gcd(res, b);
|
|
575
|
+
}
|
|
576
|
+
result.sign(false);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
580
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
|
|
581
|
+
eval_gcd(
|
|
582
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
|
|
583
|
+
const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
|
|
584
|
+
double_limb_type b)
|
|
585
|
+
{
|
|
586
|
+
int s = eval_get_sign(a);
|
|
587
|
+
if (!b || !s)
|
|
588
|
+
{
|
|
589
|
+
if (!s)
|
|
590
|
+
result = b;
|
|
591
|
+
else
|
|
592
|
+
result = a;
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
double_limb_type res = 0;
|
|
596
|
+
if(a.sign() == 0)
|
|
597
|
+
res = eval_integer_modulus(a, b);
|
|
598
|
+
else
|
|
599
|
+
{
|
|
600
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(a);
|
|
601
|
+
t.negate();
|
|
602
|
+
res = eval_integer_modulus(t, b);
|
|
603
|
+
}
|
|
604
|
+
res = eval_gcd(res, b);
|
|
605
|
+
result = res;
|
|
606
|
+
result.sign(false);
|
|
607
|
+
}
|
|
608
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
609
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
|
|
610
|
+
eval_gcd(
|
|
611
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
|
|
612
|
+
const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
|
|
613
|
+
signed_double_limb_type v)
|
|
614
|
+
{
|
|
615
|
+
eval_gcd(result, a, static_cast<double_limb_type>(v < 0 ? -v : v));
|
|
616
|
+
}
|
|
617
|
+
//
|
|
618
|
+
// These 2 overloads take care of gcd against an (unsigned) short etc:
|
|
619
|
+
//
|
|
620
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
|
|
621
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_unsigned<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
|
|
622
|
+
eval_gcd(
|
|
623
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
|
|
624
|
+
const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
|
|
625
|
+
const Integer& v)
|
|
626
|
+
{
|
|
627
|
+
eval_gcd(result, a, static_cast<limb_type>(v));
|
|
628
|
+
}
|
|
629
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
|
|
630
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_signed<Integer>::value && boost::multiprecision::detail::is_integral<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
|
|
631
|
+
eval_gcd(
|
|
632
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
|
|
633
|
+
const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
|
|
634
|
+
const Integer& v)
|
|
635
|
+
{
|
|
636
|
+
eval_gcd(result, a, static_cast<limb_type>(v < 0 ? -v : v));
|
|
637
|
+
}
|
|
638
|
+
//
|
|
639
|
+
// What follows is Lehmer's GCD algorithm:
|
|
640
|
+
// Essentially this uses the leading digit(s) of U and V
|
|
641
|
+
// only to run a "simulated" Euclid algorithm. It stops
|
|
642
|
+
// when the calculated quotient differs from what would have been
|
|
643
|
+
// the true quotient. At that point the cosequences are used to
|
|
644
|
+
// calculate the new U and V. A nice lucid description appears
|
|
645
|
+
// in "An Analysis of Lehmer's Euclidean GCD Algorithm",
|
|
646
|
+
// by Jonathan Sorenson. https://www.researchgate.net/publication/2424634_An_Analysis_of_Lehmer%27s_Euclidean_GCD_Algorithm
|
|
647
|
+
// DOI: 10.1145/220346.220378.
|
|
648
|
+
//
|
|
649
|
+
// There are two versions of this algorithm here, and both are "double digit"
|
|
650
|
+
// variations: which is to say if there are k bits per limb, then they extract
|
|
651
|
+
// 2k bits into a double_limb_type and then run the algorithm on that. The first
|
|
652
|
+
// version is a straightforward version of the algorithm, and is designed for
|
|
653
|
+
// situations where double_limb_type is a native integer (for example where
|
|
654
|
+
// limb_type is a 32-bit integer on a 64-bit machine). For 32-bit limbs it
|
|
655
|
+
// reduces the size of U by about 30 bits per call. The second is a more complex
|
|
656
|
+
// version for situations where double_limb_type is a synthetic type: for example
|
|
657
|
+
// __int128. For 64 bit limbs it reduces the size of U by about 62 bits per call.
|
|
658
|
+
//
|
|
659
|
+
// The complexity of the algorithm given by Sorenson is roughly O(ln^2(N)) for
|
|
660
|
+
// two N bit numbers.
|
|
661
|
+
//
|
|
662
|
+
// The original double-digit version of the algorithm is described in:
|
|
663
|
+
//
|
|
664
|
+
// "A Double Digit Lehmer-Euclid Algorithm for Finding the GCD of Long Integers",
|
|
665
|
+
// Tudor Jebelean, J Symbolic Computation, 1995 (19), 145.
|
|
666
|
+
//
|
|
667
|
+
#ifndef BOOST_HAS_INT128
|
|
668
|
+
//
|
|
669
|
+
// When double_limb_type is a native integer type then we should just use it and not worry about the consequences.
|
|
670
|
+
// This can eliminate approximately a full limb with each call.
|
|
671
|
+
//
|
|
672
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Storage>
|
|
673
|
+
void eval_gcd_lehmer(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& U, cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& V, std::size_t lu, Storage& storage)
|
|
674
|
+
{
|
|
675
|
+
//
|
|
676
|
+
// Extract the leading 2 * bits_per_limb bits from U and V:
|
|
677
|
+
//
|
|
678
|
+
std::size_t h = lu % bits_per_limb;
|
|
679
|
+
double_limb_type u = (static_cast<double_limb_type>((U.limbs()[U.size() - 1])) << bits_per_limb) | U.limbs()[U.size() - 2];
|
|
680
|
+
double_limb_type v = (static_cast<double_limb_type>((V.size() < U.size() ? 0 : V.limbs()[V.size() - 1])) << bits_per_limb) | V.limbs()[U.size() - 2];
|
|
681
|
+
if (h)
|
|
682
|
+
{
|
|
683
|
+
u <<= bits_per_limb - h;
|
|
684
|
+
u |= U.limbs()[U.size() - 3] >> h;
|
|
685
|
+
v <<= bits_per_limb - h;
|
|
686
|
+
v |= V.limbs()[U.size() - 3] >> h;
|
|
687
|
+
}
|
|
688
|
+
//
|
|
689
|
+
// Co-sequences x an y: we need only the last 3 values of these,
|
|
690
|
+
// the first 2 values are known correct, the third gets checked
|
|
691
|
+
// in each loop operation, and we terminate when they go wrong.
|
|
692
|
+
//
|
|
693
|
+
// x[i+0] is positive for even i.
|
|
694
|
+
// y[i+0] is positive for odd i.
|
|
695
|
+
//
|
|
696
|
+
// However we track only absolute values here:
|
|
697
|
+
//
|
|
698
|
+
double_limb_type x[3] = {1, 0};
|
|
699
|
+
double_limb_type y[3] = {0, 1};
|
|
700
|
+
std::size_t i = 0;
|
|
701
|
+
|
|
702
|
+
#ifdef BOOST_MP_GCD_DEBUG
|
|
703
|
+
cpp_int UU, VV;
|
|
704
|
+
UU = U;
|
|
705
|
+
VV = V;
|
|
706
|
+
#endif
|
|
707
|
+
|
|
708
|
+
while (true)
|
|
709
|
+
{
|
|
710
|
+
double_limb_type q = u / v;
|
|
711
|
+
x[2] = x[0] + q * x[1];
|
|
712
|
+
y[2] = y[0] + q * y[1];
|
|
713
|
+
double_limb_type tu = u;
|
|
714
|
+
u = v;
|
|
715
|
+
v = tu - q * v;
|
|
716
|
+
++i;
|
|
717
|
+
//
|
|
718
|
+
// We must make sure that y[2] occupies a single limb otherwise
|
|
719
|
+
// the multiprecision multiplications below would be much more expensive.
|
|
720
|
+
// This can sometimes lose us one iteration, but is worth it for improved
|
|
721
|
+
// calculation efficiency.
|
|
722
|
+
//
|
|
723
|
+
if (y[2] >> bits_per_limb)
|
|
724
|
+
break;
|
|
725
|
+
//
|
|
726
|
+
// These are Jebelean's exact termination conditions:
|
|
727
|
+
//
|
|
728
|
+
if ((i & 1u) == 0)
|
|
729
|
+
{
|
|
730
|
+
BOOST_MP_ASSERT(u > v);
|
|
731
|
+
if ((v < x[2]) || ((u - v) < (y[2] + y[1])))
|
|
732
|
+
break;
|
|
733
|
+
}
|
|
734
|
+
else
|
|
735
|
+
{
|
|
736
|
+
BOOST_MP_ASSERT(u > v);
|
|
737
|
+
if ((v < y[2]) || ((u - v) < (x[2] + x[1])))
|
|
738
|
+
break;
|
|
739
|
+
}
|
|
740
|
+
#ifdef BOOST_MP_GCD_DEBUG
|
|
741
|
+
BOOST_MP_ASSERT(q == UU / VV);
|
|
742
|
+
UU %= VV;
|
|
743
|
+
UU.swap(VV);
|
|
744
|
+
#endif
|
|
745
|
+
x[0] = x[1];
|
|
746
|
+
x[1] = x[2];
|
|
747
|
+
y[0] = y[1];
|
|
748
|
+
y[1] = y[2];
|
|
749
|
+
}
|
|
750
|
+
if (i == 1)
|
|
751
|
+
{
|
|
752
|
+
// No change to U and V we've stalled!
|
|
753
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
|
|
754
|
+
eval_modulus(t, U, V);
|
|
755
|
+
U.swap(V);
|
|
756
|
+
V.swap(t);
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
//
|
|
760
|
+
// Update U and V.
|
|
761
|
+
// We have:
|
|
762
|
+
//
|
|
763
|
+
// U = x[0]U + y[0]V and
|
|
764
|
+
// V = x[1]U + y[1]V.
|
|
765
|
+
//
|
|
766
|
+
// But since we track only absolute values of x and y
|
|
767
|
+
// we have to take account of the implied signs and perform
|
|
768
|
+
// the appropriate subtraction depending on the whether i is
|
|
769
|
+
// even or odd:
|
|
770
|
+
//
|
|
771
|
+
std::size_t ts = U.size() + 1;
|
|
772
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t1(storage, ts), t2(storage, ts), t3(storage, ts);
|
|
773
|
+
eval_multiply(t1, U, static_cast<limb_type>(x[0]));
|
|
774
|
+
eval_multiply(t2, V, static_cast<limb_type>(y[0]));
|
|
775
|
+
eval_multiply(t3, U, static_cast<limb_type>(x[1]));
|
|
776
|
+
if ((i & 1u) == 0)
|
|
777
|
+
{
|
|
778
|
+
if (x[0] == 0)
|
|
779
|
+
U = t2;
|
|
780
|
+
else
|
|
781
|
+
{
|
|
782
|
+
BOOST_MP_ASSERT(t2.compare(t1) >= 0);
|
|
783
|
+
eval_subtract(U, t2, t1);
|
|
784
|
+
BOOST_MP_ASSERT(U.sign() == false);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
else
|
|
788
|
+
{
|
|
789
|
+
BOOST_MP_ASSERT(t1.compare(t2) >= 0);
|
|
790
|
+
eval_subtract(U, t1, t2);
|
|
791
|
+
BOOST_MP_ASSERT(U.sign() == false);
|
|
792
|
+
}
|
|
793
|
+
eval_multiply(t2, V, static_cast<limb_type>(y[1]));
|
|
794
|
+
if (i & 1u)
|
|
795
|
+
{
|
|
796
|
+
if (x[1] == 0)
|
|
797
|
+
V = t2;
|
|
798
|
+
else
|
|
799
|
+
{
|
|
800
|
+
BOOST_MP_ASSERT(t2.compare(t3) >= 0);
|
|
801
|
+
eval_subtract(V, t2, t3);
|
|
802
|
+
BOOST_MP_ASSERT(V.sign() == false);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
else
|
|
806
|
+
{
|
|
807
|
+
BOOST_MP_ASSERT(t3.compare(t2) >= 0);
|
|
808
|
+
eval_subtract(V, t3, t2);
|
|
809
|
+
BOOST_MP_ASSERT(V.sign() == false);
|
|
810
|
+
}
|
|
811
|
+
BOOST_MP_ASSERT(U.compare(V) >= 0);
|
|
812
|
+
BOOST_MP_ASSERT(lu > eval_msb(U));
|
|
813
|
+
#ifdef BOOST_MP_GCD_DEBUG
|
|
814
|
+
|
|
815
|
+
BOOST_MP_ASSERT(UU == U);
|
|
816
|
+
BOOST_MP_ASSERT(VV == V);
|
|
817
|
+
|
|
818
|
+
extern std::size_t total_lehmer_gcd_calls;
|
|
819
|
+
extern std::size_t total_lehmer_gcd_bits_saved;
|
|
820
|
+
extern std::size_t total_lehmer_gcd_cycles;
|
|
821
|
+
|
|
822
|
+
++total_lehmer_gcd_calls;
|
|
823
|
+
total_lehmer_gcd_bits_saved += lu - eval_msb(U);
|
|
824
|
+
total_lehmer_gcd_cycles += i;
|
|
825
|
+
#endif
|
|
826
|
+
if (lu < 2048)
|
|
827
|
+
{
|
|
828
|
+
//
|
|
829
|
+
// Since we have stripped all common powers of 2 from U and V at the start
|
|
830
|
+
// if either are even at this point, we can remove stray powers of 2 now.
|
|
831
|
+
// Note that it is not possible for *both* U and V to be even at this point.
|
|
832
|
+
//
|
|
833
|
+
// This has an adverse effect on performance for high bit counts, but has
|
|
834
|
+
// a significant positive effect for smaller counts.
|
|
835
|
+
//
|
|
836
|
+
if ((U.limbs()[0] & 1u) == 0)
|
|
837
|
+
{
|
|
838
|
+
eval_right_shift(U, eval_lsb(U));
|
|
839
|
+
if (U.compare(V) < 0)
|
|
840
|
+
U.swap(V);
|
|
841
|
+
}
|
|
842
|
+
else if ((V.limbs()[0] & 1u) == 0)
|
|
843
|
+
{
|
|
844
|
+
eval_right_shift(V, eval_lsb(V));
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
storage.deallocate(ts * 3);
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
#else
|
|
851
|
+
//
|
|
852
|
+
// This branch is taken when double_limb_type is a synthetic type with no native hardware support.
|
|
853
|
+
// For example __int128. The assumption is that add/subtract/multiply of double_limb_type are efficient,
|
|
854
|
+
// but that division is very slow.
|
|
855
|
+
//
|
|
856
|
+
// We begin with a specialized routine for division.
|
|
857
|
+
// We know that most of the time this is called the result will be 1.
|
|
858
|
+
// For small limb counts, this almost doubles the performance of Lehmer's routine!
|
|
859
|
+
//
|
|
860
|
+
BOOST_FORCEINLINE void divide_subtract(double_limb_type& q, double_limb_type& u, const double_limb_type& v)
|
|
861
|
+
{
|
|
862
|
+
BOOST_MP_ASSERT(q == 1); // precondition on entry.
|
|
863
|
+
u -= v;
|
|
864
|
+
while (u >= v)
|
|
865
|
+
{
|
|
866
|
+
u -= v;
|
|
867
|
+
if (++q > 30)
|
|
868
|
+
{
|
|
869
|
+
double_limb_type t = u / v;
|
|
870
|
+
u -= t * v;
|
|
871
|
+
q += t;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Storage>
|
|
877
|
+
void eval_gcd_lehmer(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& U, cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& V, std::size_t lu, Storage& storage)
|
|
878
|
+
{
|
|
879
|
+
//
|
|
880
|
+
// Extract the leading 2*bits_per_limb bits from U and V:
|
|
881
|
+
//
|
|
882
|
+
std::size_t h = lu % bits_per_limb;
|
|
883
|
+
double_limb_type u, v;
|
|
884
|
+
if (h)
|
|
885
|
+
{
|
|
886
|
+
u = (static_cast<double_limb_type>((U.limbs()[U.size() - 1])) << bits_per_limb) | U.limbs()[U.size() - 2];
|
|
887
|
+
v = (static_cast<double_limb_type>((V.size() < U.size() ? 0 : V.limbs()[V.size() - 1])) << bits_per_limb) | V.limbs()[U.size() - 2];
|
|
888
|
+
u <<= bits_per_limb - h;
|
|
889
|
+
u |= U.limbs()[U.size() - 3] >> h;
|
|
890
|
+
v <<= bits_per_limb - h;
|
|
891
|
+
v |= V.limbs()[U.size() - 3] >> h;
|
|
892
|
+
}
|
|
893
|
+
else
|
|
894
|
+
{
|
|
895
|
+
u = (static_cast<double_limb_type>(U.limbs()[U.size() - 1]) << bits_per_limb) | U.limbs()[U.size() - 2];
|
|
896
|
+
v = (static_cast<double_limb_type>(V.limbs()[U.size() - 1]) << bits_per_limb) | V.limbs()[U.size() - 2];
|
|
897
|
+
}
|
|
898
|
+
//
|
|
899
|
+
// Cosequences are stored as limb_types, we take care not to overflow these:
|
|
900
|
+
//
|
|
901
|
+
// x[i+0] is positive for even i.
|
|
902
|
+
// y[i+0] is positive for odd i.
|
|
903
|
+
//
|
|
904
|
+
// However we track only absolute values here:
|
|
905
|
+
//
|
|
906
|
+
limb_type x[3] = { 1, 0 };
|
|
907
|
+
limb_type y[3] = { 0, 1 };
|
|
908
|
+
std::size_t i = 0;
|
|
909
|
+
|
|
910
|
+
#ifdef BOOST_MP_GCD_DEBUG
|
|
911
|
+
cpp_int UU, VV;
|
|
912
|
+
UU = U;
|
|
913
|
+
VV = V;
|
|
914
|
+
#endif
|
|
915
|
+
//
|
|
916
|
+
// We begine by running a single digit version of Lehmer's algorithm, we still have
|
|
917
|
+
// to track u and v at double precision, but this adds only a tiny performance penalty.
|
|
918
|
+
// What we gain is fast division, and fast termination testing.
|
|
919
|
+
// When you see static_cast<limb_type>(u >> bits_per_limb) here, this is really just
|
|
920
|
+
// a direct access to the upper bits_per_limb of the double limb type. For __int128
|
|
921
|
+
// this is simple a load of the upper 64 bits and the "shift" is optimised away.
|
|
922
|
+
//
|
|
923
|
+
double_limb_type old_u, old_v;
|
|
924
|
+
while (true)
|
|
925
|
+
{
|
|
926
|
+
limb_type q = static_cast<limb_type>(u >> bits_per_limb) / static_cast<limb_type>(v >> bits_per_limb);
|
|
927
|
+
x[2] = x[0] + q * x[1];
|
|
928
|
+
y[2] = y[0] + q * y[1];
|
|
929
|
+
double_limb_type tu = u;
|
|
930
|
+
old_u = u;
|
|
931
|
+
old_v = v;
|
|
932
|
+
u = v;
|
|
933
|
+
double_limb_type t = q * v;
|
|
934
|
+
if (tu < t)
|
|
935
|
+
{
|
|
936
|
+
++i;
|
|
937
|
+
break;
|
|
938
|
+
}
|
|
939
|
+
v = tu - t;
|
|
940
|
+
++i;
|
|
941
|
+
BOOST_MP_ASSERT((u <= v) || (t / q == old_v));
|
|
942
|
+
if (u <= v)
|
|
943
|
+
{
|
|
944
|
+
// We've gone terribly wrong, probably numeric overflow:
|
|
945
|
+
break;
|
|
946
|
+
}
|
|
947
|
+
if ((i & 1u) == 0)
|
|
948
|
+
{
|
|
949
|
+
if ((static_cast<limb_type>(v >> bits_per_limb) < x[2]) || ((static_cast<limb_type>(u >> bits_per_limb) - static_cast<limb_type>(v >> bits_per_limb)) < (y[2] + y[1])))
|
|
950
|
+
break;
|
|
951
|
+
}
|
|
952
|
+
else
|
|
953
|
+
{
|
|
954
|
+
if ((static_cast<limb_type>(v >> bits_per_limb) < y[2]) || ((static_cast<limb_type>(u >> bits_per_limb) - static_cast<limb_type>(v >> bits_per_limb)) < (x[2] + x[1])))
|
|
955
|
+
break;
|
|
956
|
+
}
|
|
957
|
+
#ifdef BOOST_MP_GCD_DEBUG
|
|
958
|
+
BOOST_MP_ASSERT(q == UU / VV);
|
|
959
|
+
UU %= VV;
|
|
960
|
+
UU.swap(VV);
|
|
961
|
+
#endif
|
|
962
|
+
x[0] = x[1];
|
|
963
|
+
x[1] = x[2];
|
|
964
|
+
y[0] = y[1];
|
|
965
|
+
y[1] = y[2];
|
|
966
|
+
}
|
|
967
|
+
//
|
|
968
|
+
// We get here when the single digit algorithm has gone wrong, back up i, u and v:
|
|
969
|
+
//
|
|
970
|
+
--i;
|
|
971
|
+
u = old_u;
|
|
972
|
+
v = old_v;
|
|
973
|
+
//
|
|
974
|
+
// Now run the full double-digit algorithm:
|
|
975
|
+
//
|
|
976
|
+
while (true)
|
|
977
|
+
{
|
|
978
|
+
double_limb_type q = 1u;
|
|
979
|
+
double_limb_type tt = u;
|
|
980
|
+
divide_subtract(q, u, v);
|
|
981
|
+
std::swap(u, v);
|
|
982
|
+
tt = y[0] + q * static_cast<double_limb_type>(y[1]);
|
|
983
|
+
//
|
|
984
|
+
// If calculation of y[2] would overflow a single limb, then we *must* terminate.
|
|
985
|
+
// Note that x[2] < y[2] so there is no need to check that as well:
|
|
986
|
+
//
|
|
987
|
+
if (tt >> bits_per_limb)
|
|
988
|
+
{
|
|
989
|
+
++i;
|
|
990
|
+
break;
|
|
991
|
+
}
|
|
992
|
+
x[2] = static_cast<limb_type>(x[0] + static_cast<double_limb_type>(q * x[1]));
|
|
993
|
+
y[2] = static_cast<limb_type>(tt);
|
|
994
|
+
++i;
|
|
995
|
+
if ((i & 1u) == 0)
|
|
996
|
+
{
|
|
997
|
+
BOOST_MP_ASSERT(u > v);
|
|
998
|
+
if ((v < x[2]) || ((u - v) < (static_cast<double_limb_type>(y[2]) + y[1])))
|
|
999
|
+
break;
|
|
1000
|
+
}
|
|
1001
|
+
else
|
|
1002
|
+
{
|
|
1003
|
+
BOOST_MP_ASSERT(u > v);
|
|
1004
|
+
if ((v < y[2]) || ((u - v) < (static_cast<double_limb_type>(x[2]) + x[1])))
|
|
1005
|
+
break;
|
|
1006
|
+
}
|
|
1007
|
+
#ifdef BOOST_MP_GCD_DEBUG
|
|
1008
|
+
BOOST_MP_ASSERT(q == UU / VV);
|
|
1009
|
+
UU %= VV;
|
|
1010
|
+
UU.swap(VV);
|
|
1011
|
+
#endif
|
|
1012
|
+
x[0] = x[1];
|
|
1013
|
+
x[1] = x[2];
|
|
1014
|
+
y[0] = y[1];
|
|
1015
|
+
y[1] = y[2];
|
|
1016
|
+
}
|
|
1017
|
+
if (i == 1)
|
|
1018
|
+
{
|
|
1019
|
+
// No change to U and V we've stalled!
|
|
1020
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
|
|
1021
|
+
eval_modulus(t, U, V);
|
|
1022
|
+
U.swap(V);
|
|
1023
|
+
V.swap(t);
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
//
|
|
1027
|
+
// Update U and V.
|
|
1028
|
+
// We have:
|
|
1029
|
+
//
|
|
1030
|
+
// U = x[0]U + y[0]V and
|
|
1031
|
+
// V = x[1]U + y[1]V.
|
|
1032
|
+
//
|
|
1033
|
+
// But since we track only absolute values of x and y
|
|
1034
|
+
// we have to take account of the implied signs and perform
|
|
1035
|
+
// the appropriate subtraction depending on the whether i is
|
|
1036
|
+
// even or odd:
|
|
1037
|
+
//
|
|
1038
|
+
std::size_t ts = U.size() + 1;
|
|
1039
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t1(storage, ts), t2(storage, ts), t3(storage, ts);
|
|
1040
|
+
eval_multiply(t1, U, x[0]);
|
|
1041
|
+
eval_multiply(t2, V, y[0]);
|
|
1042
|
+
eval_multiply(t3, U, x[1]);
|
|
1043
|
+
if ((i & 1u) == 0)
|
|
1044
|
+
{
|
|
1045
|
+
if (x[0] == 0)
|
|
1046
|
+
U = t2;
|
|
1047
|
+
else
|
|
1048
|
+
{
|
|
1049
|
+
BOOST_MP_ASSERT(t2.compare(t1) >= 0);
|
|
1050
|
+
eval_subtract(U, t2, t1);
|
|
1051
|
+
BOOST_MP_ASSERT(U.sign() == false);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
else
|
|
1055
|
+
{
|
|
1056
|
+
BOOST_MP_ASSERT(t1.compare(t2) >= 0);
|
|
1057
|
+
eval_subtract(U, t1, t2);
|
|
1058
|
+
BOOST_MP_ASSERT(U.sign() == false);
|
|
1059
|
+
}
|
|
1060
|
+
eval_multiply(t2, V, y[1]);
|
|
1061
|
+
if (i & 1u)
|
|
1062
|
+
{
|
|
1063
|
+
if (x[1] == 0)
|
|
1064
|
+
V = t2;
|
|
1065
|
+
else
|
|
1066
|
+
{
|
|
1067
|
+
BOOST_MP_ASSERT(t2.compare(t3) >= 0);
|
|
1068
|
+
eval_subtract(V, t2, t3);
|
|
1069
|
+
BOOST_MP_ASSERT(V.sign() == false);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
else
|
|
1073
|
+
{
|
|
1074
|
+
BOOST_MP_ASSERT(t3.compare(t2) >= 0);
|
|
1075
|
+
eval_subtract(V, t3, t2);
|
|
1076
|
+
BOOST_MP_ASSERT(V.sign() == false);
|
|
1077
|
+
}
|
|
1078
|
+
BOOST_MP_ASSERT(U.compare(V) >= 0);
|
|
1079
|
+
BOOST_MP_ASSERT(lu > eval_msb(U));
|
|
1080
|
+
#ifdef BOOST_MP_GCD_DEBUG
|
|
1081
|
+
|
|
1082
|
+
BOOST_MP_ASSERT(UU == U);
|
|
1083
|
+
BOOST_MP_ASSERT(VV == V);
|
|
1084
|
+
|
|
1085
|
+
extern std::size_t total_lehmer_gcd_calls;
|
|
1086
|
+
extern std::size_t total_lehmer_gcd_bits_saved;
|
|
1087
|
+
extern std::size_t total_lehmer_gcd_cycles;
|
|
1088
|
+
|
|
1089
|
+
++total_lehmer_gcd_calls;
|
|
1090
|
+
total_lehmer_gcd_bits_saved += lu - eval_msb(U);
|
|
1091
|
+
total_lehmer_gcd_cycles += i;
|
|
1092
|
+
#endif
|
|
1093
|
+
if (lu < 2048)
|
|
1094
|
+
{
|
|
1095
|
+
//
|
|
1096
|
+
// Since we have stripped all common powers of 2 from U and V at the start
|
|
1097
|
+
// if either are even at this point, we can remove stray powers of 2 now.
|
|
1098
|
+
// Note that it is not possible for *both* U and V to be even at this point.
|
|
1099
|
+
//
|
|
1100
|
+
// This has an adverse effect on performance for high bit counts, but has
|
|
1101
|
+
// a significant positive effect for smaller counts.
|
|
1102
|
+
//
|
|
1103
|
+
if ((U.limbs()[0] & 1u) == 0)
|
|
1104
|
+
{
|
|
1105
|
+
eval_right_shift(U, eval_lsb(U));
|
|
1106
|
+
if (U.compare(V) < 0)
|
|
1107
|
+
U.swap(V);
|
|
1108
|
+
}
|
|
1109
|
+
else if ((V.limbs()[0] & 1u) == 0)
|
|
1110
|
+
{
|
|
1111
|
+
eval_right_shift(V, eval_lsb(V));
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
storage.deallocate(ts * 3);
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
#endif
|
|
1118
|
+
|
|
1119
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
1120
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
|
|
1121
|
+
eval_gcd(
|
|
1122
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
|
|
1123
|
+
const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
|
|
1124
|
+
const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b)
|
|
1125
|
+
{
|
|
1126
|
+
using default_ops::eval_get_sign;
|
|
1127
|
+
using default_ops::eval_is_zero;
|
|
1128
|
+
using default_ops::eval_lsb;
|
|
1129
|
+
|
|
1130
|
+
if (a.size() == 1)
|
|
1131
|
+
{
|
|
1132
|
+
eval_gcd(result, b, *a.limbs());
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
1135
|
+
if (b.size() == 1)
|
|
1136
|
+
{
|
|
1137
|
+
eval_gcd(result, a, *b.limbs());
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
std::size_t temp_size = (std::max)(a.size(), b.size()) + 1;
|
|
1141
|
+
typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::scoped_shared_storage storage(a, temp_size * 6);
|
|
1142
|
+
|
|
1143
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> U(storage, temp_size);
|
|
1144
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> V(storage, temp_size);
|
|
1145
|
+
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(storage, temp_size);
|
|
1146
|
+
U = a;
|
|
1147
|
+
V = b;
|
|
1148
|
+
|
|
1149
|
+
int s = eval_get_sign(U);
|
|
1150
|
+
|
|
1151
|
+
/* GCD(0,x) := x */
|
|
1152
|
+
if (s < 0)
|
|
1153
|
+
{
|
|
1154
|
+
U.negate();
|
|
1155
|
+
}
|
|
1156
|
+
else if (s == 0)
|
|
1157
|
+
{
|
|
1158
|
+
result = V;
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
s = eval_get_sign(V);
|
|
1162
|
+
if (s < 0)
|
|
1163
|
+
{
|
|
1164
|
+
V.negate();
|
|
1165
|
+
}
|
|
1166
|
+
else if (s == 0)
|
|
1167
|
+
{
|
|
1168
|
+
result = U;
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
//
|
|
1172
|
+
// Remove common factors of 2:
|
|
1173
|
+
//
|
|
1174
|
+
std::size_t us = eval_lsb(U);
|
|
1175
|
+
std::size_t vs = eval_lsb(V);
|
|
1176
|
+
std::size_t shift = (std::min)(us, vs);
|
|
1177
|
+
if (us)
|
|
1178
|
+
eval_right_shift(U, us);
|
|
1179
|
+
if (vs)
|
|
1180
|
+
eval_right_shift(V, vs);
|
|
1181
|
+
|
|
1182
|
+
if (U.compare(V) < 0)
|
|
1183
|
+
U.swap(V);
|
|
1184
|
+
|
|
1185
|
+
while (!eval_is_zero(V))
|
|
1186
|
+
{
|
|
1187
|
+
if (U.size() <= 2)
|
|
1188
|
+
{
|
|
1189
|
+
//
|
|
1190
|
+
// Special case: if V has no more than 2 limbs
|
|
1191
|
+
// then we can reduce U and V to a pair of integers and perform
|
|
1192
|
+
// direct integer gcd:
|
|
1193
|
+
//
|
|
1194
|
+
if (U.size() == 1)
|
|
1195
|
+
U = eval_gcd(*V.limbs(), *U.limbs());
|
|
1196
|
+
else
|
|
1197
|
+
{
|
|
1198
|
+
double_limb_type i = U.limbs()[0] | (static_cast<double_limb_type>(U.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
|
|
1199
|
+
double_limb_type j = (V.size() == 1) ? *V.limbs() : V.limbs()[0] | (static_cast<double_limb_type>(V.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
|
|
1200
|
+
U = eval_gcd(i, j);
|
|
1201
|
+
}
|
|
1202
|
+
break;
|
|
1203
|
+
}
|
|
1204
|
+
std::size_t lu = eval_msb(U) + 1;
|
|
1205
|
+
std::size_t lv = eval_msb(V) + 1;
|
|
1206
|
+
#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
|
|
1207
|
+
if (!BOOST_MP_IS_CONST_EVALUATED(lu) && (lu - lv <= bits_per_limb / 2))
|
|
1208
|
+
#else
|
|
1209
|
+
if (lu - lv <= bits_per_limb / 2)
|
|
1210
|
+
#endif
|
|
1211
|
+
{
|
|
1212
|
+
eval_gcd_lehmer(U, V, lu, storage);
|
|
1213
|
+
}
|
|
1214
|
+
else
|
|
1215
|
+
{
|
|
1216
|
+
eval_modulus(t, U, V);
|
|
1217
|
+
U.swap(V);
|
|
1218
|
+
V.swap(t);
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
result = U;
|
|
1222
|
+
if (shift)
|
|
1223
|
+
eval_left_shift(result, shift);
|
|
1224
|
+
}
|
|
1225
|
+
//
|
|
1226
|
+
// Now again for trivial backends:
|
|
1227
|
+
//
|
|
1228
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
1229
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
|
|
1230
|
+
eval_gcd(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) noexcept
|
|
1231
|
+
{
|
|
1232
|
+
*result.limbs() = boost::multiprecision::detail::constexpr_gcd(*a.limbs(), *b.limbs());
|
|
1233
|
+
result.sign(false);
|
|
1234
|
+
}
|
|
1235
|
+
// This one is only enabled for unchecked cpp_int's, for checked int's we need the checking in the default version:
|
|
1236
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
1237
|
+
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (Checked1 == unchecked)>::type
|
|
1238
|
+
eval_lcm(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
|
|
1239
|
+
{
|
|
1240
|
+
*result.limbs() = boost::multiprecision::detail::constexpr_lcm(*a.limbs(), *b.limbs());
|
|
1241
|
+
result.normalize(); // result may overflow the specified number of bits
|
|
1242
|
+
result.sign(false);
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
inline void conversion_overflow(const std::integral_constant<int, checked>&)
|
|
1246
|
+
{
|
|
1247
|
+
BOOST_MP_THROW_EXCEPTION(std::overflow_error("Overflow in conversion to narrower type"));
|
|
1248
|
+
}
|
|
1249
|
+
inline BOOST_MP_CXX14_CONSTEXPR void conversion_overflow(const std::integral_constant<int, unchecked>&) {}
|
|
1250
|
+
|
|
1251
|
+
#if defined(__clang__) && defined(__MINGW32__)
|
|
1252
|
+
//
|
|
1253
|
+
// clang-11 on Mingw segfaults on conversion of __int128 -> float.
|
|
1254
|
+
// See: https://bugs.llvm.org/show_bug.cgi?id=48941
|
|
1255
|
+
// These workarounds pass everything through an intermediate uint64_t.
|
|
1256
|
+
//
|
|
1257
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
1258
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
1259
|
+
is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && std::is_same<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, double_limb_type>::value>::type
|
|
1260
|
+
eval_convert_to(float* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
|
|
1261
|
+
{
|
|
1262
|
+
float f = static_cast<std::uint64_t>((*val.limbs()) >> 64);
|
|
1263
|
+
*result = std::ldexp(f, 64);
|
|
1264
|
+
*result += static_cast<std::uint64_t>((*val.limbs()));
|
|
1265
|
+
if(val.sign())
|
|
1266
|
+
*result = -*result;
|
|
1267
|
+
}
|
|
1268
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
1269
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
1270
|
+
is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && std::is_same<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, double_limb_type>::value>::type
|
|
1271
|
+
eval_convert_to(double* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
|
|
1272
|
+
{
|
|
1273
|
+
float f = static_cast<std::uint64_t>((*val.limbs()) >> 64);
|
|
1274
|
+
*result = std::ldexp(f, 64);
|
|
1275
|
+
*result += static_cast<std::uint64_t>((*val.limbs()));
|
|
1276
|
+
if(val.sign())
|
|
1277
|
+
*result = -*result;
|
|
1278
|
+
}
|
|
1279
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
1280
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
1281
|
+
is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && std::is_same<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, double_limb_type>::value>::type
|
|
1282
|
+
eval_convert_to(long double* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
|
|
1283
|
+
{
|
|
1284
|
+
float f = static_cast<std::uint64_t>((*val.limbs()) >> 64);
|
|
1285
|
+
*result = std::ldexp(f, 64);
|
|
1286
|
+
*result += static_cast<std::uint64_t>((*val.limbs()));
|
|
1287
|
+
if(val.sign())
|
|
1288
|
+
*result = -*result;
|
|
1289
|
+
}
|
|
1290
|
+
#endif
|
|
1291
|
+
|
|
1292
|
+
template <class R, std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
1293
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
1294
|
+
is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && std::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value>::type
|
|
1295
|
+
eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
|
|
1296
|
+
{
|
|
1297
|
+
BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized)
|
|
1298
|
+
{
|
|
1299
|
+
using common_type = typename std::common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type;
|
|
1300
|
+
|
|
1301
|
+
if (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)()))
|
|
1302
|
+
{
|
|
1303
|
+
if (val.isneg())
|
|
1304
|
+
{
|
|
1305
|
+
check_is_negative(std::integral_constant < bool, (boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value) || (number_category<R>::value == number_kind_floating_point) > ());
|
|
1306
|
+
if (static_cast<common_type>(*val.limbs()) > -static_cast<common_type>((std::numeric_limits<R>::min)()))
|
|
1307
|
+
conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
|
|
1308
|
+
*result = (std::numeric_limits<R>::min)();
|
|
1309
|
+
}
|
|
1310
|
+
else
|
|
1311
|
+
{
|
|
1312
|
+
conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
|
|
1313
|
+
*result = boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value ? (std::numeric_limits<R>::max)() : static_cast<R>(*val.limbs());
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
else
|
|
1317
|
+
{
|
|
1318
|
+
*result = static_cast<R>(*val.limbs());
|
|
1319
|
+
if (val.isneg())
|
|
1320
|
+
{
|
|
1321
|
+
check_is_negative(std::integral_constant < bool, (boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value) || (number_category<R>::value == number_kind_floating_point) > ());
|
|
1322
|
+
*result = negate_integer(*result, std::integral_constant < bool, is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point) > ());
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
else
|
|
1327
|
+
{
|
|
1328
|
+
*result = static_cast<R>(*val.limbs());
|
|
1329
|
+
if (val.isneg())
|
|
1330
|
+
{
|
|
1331
|
+
check_is_negative(std::integral_constant<bool, (boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value) || (number_category<R>::value == number_kind_floating_point) > ());
|
|
1332
|
+
*result = negate_integer(*result, std::integral_constant<bool, is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point) > ());
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
template <class R, std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
1338
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
1339
|
+
is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && std::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value>::type
|
|
1340
|
+
eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
|
|
1341
|
+
{
|
|
1342
|
+
BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized)
|
|
1343
|
+
{
|
|
1344
|
+
using common_type = typename std::common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type;
|
|
1345
|
+
|
|
1346
|
+
if(static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)()))
|
|
1347
|
+
{
|
|
1348
|
+
conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
|
|
1349
|
+
*result = boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value ? (std::numeric_limits<R>::max)() : static_cast<R>(*val.limbs());
|
|
1350
|
+
}
|
|
1351
|
+
else
|
|
1352
|
+
*result = static_cast<R>(*val.limbs());
|
|
1353
|
+
}
|
|
1354
|
+
else
|
|
1355
|
+
*result = static_cast<R>(*val.limbs());
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
1359
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
|
|
1360
|
+
eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
|
|
1361
|
+
{
|
|
1362
|
+
using default_ops::eval_get_sign;
|
|
1363
|
+
if (eval_get_sign(a) == 0)
|
|
1364
|
+
{
|
|
1365
|
+
BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
|
|
1366
|
+
}
|
|
1367
|
+
if (a.sign())
|
|
1368
|
+
{
|
|
1369
|
+
BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
|
|
1370
|
+
}
|
|
1371
|
+
//
|
|
1372
|
+
// Find the index of the least significant bit within that limb:
|
|
1373
|
+
//
|
|
1374
|
+
return boost::multiprecision::detail::find_lsb(*a.limbs());
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
1378
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
|
|
1379
|
+
eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
|
|
1380
|
+
{
|
|
1381
|
+
//
|
|
1382
|
+
// Find the index of the least significant bit within that limb:
|
|
1383
|
+
//
|
|
1384
|
+
return boost::multiprecision::detail::find_msb(*a.limbs());
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
1388
|
+
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
|
|
1389
|
+
eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
|
|
1390
|
+
{
|
|
1391
|
+
using default_ops::eval_get_sign;
|
|
1392
|
+
if (eval_get_sign(a) == 0)
|
|
1393
|
+
{
|
|
1394
|
+
BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
|
|
1395
|
+
}
|
|
1396
|
+
if (a.sign())
|
|
1397
|
+
{
|
|
1398
|
+
BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
|
|
1399
|
+
}
|
|
1400
|
+
return eval_msb_imp(a);
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
1404
|
+
inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) noexcept
|
|
1405
|
+
{
|
|
1406
|
+
std::size_t result = 0;
|
|
1407
|
+
for (std::size_t i = 0; i < val.size(); ++i)
|
|
1408
|
+
{
|
|
1409
|
+
boost::multiprecision::detail::hash_combine(result, val.limbs()[i]);
|
|
1410
|
+
}
|
|
1411
|
+
boost::multiprecision::detail::hash_combine(result, val.sign());
|
|
1412
|
+
return result;
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
#ifdef BOOST_MSVC
|
|
1416
|
+
#pragma warning(pop)
|
|
1417
|
+
#endif
|
|
1418
|
+
|
|
1419
|
+
} // Namespace backends
|
|
1420
|
+
|
|
1421
|
+
namespace detail {
|
|
1422
|
+
|
|
1423
|
+
#ifndef BOOST_MP_STANDALONE
|
|
1424
|
+
template <typename T>
|
|
1425
|
+
inline BOOST_CXX14_CONSTEXPR T constexpr_gcd(T a, T b) noexcept
|
|
1426
|
+
{
|
|
1427
|
+
return boost::integer::gcd(a, b);
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
template <typename T>
|
|
1431
|
+
inline BOOST_CXX14_CONSTEXPR T constexpr_lcm(T a, T b) noexcept
|
|
1432
|
+
{
|
|
1433
|
+
return boost::integer::lcm(a, b);
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
#else
|
|
1437
|
+
|
|
1438
|
+
template <typename T>
|
|
1439
|
+
inline BOOST_CXX14_CONSTEXPR T constexpr_gcd(T a, T b) noexcept
|
|
1440
|
+
{
|
|
1441
|
+
return boost::multiprecision::backends::eval_gcd(a, b);
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
template <typename T>
|
|
1445
|
+
inline BOOST_CXX14_CONSTEXPR T constexpr_lcm(T a, T b) noexcept
|
|
1446
|
+
{
|
|
1447
|
+
const T ab_gcd = boost::multiprecision::detail::constexpr_gcd(a, b);
|
|
1448
|
+
return (a * b) / ab_gcd;
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
#endif // BOOST_MP_STANDALONE
|
|
1452
|
+
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
}} // Namespace boost::multiprecision
|
|
1456
|
+
|
|
1457
|
+
#endif
|