mqt-core 3.3.2__cp313-cp313t-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.cp313t-win_amd64.pyd +0 -0
- mqt/core/dd.pyi +1016 -0
- mqt/core/dd_evaluation.py +368 -0
- mqt/core/fomac.cp313t-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.cp313t-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.cp313t-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,2297 @@
|
|
|
1
|
+
////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright 2013 - 2022 John Maddock.
|
|
3
|
+
// Copyright 2022 Christopher Kormanyos.
|
|
4
|
+
// Distributed under the Boost Software License,
|
|
5
|
+
// Version 1.0. (See accompanying file LICENSE_1_0.txt
|
|
6
|
+
// or copy at https://www.boost.org/LICENSE_1_0.txt)
|
|
7
|
+
|
|
8
|
+
#ifndef BOOST_MP_CPP_BIN_FLOAT_HPP
|
|
9
|
+
#define BOOST_MP_CPP_BIN_FLOAT_HPP
|
|
10
|
+
|
|
11
|
+
#include <cmath>
|
|
12
|
+
#include <cstdint>
|
|
13
|
+
#include <limits>
|
|
14
|
+
#include <type_traits>
|
|
15
|
+
#include <boost/multiprecision/cpp_int.hpp>
|
|
16
|
+
#include <boost/multiprecision/integer.hpp>
|
|
17
|
+
#include <boost/multiprecision/detail/standalone_config.hpp>
|
|
18
|
+
#include <boost/multiprecision/detail/fpclassify.hpp>
|
|
19
|
+
#include <boost/multiprecision/detail/float_string_cvt.hpp>
|
|
20
|
+
#include <boost/multiprecision/traits/max_digits10.hpp>
|
|
21
|
+
#include <boost/multiprecision/detail/hash.hpp>
|
|
22
|
+
#include <boost/multiprecision/detail/no_exceptions_support.hpp>
|
|
23
|
+
#include <boost/multiprecision/detail/assert.hpp>
|
|
24
|
+
#include <boost/multiprecision/detail/float128_functions.hpp>
|
|
25
|
+
#include <boost/multiprecision/detail/functions/trunc.hpp>
|
|
26
|
+
|
|
27
|
+
//
|
|
28
|
+
// Some includes we need from Boost.Math, since we rely on that library to provide these functions:
|
|
29
|
+
//
|
|
30
|
+
#ifdef BOOST_MP_MATH_AVAILABLE
|
|
31
|
+
#include <boost/math/special_functions/asinh.hpp>
|
|
32
|
+
#include <boost/math/special_functions/acosh.hpp>
|
|
33
|
+
#include <boost/math/special_functions/atanh.hpp>
|
|
34
|
+
#include <boost/math/special_functions/cbrt.hpp>
|
|
35
|
+
#include <boost/math/special_functions/expm1.hpp>
|
|
36
|
+
#include <boost/math/special_functions/gamma.hpp>
|
|
37
|
+
#endif
|
|
38
|
+
|
|
39
|
+
#ifdef BOOST_HAS_FLOAT128
|
|
40
|
+
# if __has_include(<quadmath.h>)
|
|
41
|
+
# include <quadmath.h>
|
|
42
|
+
# define BOOST_MP_HAS_FLOAT128_SUPPORT
|
|
43
|
+
# endif
|
|
44
|
+
#endif
|
|
45
|
+
|
|
46
|
+
namespace boost {
|
|
47
|
+
namespace multiprecision {
|
|
48
|
+
namespace backends {
|
|
49
|
+
|
|
50
|
+
#ifdef BOOST_MSVC
|
|
51
|
+
#pragma warning(push)
|
|
52
|
+
#pragma warning(disable : 4522 6326) // multiple assignment operators specified, comparison of two constants
|
|
53
|
+
#endif
|
|
54
|
+
|
|
55
|
+
namespace detail {
|
|
56
|
+
|
|
57
|
+
template <class U>
|
|
58
|
+
inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<U>::value, bool>::type is_negative(U) { return false; }
|
|
59
|
+
template <class S>
|
|
60
|
+
inline typename std::enable_if< !boost::multiprecision::detail::is_unsigned<S>::value, bool>::type is_negative(S s) { return s < 0; }
|
|
61
|
+
|
|
62
|
+
template <class Float, std::ptrdiff_t, bool = number_category<Float>::value == number_kind_floating_point>
|
|
63
|
+
struct is_cpp_bin_float_implicitly_constructible_from_type
|
|
64
|
+
{
|
|
65
|
+
static constexpr bool value = false;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
template <class Float, std::ptrdiff_t bit_count>
|
|
69
|
+
struct is_cpp_bin_float_implicitly_constructible_from_type<Float, bit_count, true>
|
|
70
|
+
{
|
|
71
|
+
static constexpr bool value = (std::numeric_limits<Float>::digits <= static_cast<int>(bit_count)) && (std::numeric_limits<Float>::radix == 2) && std::numeric_limits<Float>::is_specialized
|
|
72
|
+
#ifdef BOOST_MP_HAS_FLOAT128_SUPPORT
|
|
73
|
+
&& !std::is_same<Float, float128_type>::value
|
|
74
|
+
#endif
|
|
75
|
+
&& (std::is_floating_point<Float>::value || is_number<Float>::value);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
template <class Float, std::ptrdiff_t, bool = number_category<Float>::value == number_kind_floating_point>
|
|
79
|
+
struct is_cpp_bin_float_explicitly_constructible_from_type
|
|
80
|
+
{
|
|
81
|
+
static constexpr bool value = false;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
template <class Float, std::ptrdiff_t bit_count>
|
|
85
|
+
struct is_cpp_bin_float_explicitly_constructible_from_type<Float, bit_count, true>
|
|
86
|
+
{
|
|
87
|
+
static constexpr bool value = (std::numeric_limits<Float>::digits > static_cast<int>(bit_count)) && (std::numeric_limits<Float>::radix == 2) && std::numeric_limits<Float>::is_specialized
|
|
88
|
+
#ifdef BOOST_MP_HAS_FLOAT128_SUPPORT
|
|
89
|
+
&& !std::is_same<Float, float128_type>::value
|
|
90
|
+
#endif
|
|
91
|
+
;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
} // namespace detail
|
|
95
|
+
|
|
96
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinExponent, Exponent MaxExponent>
|
|
97
|
+
class cpp_bin_float
|
|
98
|
+
{
|
|
99
|
+
public:
|
|
100
|
+
static constexpr unsigned bit_count = DigitBase == digit_base_2 ? Digits : (Digits * 1000uL) / 301uL + (((Digits * 1000uL) % 301) ? 2u : 1u);
|
|
101
|
+
using rep_type = cpp_int_backend<std::is_void<Allocator>::value ? bit_count : 0, bit_count, std::is_void<Allocator>::value ? unsigned_magnitude : signed_magnitude, unchecked, Allocator>;
|
|
102
|
+
using double_rep_type = cpp_int_backend<std::is_void<Allocator>::value ? 2 * bit_count : 0, 2 * bit_count, std::is_void<Allocator>::value ? unsigned_magnitude : signed_magnitude, unchecked, Allocator>;
|
|
103
|
+
|
|
104
|
+
using signed_types = typename rep_type::signed_types;
|
|
105
|
+
using unsigned_types = typename rep_type::unsigned_types;
|
|
106
|
+
using float_types = std::tuple<float, double, long double>;
|
|
107
|
+
using exponent_type = Exponent;
|
|
108
|
+
|
|
109
|
+
static constexpr exponent_type max_exponent_limit = (std::numeric_limits<exponent_type>::max)()- 2 * static_cast<exponent_type>(bit_count);
|
|
110
|
+
static constexpr exponent_type min_exponent_limit = (std::numeric_limits<exponent_type>::min)() + 2 * static_cast<exponent_type>(bit_count);
|
|
111
|
+
|
|
112
|
+
static_assert(MinExponent >= min_exponent_limit, "Template parameter MinExponent is too negative for our internal logic to function correctly, sorry!");
|
|
113
|
+
static_assert(MaxExponent <= max_exponent_limit, "Template parameter MaxExponent is too large for our internal logic to function correctly, sorry!");
|
|
114
|
+
static_assert(MinExponent <= 0, "Template parameter MinExponent can not be positive!");
|
|
115
|
+
static_assert(MaxExponent >= 0, "Template parameter MaxExponent can not be negative!");
|
|
116
|
+
|
|
117
|
+
static constexpr exponent_type max_exponent = MaxExponent == 0 ? max_exponent_limit : MaxExponent;
|
|
118
|
+
static constexpr exponent_type min_exponent = MinExponent == 0 ? min_exponent_limit : MinExponent;
|
|
119
|
+
|
|
120
|
+
static constexpr exponent_type exponent_zero = max_exponent + 1;
|
|
121
|
+
static constexpr exponent_type exponent_infinity = max_exponent + 2;
|
|
122
|
+
static constexpr exponent_type exponent_nan = max_exponent + 3;
|
|
123
|
+
|
|
124
|
+
private:
|
|
125
|
+
rep_type m_data;
|
|
126
|
+
exponent_type m_exponent;
|
|
127
|
+
bool m_sign;
|
|
128
|
+
|
|
129
|
+
public:
|
|
130
|
+
cpp_bin_float() noexcept(noexcept(rep_type())) : m_data(), m_exponent(exponent_zero), m_sign(false) {}
|
|
131
|
+
|
|
132
|
+
cpp_bin_float(const cpp_bin_float& o) noexcept(noexcept(rep_type(std::declval<const rep_type&>())))
|
|
133
|
+
: m_data(o.m_data), m_exponent(o.m_exponent), m_sign(o.m_sign) {}
|
|
134
|
+
|
|
135
|
+
template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
|
|
136
|
+
cpp_bin_float(const cpp_bin_float<D, B, A, E, MinE, MaxE>& o, typename std::enable_if<(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = nullptr)
|
|
137
|
+
{
|
|
138
|
+
*this = o;
|
|
139
|
+
}
|
|
140
|
+
template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
|
|
141
|
+
explicit cpp_bin_float(const cpp_bin_float<D, B, A, E, MinE, MaxE>& o, typename std::enable_if< !(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = nullptr)
|
|
142
|
+
: m_exponent(o.exponent()), m_sign(o.sign())
|
|
143
|
+
{
|
|
144
|
+
*this = o;
|
|
145
|
+
}
|
|
146
|
+
// rvalue copy:
|
|
147
|
+
template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
|
|
148
|
+
cpp_bin_float(cpp_bin_float<D, B, A, E, MinE, MaxE>&& o, typename std::enable_if<(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = nullptr)noexcept(noexcept(rep_type(std::declval<rep_type&&>())))
|
|
149
|
+
{
|
|
150
|
+
*this = std::move(o);
|
|
151
|
+
}
|
|
152
|
+
template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
|
|
153
|
+
explicit cpp_bin_float(cpp_bin_float<D, B, A, E, MinE, MaxE>&& o, typename std::enable_if< !(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = nullptr) noexcept(noexcept(rep_type(std::declval<rep_type&&>())))
|
|
154
|
+
: m_exponent(o.exponent()), m_sign(o.sign())
|
|
155
|
+
{
|
|
156
|
+
*this = std::move(o);
|
|
157
|
+
}
|
|
158
|
+
template <class Float>
|
|
159
|
+
cpp_bin_float(const Float& f,
|
|
160
|
+
typename std::enable_if<detail::is_cpp_bin_float_implicitly_constructible_from_type<Float, static_cast<std::ptrdiff_t>(bit_count)>::value>::type const* = nullptr)
|
|
161
|
+
: m_data(), m_exponent(0), m_sign(false)
|
|
162
|
+
{
|
|
163
|
+
this->assign_float(f);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
template <class Float>
|
|
167
|
+
explicit cpp_bin_float(const Float& f,
|
|
168
|
+
typename std::enable_if<detail::is_cpp_bin_float_explicitly_constructible_from_type<Float, static_cast<std::ptrdiff_t>(bit_count)>::value>::type const* = nullptr)
|
|
169
|
+
: m_data(), m_exponent(0), m_sign(false)
|
|
170
|
+
{
|
|
171
|
+
this->assign_float(f);
|
|
172
|
+
}
|
|
173
|
+
#ifdef BOOST_MP_HAS_FLOAT128_SUPPORT
|
|
174
|
+
template <class Float>
|
|
175
|
+
cpp_bin_float(const Float& f,
|
|
176
|
+
typename std::enable_if<
|
|
177
|
+
std::is_same<Float, float128_type>::value && (static_cast<int>(bit_count) >= 113)>::type const* = nullptr)
|
|
178
|
+
: m_data(), m_exponent(0), m_sign(false)
|
|
179
|
+
{
|
|
180
|
+
this->assign_float(f);
|
|
181
|
+
}
|
|
182
|
+
template <class Float>
|
|
183
|
+
explicit cpp_bin_float(const Float& f,
|
|
184
|
+
typename std::enable_if<
|
|
185
|
+
std::is_same<Float, float128_type>::value && (static_cast<int>(bit_count) < 113)>::type const* = nullptr)
|
|
186
|
+
: m_data(), m_exponent(0), m_sign(false)
|
|
187
|
+
{
|
|
188
|
+
this->assign_float(f);
|
|
189
|
+
}
|
|
190
|
+
#endif
|
|
191
|
+
cpp_bin_float& operator=(const cpp_bin_float& o) noexcept(noexcept(std::declval<rep_type&>() = std::declval<const rep_type&>()))
|
|
192
|
+
{
|
|
193
|
+
m_data = o.m_data;
|
|
194
|
+
m_exponent = o.m_exponent;
|
|
195
|
+
m_sign = o.m_sign;
|
|
196
|
+
return *this;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
template <class A, class E, E MinE, E MaxE>
|
|
200
|
+
cpp_bin_float& operator=(const cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>& o) noexcept(noexcept(std::declval<rep_type&>() = std::declval<const rep_type&>()))
|
|
201
|
+
{
|
|
202
|
+
m_data = o.bits();
|
|
203
|
+
m_sign = o.sign();
|
|
204
|
+
if (o.exponent() == cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>::exponent_zero)
|
|
205
|
+
m_exponent = exponent_zero;
|
|
206
|
+
else if (o.exponent() == cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>::exponent_nan)
|
|
207
|
+
m_exponent = exponent_nan;
|
|
208
|
+
else if (o.exponent() == cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>::exponent_infinity)
|
|
209
|
+
m_exponent = exponent_infinity;
|
|
210
|
+
else if (o.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
|
|
211
|
+
{
|
|
212
|
+
// Overflow:
|
|
213
|
+
exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
|
|
214
|
+
bits() = static_cast<limb_type>(0u);
|
|
215
|
+
}
|
|
216
|
+
else if (o.exponent() < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
|
|
217
|
+
{
|
|
218
|
+
// Underflow:
|
|
219
|
+
exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
|
220
|
+
bits() = static_cast<limb_type>(0u);
|
|
221
|
+
}
|
|
222
|
+
else
|
|
223
|
+
m_exponent = o.exponent();
|
|
224
|
+
return *this;
|
|
225
|
+
}
|
|
226
|
+
// rvalue copy:
|
|
227
|
+
template <class A, class E, E MinE, E MaxE>
|
|
228
|
+
cpp_bin_float& operator=(cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>&& o) noexcept(noexcept(std::declval<rep_type&>() = std::declval<rep_type&&>()))
|
|
229
|
+
{
|
|
230
|
+
m_data = std::move(o.bits());
|
|
231
|
+
m_sign = o.sign();
|
|
232
|
+
if (o.exponent() == cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>::exponent_zero)
|
|
233
|
+
m_exponent = exponent_zero;
|
|
234
|
+
else if (o.exponent() == cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>::exponent_nan)
|
|
235
|
+
m_exponent = exponent_nan;
|
|
236
|
+
else if (o.exponent() == cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>::exponent_infinity)
|
|
237
|
+
m_exponent = exponent_infinity;
|
|
238
|
+
else if (o.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
|
|
239
|
+
{
|
|
240
|
+
// Overflow:
|
|
241
|
+
exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
|
|
242
|
+
bits() = static_cast<limb_type>(0u);
|
|
243
|
+
}
|
|
244
|
+
else if (o.exponent() < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
|
|
245
|
+
{
|
|
246
|
+
// Underflow:
|
|
247
|
+
exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
|
248
|
+
bits() = static_cast<limb_type>(0u);
|
|
249
|
+
}
|
|
250
|
+
else
|
|
251
|
+
m_exponent = o.exponent();
|
|
252
|
+
return *this;
|
|
253
|
+
}
|
|
254
|
+
template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
|
|
255
|
+
cpp_bin_float& operator=(const cpp_bin_float<D, B, A, E, MinE, MaxE>& f)
|
|
256
|
+
{
|
|
257
|
+
switch (eval_fpclassify(f))
|
|
258
|
+
{
|
|
259
|
+
case FP_ZERO:
|
|
260
|
+
m_data = limb_type(0);
|
|
261
|
+
m_sign = f.sign();
|
|
262
|
+
m_exponent = exponent_zero;
|
|
263
|
+
break;
|
|
264
|
+
case FP_NAN:
|
|
265
|
+
m_data = limb_type(0);
|
|
266
|
+
m_sign = false;
|
|
267
|
+
m_exponent = exponent_nan;
|
|
268
|
+
break;
|
|
269
|
+
;
|
|
270
|
+
case FP_INFINITE:
|
|
271
|
+
m_data = limb_type(0);
|
|
272
|
+
m_sign = f.sign();
|
|
273
|
+
m_exponent = exponent_infinity;
|
|
274
|
+
break;
|
|
275
|
+
default:
|
|
276
|
+
typename cpp_bin_float<D, B, A, E, MinE, MaxE>::rep_type b(f.bits());
|
|
277
|
+
this->exponent() = f.exponent() + (E)bit_count - (E)cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count;
|
|
278
|
+
this->sign() = f.sign();
|
|
279
|
+
copy_and_round(*this, b);
|
|
280
|
+
}
|
|
281
|
+
return *this;
|
|
282
|
+
}
|
|
283
|
+
#ifdef BOOST_MP_HAS_FLOAT128_SUPPORT
|
|
284
|
+
template <class Float>
|
|
285
|
+
typename std::enable_if<
|
|
286
|
+
(number_category<Float>::value == number_kind_floating_point)
|
|
287
|
+
//&& (std::numeric_limits<Float>::digits <= static_cast<int>(bit_count))
|
|
288
|
+
&& ((std::numeric_limits<Float>::radix == 2) || (std::is_same<Float, float128_type>::value)),
|
|
289
|
+
cpp_bin_float&>::type
|
|
290
|
+
operator=(const Float& f)
|
|
291
|
+
#else
|
|
292
|
+
template <class Float>
|
|
293
|
+
typename std::enable_if<
|
|
294
|
+
(number_category<Float>::value == number_kind_floating_point)
|
|
295
|
+
//&& (std::numeric_limits<Float>::digits <= static_cast<int>(bit_count))
|
|
296
|
+
&& (std::numeric_limits<Float>::radix == 2),
|
|
297
|
+
cpp_bin_float&>::type
|
|
298
|
+
operator=(const Float& f)
|
|
299
|
+
#endif
|
|
300
|
+
{
|
|
301
|
+
return assign_float(f);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
#ifdef BOOST_MP_HAS_FLOAT128_SUPPORT
|
|
305
|
+
template <class Float>
|
|
306
|
+
typename std::enable_if<std::is_same<Float, float128_type>::value && (std::numeric_limits<Float>::digits > Digits), cpp_bin_float&>::type assign_float(Float f)
|
|
307
|
+
{
|
|
308
|
+
cpp_bin_float<113, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> bf(f);
|
|
309
|
+
return *this = bf;
|
|
310
|
+
}
|
|
311
|
+
template <class Float>
|
|
312
|
+
typename std::enable_if<std::is_same<Float, float128_type>::value && (std::numeric_limits<Float>::digits <= Digits), cpp_bin_float&>::type assign_float(Float f)
|
|
313
|
+
{
|
|
314
|
+
using default_ops::eval_add;
|
|
315
|
+
using bf_int_type = typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type;
|
|
316
|
+
if (f == 0)
|
|
317
|
+
{
|
|
318
|
+
m_data = limb_type(0);
|
|
319
|
+
m_sign = (signbitq(f) > 0);
|
|
320
|
+
m_exponent = exponent_zero;
|
|
321
|
+
return *this;
|
|
322
|
+
}
|
|
323
|
+
else if (isnanq(f))
|
|
324
|
+
{
|
|
325
|
+
m_data = limb_type(0);
|
|
326
|
+
m_sign = false;
|
|
327
|
+
m_exponent = exponent_nan;
|
|
328
|
+
return *this;
|
|
329
|
+
}
|
|
330
|
+
else if (isinfq(f))
|
|
331
|
+
{
|
|
332
|
+
m_data = limb_type(0);
|
|
333
|
+
m_sign = (f < 0);
|
|
334
|
+
m_exponent = exponent_infinity;
|
|
335
|
+
return *this;
|
|
336
|
+
}
|
|
337
|
+
if (f < 0)
|
|
338
|
+
{
|
|
339
|
+
*this = -f;
|
|
340
|
+
this->negate();
|
|
341
|
+
return *this;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
using ui_type = typename std::tuple_element<0, unsigned_types>::type;
|
|
345
|
+
m_data = static_cast<ui_type>(0u);
|
|
346
|
+
m_sign = false;
|
|
347
|
+
m_exponent = 0;
|
|
348
|
+
|
|
349
|
+
constexpr std::ptrdiff_t bits = sizeof(int) * CHAR_BIT - 1 < MaxExponent - 1 ? sizeof(int) * CHAR_BIT - 1 : 3;
|
|
350
|
+
int e;
|
|
351
|
+
f = frexpq(f, &e);
|
|
352
|
+
while (f)
|
|
353
|
+
{
|
|
354
|
+
f = ldexpq(f, bits);
|
|
355
|
+
e -= bits;
|
|
356
|
+
int ipart = static_cast<int>(truncq(f));
|
|
357
|
+
f -= ipart;
|
|
358
|
+
m_exponent += bits;
|
|
359
|
+
cpp_bin_float t;
|
|
360
|
+
t = static_cast<bf_int_type>(ipart);
|
|
361
|
+
eval_add(*this, t);
|
|
362
|
+
}
|
|
363
|
+
m_exponent += static_cast<Exponent>(e);
|
|
364
|
+
if (m_exponent > max_exponent)
|
|
365
|
+
{
|
|
366
|
+
m_exponent = exponent_infinity;
|
|
367
|
+
m_data = static_cast<ui_type>(0u);
|
|
368
|
+
}
|
|
369
|
+
else if (m_exponent < min_exponent)
|
|
370
|
+
{
|
|
371
|
+
m_exponent = exponent_zero;
|
|
372
|
+
m_data = static_cast<ui_type>(0u);
|
|
373
|
+
}
|
|
374
|
+
return *this;
|
|
375
|
+
}
|
|
376
|
+
#endif
|
|
377
|
+
#ifdef BOOST_MP_HAS_FLOAT128_SUPPORT
|
|
378
|
+
template <class Float>
|
|
379
|
+
typename std::enable_if<std::is_floating_point<Float>::value && !std::is_same<Float, float128_type>::value && (std::numeric_limits<Float>::digits > Digits), cpp_bin_float&>::type assign_float(Float f)
|
|
380
|
+
#else
|
|
381
|
+
template <class Float>
|
|
382
|
+
typename std::enable_if<std::is_floating_point<Float>::value && (std::numeric_limits<Float>::digits > Digits), cpp_bin_float&>::type assign_float(Float f)
|
|
383
|
+
#endif
|
|
384
|
+
{
|
|
385
|
+
cpp_bin_float<std::numeric_limits<Float>::digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> bf(f);
|
|
386
|
+
return *this = bf;
|
|
387
|
+
}
|
|
388
|
+
#ifdef BOOST_MP_HAS_FLOAT128_SUPPORT
|
|
389
|
+
template <class Float>
|
|
390
|
+
typename std::enable_if<std::is_floating_point<Float>::value && !std::is_same<Float, float128_type>::value && (std::numeric_limits<Float>::digits <= Digits), cpp_bin_float&>::type assign_float(Float f)
|
|
391
|
+
#else
|
|
392
|
+
template <class Float>
|
|
393
|
+
typename std::enable_if<std::is_floating_point<Float>::value && (std::numeric_limits<Float>::digits <= Digits), cpp_bin_float&>::type assign_float(Float f)
|
|
394
|
+
#endif
|
|
395
|
+
{
|
|
396
|
+
using std::frexp;
|
|
397
|
+
using std::ldexp;
|
|
398
|
+
using std::signbit;
|
|
399
|
+
using default_ops::eval_add;
|
|
400
|
+
using bf_int_type = typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type;
|
|
401
|
+
|
|
402
|
+
switch (BOOST_MP_FPCLASSIFY(f))
|
|
403
|
+
{
|
|
404
|
+
case FP_ZERO:
|
|
405
|
+
m_data = limb_type(0);
|
|
406
|
+
m_sign = ((signbit)(f));
|
|
407
|
+
m_exponent = exponent_zero;
|
|
408
|
+
return *this;
|
|
409
|
+
case FP_NAN:
|
|
410
|
+
m_data = limb_type(0);
|
|
411
|
+
m_sign = false;
|
|
412
|
+
m_exponent = exponent_nan;
|
|
413
|
+
return *this;
|
|
414
|
+
case FP_INFINITE:
|
|
415
|
+
m_data = limb_type(0);
|
|
416
|
+
m_sign = (f < 0);
|
|
417
|
+
m_exponent = exponent_infinity;
|
|
418
|
+
return *this;
|
|
419
|
+
}
|
|
420
|
+
if (f < 0)
|
|
421
|
+
{
|
|
422
|
+
*this = -f;
|
|
423
|
+
this->negate();
|
|
424
|
+
return *this;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
using ui_type = typename std::tuple_element<0, unsigned_types>::type;
|
|
428
|
+
m_data = static_cast<ui_type>(0u);
|
|
429
|
+
m_sign = false;
|
|
430
|
+
m_exponent = 0;
|
|
431
|
+
|
|
432
|
+
//
|
|
433
|
+
// This code picks off the bits in f a few at a time and injects them into *this.
|
|
434
|
+
// It does not do roundingm so we must have more digits precision in *this than
|
|
435
|
+
// in the floating point value (the normal situation, unless we're emulating another
|
|
436
|
+
// type like float16_t).
|
|
437
|
+
//
|
|
438
|
+
constexpr std::ptrdiff_t bits = static_cast<std::ptrdiff_t>(sizeof(int) * CHAR_BIT - 1) < static_cast<std::ptrdiff_t>(MaxExponent - 1) ? static_cast<std::ptrdiff_t>(sizeof(int) * CHAR_BIT - 1) : 3;
|
|
439
|
+
int e;
|
|
440
|
+
f = frexp(f, &e);
|
|
441
|
+
while (f != static_cast<Float>(0.0F))
|
|
442
|
+
{
|
|
443
|
+
f = ldexp(f, bits);
|
|
444
|
+
e -= static_cast<int>(bits);
|
|
445
|
+
int ipart = boost::multiprecision::detail::itrunc(f);
|
|
446
|
+
f -= static_cast<Float>(ipart);
|
|
447
|
+
m_exponent += static_cast<exponent_type>(bits);
|
|
448
|
+
cpp_bin_float t;
|
|
449
|
+
t = static_cast<bf_int_type>(ipart);
|
|
450
|
+
eval_add(*this, t);
|
|
451
|
+
}
|
|
452
|
+
m_exponent += static_cast<Exponent>(e);
|
|
453
|
+
if (m_exponent > max_exponent)
|
|
454
|
+
{
|
|
455
|
+
m_exponent = exponent_infinity;
|
|
456
|
+
m_data = static_cast<ui_type>(0u);
|
|
457
|
+
}
|
|
458
|
+
else if(m_exponent < min_exponent)
|
|
459
|
+
{
|
|
460
|
+
m_exponent = exponent_zero;
|
|
461
|
+
m_data = static_cast<ui_type>(0u);
|
|
462
|
+
}
|
|
463
|
+
return *this;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
template <class Float>
|
|
467
|
+
typename std::enable_if<
|
|
468
|
+
(number_category<Float>::value == number_kind_floating_point) && !std::is_floating_point<Float>::value && (number_category<Float>::value == number_kind_floating_point),
|
|
469
|
+
cpp_bin_float&>::type
|
|
470
|
+
assign_float(Float f)
|
|
471
|
+
{
|
|
472
|
+
using default_ops::eval_add;
|
|
473
|
+
using default_ops::eval_convert_to;
|
|
474
|
+
using default_ops::eval_get_sign;
|
|
475
|
+
using default_ops::eval_subtract;
|
|
476
|
+
|
|
477
|
+
using f_int_type = typename boost::multiprecision::detail::canonical<int, Float>::type ;
|
|
478
|
+
using bf_int_type = typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type;
|
|
479
|
+
|
|
480
|
+
switch (eval_fpclassify(f))
|
|
481
|
+
{
|
|
482
|
+
case FP_ZERO:
|
|
483
|
+
m_data = limb_type(0);
|
|
484
|
+
m_sign = (eval_get_sign(f) > 0);
|
|
485
|
+
m_exponent = exponent_zero;
|
|
486
|
+
return *this;
|
|
487
|
+
case FP_NAN:
|
|
488
|
+
m_data = limb_type(0);
|
|
489
|
+
m_sign = false;
|
|
490
|
+
m_exponent = exponent_nan;
|
|
491
|
+
return *this;
|
|
492
|
+
case FP_INFINITE:
|
|
493
|
+
m_data = limb_type(0);
|
|
494
|
+
m_sign = eval_get_sign(f) < 0;
|
|
495
|
+
m_exponent = exponent_infinity;
|
|
496
|
+
return *this;
|
|
497
|
+
}
|
|
498
|
+
if (eval_get_sign(f) < 0)
|
|
499
|
+
{
|
|
500
|
+
f.negate();
|
|
501
|
+
assign_float(f);
|
|
502
|
+
this->negate();
|
|
503
|
+
return *this;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
using ui_type = typename std::tuple_element<0, unsigned_types>::type;
|
|
507
|
+
m_data = static_cast<ui_type>(0u);
|
|
508
|
+
m_sign = false;
|
|
509
|
+
m_exponent = 0;
|
|
510
|
+
|
|
511
|
+
constexpr std::ptrdiff_t bits = sizeof(int) * CHAR_BIT - 1;
|
|
512
|
+
int e;
|
|
513
|
+
eval_frexp(f, f, &e);
|
|
514
|
+
while (eval_get_sign(f) != 0)
|
|
515
|
+
{
|
|
516
|
+
eval_ldexp(f, f, bits);
|
|
517
|
+
e -= bits;
|
|
518
|
+
int ipart;
|
|
519
|
+
eval_convert_to(&ipart, f);
|
|
520
|
+
eval_subtract(f, static_cast<f_int_type>(ipart));
|
|
521
|
+
m_exponent += bits;
|
|
522
|
+
eval_add(*this, static_cast<bf_int_type>(ipart));
|
|
523
|
+
}
|
|
524
|
+
m_exponent += e;
|
|
525
|
+
if (m_exponent > max_exponent)
|
|
526
|
+
m_exponent = exponent_infinity;
|
|
527
|
+
if (m_exponent < min_exponent)
|
|
528
|
+
{
|
|
529
|
+
m_data = limb_type(0u);
|
|
530
|
+
m_exponent = exponent_zero;
|
|
531
|
+
m_sign = (eval_get_sign(f) > 0);
|
|
532
|
+
}
|
|
533
|
+
else if (eval_get_sign(m_data) == 0)
|
|
534
|
+
{
|
|
535
|
+
m_exponent = exponent_zero;
|
|
536
|
+
m_sign = (eval_get_sign(f) > 0);
|
|
537
|
+
}
|
|
538
|
+
return *this;
|
|
539
|
+
}
|
|
540
|
+
template <class B, expression_template_option et>
|
|
541
|
+
cpp_bin_float& assign_float(const number<B, et>& f)
|
|
542
|
+
{
|
|
543
|
+
return assign_float(f.backend());
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
template <class I>
|
|
547
|
+
typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value, cpp_bin_float&>::type operator=(const I& i)
|
|
548
|
+
{
|
|
549
|
+
using default_ops::eval_bit_test;
|
|
550
|
+
if (!i)
|
|
551
|
+
{
|
|
552
|
+
m_data = static_cast<limb_type>(0);
|
|
553
|
+
m_exponent = exponent_zero;
|
|
554
|
+
m_sign = false;
|
|
555
|
+
}
|
|
556
|
+
else
|
|
557
|
+
{
|
|
558
|
+
using ui_type = typename boost::multiprecision::detail::make_unsigned<I>::type ;
|
|
559
|
+
ui_type fi = static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(i));
|
|
560
|
+
using ar_type = typename boost::multiprecision::detail::canonical<ui_type, rep_type>::type;
|
|
561
|
+
m_data = static_cast<ar_type>(fi);
|
|
562
|
+
std::size_t shift = msb(fi);
|
|
563
|
+
if (shift > max_exponent)
|
|
564
|
+
{
|
|
565
|
+
m_exponent = exponent_infinity;
|
|
566
|
+
m_data = static_cast<limb_type>(0);
|
|
567
|
+
}
|
|
568
|
+
else if (shift >= bit_count)
|
|
569
|
+
{
|
|
570
|
+
m_exponent = static_cast<Exponent>(shift);
|
|
571
|
+
m_data = static_cast<ar_type>(fi >> (shift + 1 - bit_count));
|
|
572
|
+
}
|
|
573
|
+
else
|
|
574
|
+
{
|
|
575
|
+
m_exponent = static_cast<Exponent>(shift);
|
|
576
|
+
eval_left_shift(m_data, bit_count - shift - 1);
|
|
577
|
+
}
|
|
578
|
+
BOOST_MP_ASSERT((m_exponent == exponent_infinity) || eval_bit_test(m_data, bit_count - 1));
|
|
579
|
+
m_sign = detail::is_negative(i);
|
|
580
|
+
}
|
|
581
|
+
return *this;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
cpp_bin_float& operator=(const char* s);
|
|
585
|
+
|
|
586
|
+
void swap(cpp_bin_float& o) noexcept
|
|
587
|
+
{
|
|
588
|
+
m_data.swap(o.m_data);
|
|
589
|
+
std::swap(m_exponent, o.m_exponent);
|
|
590
|
+
std::swap(m_sign, o.m_sign);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
std::string str(std::streamsize dig, std::ios_base::fmtflags f) const;
|
|
594
|
+
|
|
595
|
+
void negate()
|
|
596
|
+
{
|
|
597
|
+
if (m_exponent != exponent_nan)
|
|
598
|
+
m_sign = !m_sign;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
int compare(const cpp_bin_float& o) const noexcept
|
|
602
|
+
{
|
|
603
|
+
if (m_sign != o.m_sign)
|
|
604
|
+
return (m_exponent == exponent_zero) && (m_exponent == o.m_exponent) ? 0 : m_sign ? -1 : 1;
|
|
605
|
+
int result;
|
|
606
|
+
if (m_exponent == exponent_nan)
|
|
607
|
+
return -1;
|
|
608
|
+
else if (m_exponent != o.m_exponent)
|
|
609
|
+
{
|
|
610
|
+
if (m_exponent == exponent_zero)
|
|
611
|
+
result = -1;
|
|
612
|
+
else if (o.m_exponent == exponent_zero)
|
|
613
|
+
result = 1;
|
|
614
|
+
else
|
|
615
|
+
result = m_exponent > o.m_exponent ? 1 : -1;
|
|
616
|
+
}
|
|
617
|
+
else
|
|
618
|
+
result = m_data.compare(o.m_data);
|
|
619
|
+
if (m_sign)
|
|
620
|
+
result = -result;
|
|
621
|
+
return result;
|
|
622
|
+
}
|
|
623
|
+
template <class A>
|
|
624
|
+
int compare(const A& o) const noexcept
|
|
625
|
+
{
|
|
626
|
+
cpp_bin_float b;
|
|
627
|
+
b = o;
|
|
628
|
+
return compare(b);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
rep_type& bits() { return m_data; }
|
|
632
|
+
const rep_type& bits() const { return m_data; }
|
|
633
|
+
exponent_type& exponent() { return m_exponent; }
|
|
634
|
+
const exponent_type& exponent() const { return m_exponent; }
|
|
635
|
+
bool& sign() { return m_sign; }
|
|
636
|
+
const bool& sign() const { return m_sign; }
|
|
637
|
+
void check_invariants()
|
|
638
|
+
{
|
|
639
|
+
using default_ops::eval_bit_test;
|
|
640
|
+
using default_ops::eval_is_zero;
|
|
641
|
+
if ((m_exponent <= max_exponent) && (m_exponent >= min_exponent))
|
|
642
|
+
{
|
|
643
|
+
BOOST_MP_ASSERT(eval_bit_test(m_data, bit_count - 1));
|
|
644
|
+
}
|
|
645
|
+
else
|
|
646
|
+
{
|
|
647
|
+
BOOST_MP_ASSERT(m_exponent > max_exponent);
|
|
648
|
+
BOOST_MP_ASSERT(m_exponent <= exponent_nan);
|
|
649
|
+
BOOST_MP_ASSERT(eval_is_zero(m_data));
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
#ifndef BOOST_MP_STANDALONE
|
|
654
|
+
template <class Archive>
|
|
655
|
+
void serialize(Archive& ar, const unsigned int /*version*/)
|
|
656
|
+
{
|
|
657
|
+
ar& boost::make_nvp("data", m_data);
|
|
658
|
+
ar& boost::make_nvp("exponent", m_exponent);
|
|
659
|
+
ar& boost::make_nvp("sign", m_sign);
|
|
660
|
+
}
|
|
661
|
+
#endif
|
|
662
|
+
};
|
|
663
|
+
|
|
664
|
+
#ifdef BOOST_MSVC
|
|
665
|
+
#pragma warning(pop)
|
|
666
|
+
#endif
|
|
667
|
+
|
|
668
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class Int>
|
|
669
|
+
inline void copy_and_round(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, Int& arg, std::ptrdiff_t bits_to_keep = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
|
|
670
|
+
{
|
|
671
|
+
// Precondition: exponent of res must have been set before this function is called
|
|
672
|
+
// as we may need to adjust it based on how many bits_to_keep in arg are set.
|
|
673
|
+
using default_ops::eval_bit_test;
|
|
674
|
+
using default_ops::eval_get_sign;
|
|
675
|
+
using default_ops::eval_increment;
|
|
676
|
+
using default_ops::eval_left_shift;
|
|
677
|
+
using default_ops::eval_lsb;
|
|
678
|
+
using default_ops::eval_msb;
|
|
679
|
+
using default_ops::eval_right_shift;
|
|
680
|
+
|
|
681
|
+
// cancellation may have resulted in arg being all zeros:
|
|
682
|
+
if (eval_get_sign(arg) == 0)
|
|
683
|
+
{
|
|
684
|
+
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
|
685
|
+
res.sign() = false;
|
|
686
|
+
res.bits() = static_cast<limb_type>(0u);
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
std::ptrdiff_t msb = static_cast<std::ptrdiff_t>(eval_msb(arg));
|
|
690
|
+
if (static_cast<std::ptrdiff_t >(bits_to_keep) > msb + 1)
|
|
691
|
+
{
|
|
692
|
+
// Must have had cancellation in subtraction,
|
|
693
|
+
// or be converting from a narrower type, so shift left:
|
|
694
|
+
res.bits() = arg;
|
|
695
|
+
eval_left_shift(res.bits(), static_cast<double_limb_type>(bits_to_keep - msb - 1));
|
|
696
|
+
res.exponent() -= static_cast<Exponent>(bits_to_keep - msb - 1);
|
|
697
|
+
}
|
|
698
|
+
else if (static_cast<std::ptrdiff_t >(bits_to_keep) < msb + 1)
|
|
699
|
+
{
|
|
700
|
+
// We have more bits_to_keep than we need, so round as required,
|
|
701
|
+
// first get the rounding bit:
|
|
702
|
+
bool roundup = eval_bit_test(arg, static_cast<std::size_t>(msb - bits_to_keep));
|
|
703
|
+
// Then check for a tie:
|
|
704
|
+
if (roundup && (msb - bits_to_keep == static_cast<std::ptrdiff_t>(eval_lsb(arg))))
|
|
705
|
+
{
|
|
706
|
+
// Ties round towards even:
|
|
707
|
+
if (!eval_bit_test(arg, static_cast<std::size_t>(msb - bits_to_keep + 1)))
|
|
708
|
+
roundup = false;
|
|
709
|
+
}
|
|
710
|
+
// Shift off the bits_to_keep we don't need:
|
|
711
|
+
eval_right_shift(arg, static_cast<double_limb_type>(msb - bits_to_keep + 1));
|
|
712
|
+
res.exponent() += static_cast<Exponent>(msb - bits_to_keep + 1);
|
|
713
|
+
if (roundup)
|
|
714
|
+
{
|
|
715
|
+
eval_increment(arg);
|
|
716
|
+
if (bits_to_keep)
|
|
717
|
+
{
|
|
718
|
+
if (eval_bit_test(arg, static_cast<std::size_t>(bits_to_keep)))
|
|
719
|
+
{
|
|
720
|
+
// This happens very very rairly, all the bits left after
|
|
721
|
+
// truncation must be 1's and we're rounding up an order of magnitude:
|
|
722
|
+
eval_right_shift(arg, 1u);
|
|
723
|
+
++res.exponent();
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
else
|
|
727
|
+
{
|
|
728
|
+
// We get here when bits_to_keep is zero but we're rounding up,
|
|
729
|
+
// as a result we end up with a single digit that is a 1:
|
|
730
|
+
++bits_to_keep;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
if (bits_to_keep != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
|
|
734
|
+
{
|
|
735
|
+
// Normalize result when we're rounding to fewer bits than we can hold, only happens in conversions
|
|
736
|
+
// to narrower types:
|
|
737
|
+
eval_left_shift(arg, static_cast<double_limb_type>(static_cast<std::ptrdiff_t>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - bits_to_keep));
|
|
738
|
+
res.exponent() -= static_cast<Exponent>(static_cast<std::ptrdiff_t>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - bits_to_keep);
|
|
739
|
+
}
|
|
740
|
+
res.bits() = arg;
|
|
741
|
+
}
|
|
742
|
+
else
|
|
743
|
+
{
|
|
744
|
+
res.bits() = arg;
|
|
745
|
+
}
|
|
746
|
+
if (!bits_to_keep && !res.bits().limbs()[0])
|
|
747
|
+
{
|
|
748
|
+
// We're keeping zero bits and did not round up, so result is zero:
|
|
749
|
+
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
// Result must be normalized:
|
|
753
|
+
BOOST_MP_ASSERT(((std::ptrdiff_t )eval_msb(res.bits()) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
|
|
754
|
+
|
|
755
|
+
if (res.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
|
|
756
|
+
{
|
|
757
|
+
// Overflow:
|
|
758
|
+
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
|
|
759
|
+
res.bits() = static_cast<limb_type>(0u);
|
|
760
|
+
}
|
|
761
|
+
else if (res.exponent() < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
|
|
762
|
+
{
|
|
763
|
+
// Underflow:
|
|
764
|
+
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
|
765
|
+
res.bits() = static_cast<limb_type>(0u);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class BinFloat2, class BinFloat3>
|
|
770
|
+
inline void do_eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
|
|
771
|
+
const BinFloat2& a, const BinFloat3& b)
|
|
772
|
+
{
|
|
773
|
+
if (a.exponent() < b.exponent())
|
|
774
|
+
{
|
|
775
|
+
bool s = a.sign();
|
|
776
|
+
do_eval_add(res, b, a);
|
|
777
|
+
if (res.sign() != s)
|
|
778
|
+
res.negate();
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
using default_ops::eval_add;
|
|
783
|
+
using default_ops::eval_bit_test;
|
|
784
|
+
|
|
785
|
+
using exponent_type = typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type;
|
|
786
|
+
|
|
787
|
+
typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
|
|
788
|
+
|
|
789
|
+
// Special cases first:
|
|
790
|
+
switch (a.exponent())
|
|
791
|
+
{
|
|
792
|
+
case BinFloat2::exponent_zero:
|
|
793
|
+
{
|
|
794
|
+
bool s = a.sign();
|
|
795
|
+
res = b;
|
|
796
|
+
res.sign() = s;
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
case BinFloat2::exponent_infinity:
|
|
800
|
+
if (b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan)
|
|
801
|
+
res = b;
|
|
802
|
+
else
|
|
803
|
+
res = a;
|
|
804
|
+
return; // result is still infinite.
|
|
805
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
|
806
|
+
res = a;
|
|
807
|
+
return; // result is still a NaN.
|
|
808
|
+
}
|
|
809
|
+
switch (b.exponent())
|
|
810
|
+
{
|
|
811
|
+
case BinFloat3::exponent_zero:
|
|
812
|
+
res = a;
|
|
813
|
+
return;
|
|
814
|
+
case BinFloat3::exponent_infinity:
|
|
815
|
+
res = b;
|
|
816
|
+
if (res.sign())
|
|
817
|
+
res.negate();
|
|
818
|
+
return; // result is infinite.
|
|
819
|
+
case BinFloat3::exponent_nan:
|
|
820
|
+
res = b;
|
|
821
|
+
return; // result is a NaN.
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
static_assert((std::numeric_limits<exponent_type>::max)() - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent, "Exponent range check failed");
|
|
825
|
+
|
|
826
|
+
bool s = a.sign();
|
|
827
|
+
dt = a.bits();
|
|
828
|
+
if (a.exponent() > (std::ptrdiff_t )cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + b.exponent())
|
|
829
|
+
{
|
|
830
|
+
res.exponent() = a.exponent();
|
|
831
|
+
}
|
|
832
|
+
else
|
|
833
|
+
{
|
|
834
|
+
exponent_type e_diff = a.exponent() - b.exponent();
|
|
835
|
+
BOOST_MP_ASSERT(e_diff >= 0);
|
|
836
|
+
eval_left_shift(dt, static_cast<double_limb_type>(e_diff));
|
|
837
|
+
res.exponent() = a.exponent() - e_diff;
|
|
838
|
+
eval_add(dt, b.bits());
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
copy_and_round(res, dt);
|
|
842
|
+
res.check_invariants();
|
|
843
|
+
if (res.sign() != s)
|
|
844
|
+
res.negate();
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
template <class BinFloat1, class BinFloat2, class BinFloat3>
|
|
848
|
+
inline void do_eval_subtract(BinFloat1& res, const BinFloat2& a, const BinFloat3& b)
|
|
849
|
+
{
|
|
850
|
+
using default_ops::eval_bit_test;
|
|
851
|
+
using default_ops::eval_decrement;
|
|
852
|
+
using default_ops::eval_subtract;
|
|
853
|
+
|
|
854
|
+
typename BinFloat1::double_rep_type dt;
|
|
855
|
+
|
|
856
|
+
// Special cases first:
|
|
857
|
+
switch (a.exponent())
|
|
858
|
+
{
|
|
859
|
+
case BinFloat2::exponent_zero:
|
|
860
|
+
if (b.exponent() == BinFloat3::exponent_nan)
|
|
861
|
+
res = std::numeric_limits<number<BinFloat1> >::quiet_NaN().backend();
|
|
862
|
+
else
|
|
863
|
+
{
|
|
864
|
+
bool s = a.sign();
|
|
865
|
+
res = b;
|
|
866
|
+
if (res.exponent() == BinFloat1::exponent_zero)
|
|
867
|
+
res.sign() = false;
|
|
868
|
+
else if (res.sign() == s)
|
|
869
|
+
res.negate();
|
|
870
|
+
}
|
|
871
|
+
return;
|
|
872
|
+
case BinFloat2::exponent_infinity:
|
|
873
|
+
if ((b.exponent() == BinFloat3::exponent_nan) || (b.exponent() == BinFloat3::exponent_infinity))
|
|
874
|
+
res = std::numeric_limits<number<BinFloat1> >::quiet_NaN().backend();
|
|
875
|
+
else
|
|
876
|
+
res = a;
|
|
877
|
+
return;
|
|
878
|
+
case BinFloat2::exponent_nan:
|
|
879
|
+
res = a;
|
|
880
|
+
return; // result is still a NaN.
|
|
881
|
+
}
|
|
882
|
+
switch (b.exponent())
|
|
883
|
+
{
|
|
884
|
+
case BinFloat3::exponent_zero:
|
|
885
|
+
res = a;
|
|
886
|
+
return;
|
|
887
|
+
case BinFloat3::exponent_infinity:
|
|
888
|
+
res.exponent() = BinFloat1::exponent_infinity;
|
|
889
|
+
res.sign() = !a.sign();
|
|
890
|
+
res.bits() = static_cast<limb_type>(0u);
|
|
891
|
+
return; // result is a NaN.
|
|
892
|
+
case BinFloat3::exponent_nan:
|
|
893
|
+
res = b;
|
|
894
|
+
return; // result is still a NaN.
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
bool s = a.sign();
|
|
898
|
+
if ((a.exponent() > b.exponent()) || ((a.exponent() == b.exponent()) && a.bits().compare(b.bits()) >= 0))
|
|
899
|
+
{
|
|
900
|
+
dt = a.bits();
|
|
901
|
+
if (a.exponent() <= (std::ptrdiff_t )BinFloat1::bit_count + b.exponent())
|
|
902
|
+
{
|
|
903
|
+
typename BinFloat1::exponent_type e_diff = a.exponent() - b.exponent();
|
|
904
|
+
eval_left_shift(dt, static_cast<double_limb_type>(e_diff));
|
|
905
|
+
res.exponent() = a.exponent() - e_diff;
|
|
906
|
+
eval_subtract(dt, b.bits());
|
|
907
|
+
}
|
|
908
|
+
else if (a.exponent() == (std::ptrdiff_t )BinFloat1::bit_count + b.exponent() + 1)
|
|
909
|
+
{
|
|
910
|
+
if ((eval_lsb(a.bits()) == BinFloat1::bit_count - 1)
|
|
911
|
+
&& (eval_lsb(b.bits()) != BinFloat1::bit_count - 1))
|
|
912
|
+
{
|
|
913
|
+
eval_left_shift(dt, 1);
|
|
914
|
+
eval_decrement(dt);
|
|
915
|
+
res.exponent() = a.exponent() - 1;
|
|
916
|
+
}
|
|
917
|
+
else
|
|
918
|
+
res.exponent() = a.exponent();
|
|
919
|
+
}
|
|
920
|
+
else
|
|
921
|
+
res.exponent() = a.exponent();
|
|
922
|
+
}
|
|
923
|
+
else
|
|
924
|
+
{
|
|
925
|
+
dt = b.bits();
|
|
926
|
+
if (b.exponent() <= (std::ptrdiff_t )BinFloat1::bit_count + a.exponent())
|
|
927
|
+
{
|
|
928
|
+
typename BinFloat1::exponent_type e_diff = a.exponent() - b.exponent();
|
|
929
|
+
eval_left_shift(dt, static_cast<double_limb_type>(-e_diff));
|
|
930
|
+
res.exponent() = b.exponent() + e_diff;
|
|
931
|
+
eval_subtract(dt, a.bits());
|
|
932
|
+
}
|
|
933
|
+
else if (b.exponent() == (std::ptrdiff_t )BinFloat1::bit_count + a.exponent() + 1)
|
|
934
|
+
{
|
|
935
|
+
if ((eval_lsb(a.bits()) != BinFloat1::bit_count - 1)
|
|
936
|
+
&& eval_lsb(b.bits()))
|
|
937
|
+
{
|
|
938
|
+
eval_left_shift(dt, 1);
|
|
939
|
+
eval_decrement(dt);
|
|
940
|
+
res.exponent() = b.exponent() - 1;
|
|
941
|
+
}
|
|
942
|
+
else
|
|
943
|
+
res.exponent() = b.exponent();
|
|
944
|
+
}
|
|
945
|
+
else
|
|
946
|
+
res.exponent() = b.exponent();
|
|
947
|
+
s = !s;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
copy_and_round(res, dt);
|
|
951
|
+
if (res.exponent() == BinFloat1::exponent_zero)
|
|
952
|
+
res.sign() = false;
|
|
953
|
+
else if (res.sign() != s)
|
|
954
|
+
res.negate();
|
|
955
|
+
res.check_invariants();
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
|
|
959
|
+
class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2,
|
|
960
|
+
class Allocator3, class Exponent3, Exponent MinE3, Exponent MaxE3>
|
|
961
|
+
inline void eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
|
|
962
|
+
const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a,
|
|
963
|
+
const cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>& b)
|
|
964
|
+
{
|
|
965
|
+
if (a.sign() == b.sign())
|
|
966
|
+
do_eval_add(res, a, b);
|
|
967
|
+
else
|
|
968
|
+
do_eval_subtract(res, a, b);
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
|
|
972
|
+
class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2>
|
|
973
|
+
inline void eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
|
|
974
|
+
const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a)
|
|
975
|
+
{
|
|
976
|
+
return eval_add(res, res, a);
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
|
|
980
|
+
class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2,
|
|
981
|
+
class Allocator3, class Exponent3, Exponent MinE3, Exponent MaxE3>
|
|
982
|
+
inline void eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
|
|
983
|
+
const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a,
|
|
984
|
+
const cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>& b)
|
|
985
|
+
{
|
|
986
|
+
if (a.sign() != b.sign())
|
|
987
|
+
do_eval_add(res, a, b);
|
|
988
|
+
else
|
|
989
|
+
do_eval_subtract(res, a, b);
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
|
|
993
|
+
class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2>
|
|
994
|
+
inline void eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
|
|
995
|
+
const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a)
|
|
996
|
+
{
|
|
997
|
+
return eval_subtract(res, res, a);
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
|
|
1001
|
+
class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2,
|
|
1002
|
+
class Allocator3, class Exponent3, Exponent MinE3, Exponent MaxE3>
|
|
1003
|
+
inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
|
|
1004
|
+
const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a,
|
|
1005
|
+
const cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>& b)
|
|
1006
|
+
{
|
|
1007
|
+
using default_ops::eval_bit_test;
|
|
1008
|
+
using default_ops::eval_multiply;
|
|
1009
|
+
|
|
1010
|
+
// Special cases first:
|
|
1011
|
+
switch (a.exponent())
|
|
1012
|
+
{
|
|
1013
|
+
case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_zero:
|
|
1014
|
+
{
|
|
1015
|
+
if (b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_nan)
|
|
1016
|
+
res = b;
|
|
1017
|
+
else if (b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_infinity)
|
|
1018
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
|
1019
|
+
else
|
|
1020
|
+
{
|
|
1021
|
+
bool s = a.sign() != b.sign();
|
|
1022
|
+
res = a;
|
|
1023
|
+
res.sign() = s;
|
|
1024
|
+
}
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_infinity:
|
|
1028
|
+
switch (b.exponent())
|
|
1029
|
+
{
|
|
1030
|
+
case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_zero:
|
|
1031
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
|
1032
|
+
break;
|
|
1033
|
+
case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_nan:
|
|
1034
|
+
res = b;
|
|
1035
|
+
break;
|
|
1036
|
+
default:
|
|
1037
|
+
bool s = a.sign() != b.sign();
|
|
1038
|
+
res = a;
|
|
1039
|
+
res.sign() = s;
|
|
1040
|
+
break;
|
|
1041
|
+
}
|
|
1042
|
+
return;
|
|
1043
|
+
case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_nan:
|
|
1044
|
+
res = a;
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1047
|
+
if (b.exponent() > cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::max_exponent)
|
|
1048
|
+
{
|
|
1049
|
+
bool s = a.sign() != b.sign();
|
|
1050
|
+
res = b;
|
|
1051
|
+
res.sign() = s;
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
if ((a.exponent() > 0) && (b.exponent() > 0))
|
|
1055
|
+
{
|
|
1056
|
+
if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent + 2 - a.exponent() < b.exponent())
|
|
1057
|
+
{
|
|
1058
|
+
// We will certainly overflow:
|
|
1059
|
+
bool s = a.sign() != b.sign();
|
|
1060
|
+
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
|
|
1061
|
+
res.sign() = s;
|
|
1062
|
+
res.bits() = static_cast<limb_type>(0u);
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
if ((a.exponent() < 0) && (b.exponent() < 0))
|
|
1067
|
+
{
|
|
1068
|
+
if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent - 2 - a.exponent() > b.exponent())
|
|
1069
|
+
{
|
|
1070
|
+
// We will certainly underflow:
|
|
1071
|
+
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
|
1072
|
+
res.sign() = a.sign() != b.sign();
|
|
1073
|
+
res.bits() = static_cast<limb_type>(0u);
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
|
|
1079
|
+
eval_multiply(dt, a.bits(), b.bits());
|
|
1080
|
+
res.exponent() = a.exponent() + b.exponent() - (Exponent)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1;
|
|
1081
|
+
copy_and_round(res, dt);
|
|
1082
|
+
res.check_invariants();
|
|
1083
|
+
res.sign() = a.sign() != b.sign();
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
|
|
1087
|
+
class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2>
|
|
1088
|
+
inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
|
|
1089
|
+
const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a)
|
|
1090
|
+
{
|
|
1091
|
+
eval_multiply(res, res, a);
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
|
|
1095
|
+
class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2, class U>
|
|
1096
|
+
inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<U>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
|
|
1097
|
+
const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a, const U& b)
|
|
1098
|
+
{
|
|
1099
|
+
using default_ops::eval_bit_test;
|
|
1100
|
+
using default_ops::eval_multiply;
|
|
1101
|
+
|
|
1102
|
+
bool s = a.sign(); // saved for later in case a and res are the same object.
|
|
1103
|
+
|
|
1104
|
+
// Special cases first:
|
|
1105
|
+
switch (a.exponent())
|
|
1106
|
+
{
|
|
1107
|
+
case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_zero:
|
|
1108
|
+
{
|
|
1109
|
+
res = a;
|
|
1110
|
+
res.sign() = s;
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_infinity:
|
|
1114
|
+
if (b == 0)
|
|
1115
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
|
1116
|
+
else
|
|
1117
|
+
res = a;
|
|
1118
|
+
return;
|
|
1119
|
+
case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_nan:
|
|
1120
|
+
res = a;
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
|
|
1125
|
+
using canon_ui_type = typename boost::multiprecision::detail::canonical<U, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::type;
|
|
1126
|
+
eval_multiply(dt, a.bits(), static_cast<canon_ui_type>(b));
|
|
1127
|
+
res.exponent() = a.exponent();
|
|
1128
|
+
copy_and_round(res, dt);
|
|
1129
|
+
res.check_invariants();
|
|
1130
|
+
res.sign() = s;
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
|
|
1134
|
+
inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<U>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const U& b)
|
|
1135
|
+
{
|
|
1136
|
+
eval_multiply(res, res, b);
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
|
|
1140
|
+
class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2, class S>
|
|
1141
|
+
inline typename std::enable_if<boost::multiprecision::detail::is_signed<S>::value && boost::multiprecision::detail::is_integral<S>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
|
|
1142
|
+
const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a, const S& b)
|
|
1143
|
+
{
|
|
1144
|
+
using ui_type = typename boost::multiprecision::detail::make_unsigned<S>::type;
|
|
1145
|
+
eval_multiply(res, a, static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(b)));
|
|
1146
|
+
if (b < 0)
|
|
1147
|
+
res.negate();
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
|
|
1151
|
+
inline typename std::enable_if<boost::multiprecision::detail::is_signed<S>::value && boost::multiprecision::detail::is_integral<S>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const S& b)
|
|
1152
|
+
{
|
|
1153
|
+
eval_multiply(res, res, b);
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
|
|
1157
|
+
class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2,
|
|
1158
|
+
class Allocator3, class Exponent3, Exponent MinE3, Exponent MaxE3>
|
|
1159
|
+
inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
|
|
1160
|
+
const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& u,
|
|
1161
|
+
const cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>& v)
|
|
1162
|
+
{
|
|
1163
|
+
#ifdef BOOST_MSVC
|
|
1164
|
+
#pragma warning(push)
|
|
1165
|
+
#pragma warning(disable : 6326) // comparison of two constants
|
|
1166
|
+
#endif
|
|
1167
|
+
using default_ops::eval_bit_test;
|
|
1168
|
+
using default_ops::eval_get_sign;
|
|
1169
|
+
using default_ops::eval_increment;
|
|
1170
|
+
using default_ops::eval_qr;
|
|
1171
|
+
using default_ops::eval_subtract;
|
|
1172
|
+
|
|
1173
|
+
//
|
|
1174
|
+
// Special cases first:
|
|
1175
|
+
//
|
|
1176
|
+
switch (u.exponent())
|
|
1177
|
+
{
|
|
1178
|
+
case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_zero:
|
|
1179
|
+
{
|
|
1180
|
+
switch (v.exponent())
|
|
1181
|
+
{
|
|
1182
|
+
case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_zero:
|
|
1183
|
+
case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_nan:
|
|
1184
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
|
1185
|
+
return;
|
|
1186
|
+
}
|
|
1187
|
+
bool s = u.sign() != v.sign();
|
|
1188
|
+
res = u;
|
|
1189
|
+
res.sign() = s;
|
|
1190
|
+
return;
|
|
1191
|
+
}
|
|
1192
|
+
case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_infinity:
|
|
1193
|
+
{
|
|
1194
|
+
switch (v.exponent())
|
|
1195
|
+
{
|
|
1196
|
+
case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_infinity:
|
|
1197
|
+
case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_nan:
|
|
1198
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
bool s = u.sign() != v.sign();
|
|
1202
|
+
res = u;
|
|
1203
|
+
res.sign() = s;
|
|
1204
|
+
return;
|
|
1205
|
+
}
|
|
1206
|
+
case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_nan:
|
|
1207
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
|
1208
|
+
return;
|
|
1209
|
+
}
|
|
1210
|
+
switch (v.exponent())
|
|
1211
|
+
{
|
|
1212
|
+
case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_zero:
|
|
1213
|
+
{
|
|
1214
|
+
bool s = u.sign() != v.sign();
|
|
1215
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
|
|
1216
|
+
res.sign() = s;
|
|
1217
|
+
return;
|
|
1218
|
+
}
|
|
1219
|
+
case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_infinity:
|
|
1220
|
+
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
|
1221
|
+
res.bits() = limb_type(0);
|
|
1222
|
+
res.sign() = u.sign() != v.sign();
|
|
1223
|
+
return;
|
|
1224
|
+
case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_nan:
|
|
1225
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
|
1226
|
+
return;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
// We can scale u and v so that both are integers, then perform integer
|
|
1230
|
+
// division to obtain quotient q and remainder r, such that:
|
|
1231
|
+
//
|
|
1232
|
+
// q * v + r = u
|
|
1233
|
+
//
|
|
1234
|
+
// and hense:
|
|
1235
|
+
//
|
|
1236
|
+
// q + r/v = u/v
|
|
1237
|
+
//
|
|
1238
|
+
// From this, assuming q has cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count
|
|
1239
|
+
// bits we only need to determine whether
|
|
1240
|
+
// r/v is less than, equal to, or greater than 0.5 to determine rounding -
|
|
1241
|
+
// this we can do with a shift and comparison.
|
|
1242
|
+
//
|
|
1243
|
+
// We can set the exponent and sign of the result up front:
|
|
1244
|
+
//
|
|
1245
|
+
if ((v.exponent() < 0) && (u.exponent() > 0))
|
|
1246
|
+
{
|
|
1247
|
+
// Check for overflow:
|
|
1248
|
+
if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent + v.exponent() < u.exponent() - 1)
|
|
1249
|
+
{
|
|
1250
|
+
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
|
|
1251
|
+
res.sign() = u.sign() != v.sign();
|
|
1252
|
+
res.bits() = static_cast<limb_type>(0u);
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
else if ((v.exponent() > 0) && (u.exponent() < 0))
|
|
1257
|
+
{
|
|
1258
|
+
// Check for underflow:
|
|
1259
|
+
if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent + v.exponent() > u.exponent())
|
|
1260
|
+
{
|
|
1261
|
+
// We will certainly underflow:
|
|
1262
|
+
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
|
1263
|
+
res.sign() = u.sign() != v.sign();
|
|
1264
|
+
res.bits() = static_cast<limb_type>(0u);
|
|
1265
|
+
return;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
res.exponent() = u.exponent() - v.exponent() - 1;
|
|
1269
|
+
res.sign() = u.sign() != v.sign();
|
|
1270
|
+
//
|
|
1271
|
+
// Now get the quotient and remainder:
|
|
1272
|
+
//
|
|
1273
|
+
typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(u.bits()), t2(v.bits()), q, r;
|
|
1274
|
+
eval_left_shift(t, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count);
|
|
1275
|
+
eval_qr(t, t2, q, r);
|
|
1276
|
+
//
|
|
1277
|
+
// We now have either "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count"
|
|
1278
|
+
// or "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1" significant
|
|
1279
|
+
// bits in q.
|
|
1280
|
+
//
|
|
1281
|
+
constexpr unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
|
|
1282
|
+
if (eval_bit_test(q, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
|
|
1283
|
+
{
|
|
1284
|
+
//
|
|
1285
|
+
// OK we have cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1 bits,
|
|
1286
|
+
// so we already have rounding info,
|
|
1287
|
+
// we just need to changes things if the last bit is 1 and either the
|
|
1288
|
+
// remainder is non-zero (ie we do not have a tie) or the quotient would
|
|
1289
|
+
// be odd if it were shifted to the correct number of bits (ie a tiebreak).
|
|
1290
|
+
//
|
|
1291
|
+
BOOST_MP_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count));
|
|
1292
|
+
if ((q.limbs()[0] & 1u) && (eval_get_sign(r) || (q.limbs()[0] & 2u)))
|
|
1293
|
+
{
|
|
1294
|
+
eval_increment(q);
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
else
|
|
1298
|
+
{
|
|
1299
|
+
//
|
|
1300
|
+
// We have exactly "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" bits in q.
|
|
1301
|
+
// Get rounding info, which we can get by comparing 2r with v.
|
|
1302
|
+
// We want to call copy_and_round to handle rounding and general cleanup,
|
|
1303
|
+
// so we'll left shift q and add some fake digits on the end to represent
|
|
1304
|
+
// how we'll be rounding.
|
|
1305
|
+
//
|
|
1306
|
+
using local_exponent_type = typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type;
|
|
1307
|
+
|
|
1308
|
+
BOOST_MP_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
|
|
1309
|
+
constexpr unsigned lshift = (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count < limb_bits) ? 2 : limb_bits;
|
|
1310
|
+
eval_left_shift(q, lshift);
|
|
1311
|
+
res.exponent() -= static_cast<local_exponent_type>(lshift);
|
|
1312
|
+
eval_left_shift(r, 1u);
|
|
1313
|
+
int c = r.compare(v.bits());
|
|
1314
|
+
if (c == 0)
|
|
1315
|
+
q.limbs()[0] |= static_cast<limb_type>(1u) << (lshift - 1);
|
|
1316
|
+
else if (c > 0)
|
|
1317
|
+
q.limbs()[0] |= (static_cast<limb_type>(1u) << (lshift - 1)) + static_cast<limb_type>(1u);
|
|
1318
|
+
}
|
|
1319
|
+
copy_and_round(res, q);
|
|
1320
|
+
#ifdef BOOST_MSVC
|
|
1321
|
+
#pragma warning(pop)
|
|
1322
|
+
#endif
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
|
|
1326
|
+
class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2>
|
|
1327
|
+
inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
|
|
1328
|
+
const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& arg)
|
|
1329
|
+
{
|
|
1330
|
+
eval_divide(res, res, arg);
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
|
|
1334
|
+
class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2, class U>
|
|
1335
|
+
inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<U>::value && (std::numeric_limits<U>::digits <= Digits)>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
|
|
1336
|
+
const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& u, const U& v)
|
|
1337
|
+
{
|
|
1338
|
+
#ifdef BOOST_MSVC
|
|
1339
|
+
#pragma warning(push)
|
|
1340
|
+
#pragma warning(disable : 6326) // comparison of two constants
|
|
1341
|
+
#endif
|
|
1342
|
+
using default_ops::eval_bit_test;
|
|
1343
|
+
using default_ops::eval_get_sign;
|
|
1344
|
+
using default_ops::eval_increment;
|
|
1345
|
+
using default_ops::eval_qr;
|
|
1346
|
+
using default_ops::eval_subtract;
|
|
1347
|
+
|
|
1348
|
+
//
|
|
1349
|
+
// Special cases first:
|
|
1350
|
+
//
|
|
1351
|
+
switch (u.exponent())
|
|
1352
|
+
{
|
|
1353
|
+
case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_zero:
|
|
1354
|
+
{
|
|
1355
|
+
if (v == 0)
|
|
1356
|
+
{
|
|
1357
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
bool s = u.sign() != (v < 0);
|
|
1361
|
+
res = u;
|
|
1362
|
+
res.sign() = s;
|
|
1363
|
+
return;
|
|
1364
|
+
}
|
|
1365
|
+
case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_infinity:
|
|
1366
|
+
res = u;
|
|
1367
|
+
return;
|
|
1368
|
+
case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_nan:
|
|
1369
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1372
|
+
if (v == 0)
|
|
1373
|
+
{
|
|
1374
|
+
bool s = u.sign();
|
|
1375
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
|
|
1376
|
+
res.sign() = s;
|
|
1377
|
+
return;
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
// We can scale u and v so that both are integers, then perform integer
|
|
1381
|
+
// division to obtain quotient q and remainder r, such that:
|
|
1382
|
+
//
|
|
1383
|
+
// q * v + r = u
|
|
1384
|
+
//
|
|
1385
|
+
// and hense:
|
|
1386
|
+
//
|
|
1387
|
+
// q + r/v = u/v
|
|
1388
|
+
//
|
|
1389
|
+
// From this, assuming q has "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count, we only need to determine whether
|
|
1390
|
+
// r/v is less than, equal to, or greater than 0.5 to determine rounding -
|
|
1391
|
+
// this we can do with a shift and comparison.
|
|
1392
|
+
//
|
|
1393
|
+
// We can set the exponent and sign of the result up front:
|
|
1394
|
+
//
|
|
1395
|
+
std::ptrdiff_t gb = static_cast<std::ptrdiff_t>(msb(v));
|
|
1396
|
+
res.exponent() = u.exponent() - static_cast<Exponent>(gb) - static_cast<Exponent>(1);
|
|
1397
|
+
res.sign() = u.sign();
|
|
1398
|
+
//
|
|
1399
|
+
// Now get the quotient and remainder:
|
|
1400
|
+
//
|
|
1401
|
+
typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(u.bits()), q, r;
|
|
1402
|
+
eval_left_shift(t, static_cast<double_limb_type>(gb + 1));
|
|
1403
|
+
eval_qr(t, number<typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::canonical_value(v), q, r);
|
|
1404
|
+
//
|
|
1405
|
+
// We now have either "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" or "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1" significant cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in q.
|
|
1406
|
+
//
|
|
1407
|
+
constexpr unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
|
|
1408
|
+
if (eval_bit_test(q, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
|
|
1409
|
+
{
|
|
1410
|
+
//
|
|
1411
|
+
// OK we have cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1 cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count, so we already have rounding info,
|
|
1412
|
+
// we just need to changes things if the last bit is 1 and the
|
|
1413
|
+
// remainder is non-zero (ie we do not have a tie).
|
|
1414
|
+
//
|
|
1415
|
+
BOOST_MP_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count));
|
|
1416
|
+
if ((q.limbs()[0] & 1u) && eval_get_sign(r))
|
|
1417
|
+
{
|
|
1418
|
+
eval_increment(q);
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
else
|
|
1422
|
+
{
|
|
1423
|
+
//
|
|
1424
|
+
// We have exactly "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in q.
|
|
1425
|
+
// Get rounding info, which we can get by comparing 2r with v.
|
|
1426
|
+
// We want to call copy_and_round to handle rounding and general cleanup,
|
|
1427
|
+
// so we'll left shift q and add some fake cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count on the end to represent
|
|
1428
|
+
// how we'll be rounding.
|
|
1429
|
+
//
|
|
1430
|
+
using local_exponent_type = typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type;
|
|
1431
|
+
|
|
1432
|
+
BOOST_MP_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
|
|
1433
|
+
constexpr unsigned lshift = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count < limb_bits ? 2 : limb_bits;
|
|
1434
|
+
eval_left_shift(q, lshift);
|
|
1435
|
+
res.exponent() -= static_cast<local_exponent_type>(lshift);
|
|
1436
|
+
eval_left_shift(r, 1u);
|
|
1437
|
+
int c = r.compare(number<typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::canonical_value(v));
|
|
1438
|
+
if (c == 0)
|
|
1439
|
+
q.limbs()[0] |= static_cast<limb_type>(1u) << (lshift - 1);
|
|
1440
|
+
else if (c > 0)
|
|
1441
|
+
q.limbs()[0] |= (static_cast<limb_type>(1u) << (lshift - 1)) + static_cast<limb_type>(1u);
|
|
1442
|
+
}
|
|
1443
|
+
copy_and_round(res, q);
|
|
1444
|
+
#ifdef BOOST_MSVC
|
|
1445
|
+
#pragma warning(pop)
|
|
1446
|
+
#endif
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
|
|
1450
|
+
inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<U>::value && (std::numeric_limits<U>::digits <= Digits)>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const U& v)
|
|
1451
|
+
{
|
|
1452
|
+
eval_divide(res, res, v);
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
|
|
1456
|
+
class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2, class S>
|
|
1457
|
+
inline typename std::enable_if<boost::multiprecision::detail::is_signed<S>::value && boost::multiprecision::detail::is_integral<S>::value && (std::numeric_limits<S>::digits <= Digits)>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
|
|
1458
|
+
const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& u, const S& v)
|
|
1459
|
+
{
|
|
1460
|
+
using ui_type = typename boost::multiprecision::detail::make_unsigned<S>::type;
|
|
1461
|
+
eval_divide(res, u, static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(v)));
|
|
1462
|
+
if (v < 0)
|
|
1463
|
+
res.negate();
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
|
|
1467
|
+
inline typename std::enable_if<boost::multiprecision::detail::is_signed<S>::value && boost::multiprecision::detail::is_integral<S>::value && (std::numeric_limits<S>::digits <= Digits)>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const S& v)
|
|
1468
|
+
{
|
|
1469
|
+
eval_divide(res, res, v);
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1473
|
+
inline int eval_get_sign(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
|
1474
|
+
{
|
|
1475
|
+
return arg.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero ? 0 : arg.sign() ? -1 : 1;
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1479
|
+
inline bool eval_is_zero(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
|
1480
|
+
{
|
|
1481
|
+
return arg.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1485
|
+
inline bool eval_eq(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& a, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& b)
|
|
1486
|
+
{
|
|
1487
|
+
if (a.exponent() == b.exponent())
|
|
1488
|
+
{
|
|
1489
|
+
if (a.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero)
|
|
1490
|
+
return true;
|
|
1491
|
+
return (a.sign() == b.sign()) && (a.bits().compare(b.bits()) == 0) && (a.exponent() != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan);
|
|
1492
|
+
}
|
|
1493
|
+
return false;
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
template <class I, unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1497
|
+
inline void convert_to_signed_int(I* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
|
1498
|
+
{
|
|
1499
|
+
static constexpr int digits = std::numeric_limits<I>::is_specialized ? std::numeric_limits<I>::digits : sizeof(I) * CHAR_BIT - 1;
|
|
1500
|
+
static constexpr I max_val = std::numeric_limits<I>::is_specialized ? (std::numeric_limits<I>::max)() : (((I(1) << (sizeof(I) * CHAR_BIT - 2)) - 1) << 1) + 1;
|
|
1501
|
+
static constexpr I min_val = std::numeric_limits<I>::is_specialized ? (std::numeric_limits<I>::min)() : -max_val - 1;
|
|
1502
|
+
|
|
1503
|
+
|
|
1504
|
+
switch (arg.exponent())
|
|
1505
|
+
{
|
|
1506
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
|
1507
|
+
*res = 0;
|
|
1508
|
+
return;
|
|
1509
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
|
1510
|
+
BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
|
|
1511
|
+
return;
|
|
1512
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
|
1513
|
+
*res = max_val;
|
|
1514
|
+
if (arg.sign())
|
|
1515
|
+
*res = -*res;
|
|
1516
|
+
return;
|
|
1517
|
+
}
|
|
1518
|
+
using shift_type = typename std::conditional<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type;
|
|
1519
|
+
typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type man(arg.bits());
|
|
1520
|
+
shift_type shift = (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - arg.exponent();
|
|
1521
|
+
if (shift > (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
|
|
1522
|
+
{
|
|
1523
|
+
*res = 0;
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
if (arg.sign() && (arg.compare(min_val) <= 0))
|
|
1527
|
+
{
|
|
1528
|
+
*res = min_val;
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1531
|
+
else if (!arg.sign() && (arg.compare(max_val) >= 0))
|
|
1532
|
+
{
|
|
1533
|
+
*res = max_val;
|
|
1534
|
+
return;
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
if (shift < 0)
|
|
1538
|
+
{
|
|
1539
|
+
if (static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - static_cast<int>(shift) <= digits)
|
|
1540
|
+
{
|
|
1541
|
+
// We have more bits in long_long_type than the float, so it's OK to left shift:
|
|
1542
|
+
eval_convert_to(res, man);
|
|
1543
|
+
*res <<= -shift;
|
|
1544
|
+
}
|
|
1545
|
+
else
|
|
1546
|
+
{
|
|
1547
|
+
*res = (std::numeric_limits<I>::max)();
|
|
1548
|
+
return;
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
else
|
|
1552
|
+
{
|
|
1553
|
+
eval_right_shift(man, static_cast<double_limb_type>(shift));
|
|
1554
|
+
eval_convert_to(res, man);
|
|
1555
|
+
}
|
|
1556
|
+
if (arg.sign())
|
|
1557
|
+
{
|
|
1558
|
+
*res = -*res;
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1563
|
+
inline void eval_convert_to(long long* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
|
1564
|
+
{
|
|
1565
|
+
convert_to_signed_int(res, arg);
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
#ifdef BOOST_HAS_INT128
|
|
1569
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1570
|
+
inline void eval_convert_to(int128_type* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
|
1571
|
+
{
|
|
1572
|
+
convert_to_signed_int(res, arg);
|
|
1573
|
+
}
|
|
1574
|
+
#endif
|
|
1575
|
+
|
|
1576
|
+
template <class I, unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1577
|
+
inline void convert_to_unsigned_int(I* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
|
1578
|
+
{
|
|
1579
|
+
static constexpr int digits = std::numeric_limits<I>::is_specialized ? std::numeric_limits<I>::digits : sizeof(I) * CHAR_BIT;
|
|
1580
|
+
static constexpr I max_val = std::numeric_limits<I>::is_specialized ? (std::numeric_limits<I>::max)() : ~static_cast<I>(0);
|
|
1581
|
+
|
|
1582
|
+
switch (arg.exponent())
|
|
1583
|
+
{
|
|
1584
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
|
1585
|
+
*res = 0;
|
|
1586
|
+
return;
|
|
1587
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
|
1588
|
+
BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
|
|
1589
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
|
1590
|
+
*res = max_val;
|
|
1591
|
+
return;
|
|
1592
|
+
}
|
|
1593
|
+
typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type man(arg.bits());
|
|
1594
|
+
using shift_type = typename std::conditional<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type;
|
|
1595
|
+
shift_type shift = (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - arg.exponent();
|
|
1596
|
+
if (shift > (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
|
|
1597
|
+
{
|
|
1598
|
+
*res = 0;
|
|
1599
|
+
return;
|
|
1600
|
+
}
|
|
1601
|
+
else if (shift < 0)
|
|
1602
|
+
{
|
|
1603
|
+
if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - shift <= digits)
|
|
1604
|
+
{
|
|
1605
|
+
// We have more bits in ulong_long_type than the float, so it's OK to left shift:
|
|
1606
|
+
eval_convert_to(res, man);
|
|
1607
|
+
*res <<= -shift;
|
|
1608
|
+
return;
|
|
1609
|
+
}
|
|
1610
|
+
*res = max_val;
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
eval_right_shift(man, shift);
|
|
1614
|
+
eval_convert_to(res, man);
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1618
|
+
inline void eval_convert_to(unsigned long long* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
|
1619
|
+
{
|
|
1620
|
+
convert_to_unsigned_int(res, arg);
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
#ifdef BOOST_HAS_INT128
|
|
1624
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1625
|
+
inline void eval_convert_to(uint128_type* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
|
1626
|
+
{
|
|
1627
|
+
convert_to_unsigned_int(res, arg);
|
|
1628
|
+
}
|
|
1629
|
+
#endif
|
|
1630
|
+
|
|
1631
|
+
template <class Float, unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1632
|
+
inline typename std::enable_if<std::is_floating_point<Float>::value>::type eval_convert_to(Float* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& original_arg)
|
|
1633
|
+
{
|
|
1634
|
+
using conv_type = cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE>;
|
|
1635
|
+
using common_exp_type = typename std::common_type<typename conv_type::exponent_type, int>::type;
|
|
1636
|
+
|
|
1637
|
+
static constexpr int float_digits = boost::multiprecision::detail::is_float128<Float>::value ? 113 : std::numeric_limits<Float>::digits;
|
|
1638
|
+
|
|
1639
|
+
BOOST_MP_FLOAT128_USING using std::ldexp;
|
|
1640
|
+
//
|
|
1641
|
+
// Special cases first:
|
|
1642
|
+
//
|
|
1643
|
+
switch (original_arg.exponent())
|
|
1644
|
+
{
|
|
1645
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
|
1646
|
+
*res = 0;
|
|
1647
|
+
if (original_arg.sign())
|
|
1648
|
+
*res = -*res;
|
|
1649
|
+
return;
|
|
1650
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
|
1651
|
+
BOOST_IF_CONSTEXPR(boost::multiprecision::detail::is_float128<Float>::value)
|
|
1652
|
+
{
|
|
1653
|
+
*res = static_cast<Float>(std::numeric_limits<double>::quiet_NaN());
|
|
1654
|
+
}
|
|
1655
|
+
else
|
|
1656
|
+
{
|
|
1657
|
+
*res = std::numeric_limits<Float>::quiet_NaN();
|
|
1658
|
+
}
|
|
1659
|
+
return;
|
|
1660
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
|
1661
|
+
BOOST_IF_CONSTEXPR(boost::multiprecision::detail::is_float128<Float>::value)
|
|
1662
|
+
{
|
|
1663
|
+
*res = static_cast<Float>((std::numeric_limits<double>::infinity)());
|
|
1664
|
+
}
|
|
1665
|
+
else
|
|
1666
|
+
{
|
|
1667
|
+
*res = (std::numeric_limits<Float>::infinity)();
|
|
1668
|
+
}
|
|
1669
|
+
if (original_arg.sign())
|
|
1670
|
+
*res = -*res;
|
|
1671
|
+
return;
|
|
1672
|
+
}
|
|
1673
|
+
//
|
|
1674
|
+
// Check for super large exponent that must be converted to infinity:
|
|
1675
|
+
//
|
|
1676
|
+
if (original_arg.exponent() > (boost::multiprecision::detail::is_float128<Float>::value ? 16384 : std::numeric_limits<Float>::max_exponent))
|
|
1677
|
+
{
|
|
1678
|
+
BOOST_IF_CONSTEXPR(boost::multiprecision::detail::is_float128<Float>::value)
|
|
1679
|
+
{
|
|
1680
|
+
*res = static_cast<Float>(std::numeric_limits<double>::infinity());
|
|
1681
|
+
}
|
|
1682
|
+
else
|
|
1683
|
+
{
|
|
1684
|
+
*res = std::numeric_limits<Float>::has_infinity ? std::numeric_limits<Float>::infinity() : (std::numeric_limits<Float>::max)();
|
|
1685
|
+
}
|
|
1686
|
+
if (original_arg.sign())
|
|
1687
|
+
*res = -*res;
|
|
1688
|
+
return;
|
|
1689
|
+
}
|
|
1690
|
+
//
|
|
1691
|
+
// Figure out how many digits we will have in our result,
|
|
1692
|
+
// allowing for a possibly denormalized result:
|
|
1693
|
+
//
|
|
1694
|
+
common_exp_type digits_to_round_to = float_digits;
|
|
1695
|
+
if (original_arg.exponent() < std::numeric_limits<Float>::min_exponent - 1)
|
|
1696
|
+
{
|
|
1697
|
+
common_exp_type diff = original_arg.exponent();
|
|
1698
|
+
diff -= boost::multiprecision::detail::is_float128<Float>::value ? -16382 : std::numeric_limits<Float>::min_exponent - 1;
|
|
1699
|
+
digits_to_round_to += diff;
|
|
1700
|
+
}
|
|
1701
|
+
if (digits_to_round_to < 0)
|
|
1702
|
+
{
|
|
1703
|
+
// Result must be zero:
|
|
1704
|
+
*res = 0;
|
|
1705
|
+
if (original_arg.sign())
|
|
1706
|
+
*res = -*res;
|
|
1707
|
+
return;
|
|
1708
|
+
}
|
|
1709
|
+
//
|
|
1710
|
+
// Perform rounding first, then afterwards extract the digits:
|
|
1711
|
+
//
|
|
1712
|
+
cpp_bin_float<static_cast<unsigned>(float_digits), digit_base_2, Allocator, Exponent, 0, 0> arg;
|
|
1713
|
+
typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type bits(original_arg.bits());
|
|
1714
|
+
arg.exponent() = original_arg.exponent();
|
|
1715
|
+
copy_and_round(arg, bits, (std::ptrdiff_t)digits_to_round_to);
|
|
1716
|
+
common_exp_type e = arg.exponent();
|
|
1717
|
+
e -= static_cast<common_exp_type>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - 1;
|
|
1718
|
+
constexpr std::size_t limbs_needed = static_cast<std::size_t>(float_digits) / (sizeof(*arg.bits().limbs()) * CHAR_BIT) + (static_cast<std::size_t>(float_digits) % (sizeof(*arg.bits().limbs()) * CHAR_BIT) ? 1 : 0);
|
|
1719
|
+
std::size_t first_limb_needed = arg.bits().size() - limbs_needed;
|
|
1720
|
+
*res = 0;
|
|
1721
|
+
e += static_cast<common_exp_type>(first_limb_needed * sizeof(*arg.bits().limbs()) * CHAR_BIT);
|
|
1722
|
+
while (first_limb_needed < arg.bits().size())
|
|
1723
|
+
{
|
|
1724
|
+
*res += ldexp(static_cast<Float>(arg.bits().limbs()[first_limb_needed]), static_cast<int>(e));
|
|
1725
|
+
++first_limb_needed;
|
|
1726
|
+
e += static_cast<common_exp_type>(sizeof(*arg.bits().limbs()) * CHAR_BIT);
|
|
1727
|
+
}
|
|
1728
|
+
if (original_arg.sign())
|
|
1729
|
+
*res = -*res;
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1733
|
+
inline void eval_frexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg, Exponent* e)
|
|
1734
|
+
{
|
|
1735
|
+
switch (arg.exponent())
|
|
1736
|
+
{
|
|
1737
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
|
1738
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
|
1739
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
|
1740
|
+
*e = 0;
|
|
1741
|
+
res = arg;
|
|
1742
|
+
return;
|
|
1743
|
+
}
|
|
1744
|
+
res = arg;
|
|
1745
|
+
*e = arg.exponent() + 1;
|
|
1746
|
+
res.exponent() = -1;
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I>
|
|
1750
|
+
inline void eval_frexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg, I* pe)
|
|
1751
|
+
{
|
|
1752
|
+
Exponent e;
|
|
1753
|
+
eval_frexp(res, arg, &e);
|
|
1754
|
+
if ((e > (std::numeric_limits<I>::max)()) || (e < (std::numeric_limits<I>::min)()))
|
|
1755
|
+
{
|
|
1756
|
+
BOOST_MP_THROW_EXCEPTION(std::runtime_error("Exponent was outside of the range of the argument type to frexp."));
|
|
1757
|
+
}
|
|
1758
|
+
*pe = static_cast<I>(e);
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1762
|
+
inline void eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg, Exponent e)
|
|
1763
|
+
{
|
|
1764
|
+
switch (arg.exponent())
|
|
1765
|
+
{
|
|
1766
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
|
1767
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
|
1768
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
|
1769
|
+
res = arg;
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
if ((e > 0) && (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent - e < arg.exponent()))
|
|
1773
|
+
{
|
|
1774
|
+
// Overflow:
|
|
1775
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
|
|
1776
|
+
res.sign() = arg.sign();
|
|
1777
|
+
}
|
|
1778
|
+
else if ((e < 0) && (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent - e > arg.exponent()))
|
|
1779
|
+
{
|
|
1780
|
+
// Underflow:
|
|
1781
|
+
res = limb_type(0);
|
|
1782
|
+
}
|
|
1783
|
+
else
|
|
1784
|
+
{
|
|
1785
|
+
res = arg;
|
|
1786
|
+
res.exponent() += e;
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I>
|
|
1791
|
+
inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<I>::value>::type eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg, I e)
|
|
1792
|
+
{
|
|
1793
|
+
using si_type = typename boost::multiprecision::detail::make_signed<I>::type;
|
|
1794
|
+
if (e > static_cast<I>((std::numeric_limits<si_type>::max)()))
|
|
1795
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
|
|
1796
|
+
else
|
|
1797
|
+
eval_ldexp(res, arg, static_cast<si_type>(e));
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I>
|
|
1801
|
+
inline typename std::enable_if<boost::multiprecision::detail::is_signed<I>::value && boost::multiprecision::detail::is_integral<I>::value>::type eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg, I e)
|
|
1802
|
+
{
|
|
1803
|
+
if ((e > (std::numeric_limits<Exponent>::max)()) || (e < (std::numeric_limits<Exponent>::min)()))
|
|
1804
|
+
{
|
|
1805
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
|
|
1806
|
+
if (e < 0)
|
|
1807
|
+
res.negate();
|
|
1808
|
+
}
|
|
1809
|
+
else
|
|
1810
|
+
eval_ldexp(res, arg, static_cast<Exponent>(e));
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
/*
|
|
1814
|
+
* Sign manipulation
|
|
1815
|
+
*/
|
|
1816
|
+
|
|
1817
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
|
|
1818
|
+
unsigned Digits2, digit_base_type DigitBase2, class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2>
|
|
1819
|
+
inline void eval_abs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits2, DigitBase2, Allocator2, Exponent2, MinE2, MaxE2>& arg)
|
|
1820
|
+
{
|
|
1821
|
+
res = arg;
|
|
1822
|
+
res.sign() = false;
|
|
1823
|
+
}
|
|
1824
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1825
|
+
inline void eval_abs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
|
1826
|
+
{
|
|
1827
|
+
res = arg;
|
|
1828
|
+
res.sign() = false;
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
|
|
1832
|
+
unsigned Digits2, digit_base_type DigitBase2, class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2>
|
|
1833
|
+
inline void eval_fabs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits2, DigitBase2, Allocator2, Exponent2, MinE2, MaxE2>& arg)
|
|
1834
|
+
{
|
|
1835
|
+
res = arg;
|
|
1836
|
+
res.sign() = false;
|
|
1837
|
+
}
|
|
1838
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1839
|
+
inline void eval_fabs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
|
1840
|
+
{
|
|
1841
|
+
res = arg;
|
|
1842
|
+
res.sign() = false;
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1846
|
+
inline int eval_fpclassify(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
|
1847
|
+
{
|
|
1848
|
+
switch (arg.exponent())
|
|
1849
|
+
{
|
|
1850
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
|
1851
|
+
return FP_ZERO;
|
|
1852
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
|
1853
|
+
return FP_INFINITE;
|
|
1854
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
|
1855
|
+
return FP_NAN;
|
|
1856
|
+
}
|
|
1857
|
+
return FP_NORMAL;
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1861
|
+
inline void eval_sqrt(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
|
1862
|
+
{
|
|
1863
|
+
using default_ops::eval_bit_test;
|
|
1864
|
+
using default_ops::eval_increment;
|
|
1865
|
+
using default_ops::eval_integer_sqrt;
|
|
1866
|
+
switch (arg.exponent())
|
|
1867
|
+
{
|
|
1868
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
|
1869
|
+
errno = EDOM;
|
|
1870
|
+
// fallthrough...
|
|
1871
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
|
1872
|
+
res = arg;
|
|
1873
|
+
return;
|
|
1874
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
|
1875
|
+
if (arg.sign())
|
|
1876
|
+
{
|
|
1877
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
|
1878
|
+
errno = EDOM;
|
|
1879
|
+
}
|
|
1880
|
+
else
|
|
1881
|
+
res = arg;
|
|
1882
|
+
return;
|
|
1883
|
+
}
|
|
1884
|
+
if (arg.sign())
|
|
1885
|
+
{
|
|
1886
|
+
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
|
1887
|
+
errno = EDOM;
|
|
1888
|
+
return;
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(arg.bits()), r, s;
|
|
1892
|
+
eval_left_shift(t, arg.exponent() & 1 ? cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count : cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1);
|
|
1893
|
+
eval_integer_sqrt(s, r, t);
|
|
1894
|
+
|
|
1895
|
+
if (!eval_bit_test(s, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
|
|
1896
|
+
{
|
|
1897
|
+
// We have exactly the right number of cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in the result, round as required:
|
|
1898
|
+
if (s.compare(r) < 0)
|
|
1899
|
+
{
|
|
1900
|
+
eval_increment(s);
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type ae = arg.exponent();
|
|
1904
|
+
res.exponent() = ae / 2;
|
|
1905
|
+
res.sign() = false;
|
|
1906
|
+
if ((ae & 1) && (ae < 0))
|
|
1907
|
+
--res.exponent();
|
|
1908
|
+
copy_and_round(res, s);
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1912
|
+
inline void eval_floor(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
|
1913
|
+
{
|
|
1914
|
+
using default_ops::eval_increment;
|
|
1915
|
+
switch (arg.exponent())
|
|
1916
|
+
{
|
|
1917
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
|
1918
|
+
errno = EDOM;
|
|
1919
|
+
// fallthrough...
|
|
1920
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
|
1921
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
|
1922
|
+
res = arg;
|
|
1923
|
+
return;
|
|
1924
|
+
}
|
|
1925
|
+
using shift_type = typename std::conditional<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type;
|
|
1926
|
+
shift_type shift =
|
|
1927
|
+
(shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - arg.exponent() - 1;
|
|
1928
|
+
if ((arg.exponent() > (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent) || (shift <= 0))
|
|
1929
|
+
{
|
|
1930
|
+
// Either arg is already an integer, or a special value:
|
|
1931
|
+
res = arg;
|
|
1932
|
+
return;
|
|
1933
|
+
}
|
|
1934
|
+
if (shift >= (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
|
|
1935
|
+
{
|
|
1936
|
+
res = static_cast<signed_limb_type>(arg.sign() ? -1 : 0);
|
|
1937
|
+
return;
|
|
1938
|
+
}
|
|
1939
|
+
bool fractional = (shift_type)eval_lsb(arg.bits()) < shift;
|
|
1940
|
+
res = arg;
|
|
1941
|
+
eval_right_shift(res.bits(), static_cast<double_limb_type>(shift));
|
|
1942
|
+
if (fractional && res.sign())
|
|
1943
|
+
{
|
|
1944
|
+
eval_increment(res.bits());
|
|
1945
|
+
|
|
1946
|
+
const std::ptrdiff_t shift_check =
|
|
1947
|
+
static_cast<std::ptrdiff_t>(static_cast<std::ptrdiff_t>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - 1 - static_cast<std::ptrdiff_t>(shift));
|
|
1948
|
+
|
|
1949
|
+
if (static_cast<std::ptrdiff_t>(eval_msb(res.bits())) != shift_check)
|
|
1950
|
+
{
|
|
1951
|
+
// Must have extended result by one bit in the increment:
|
|
1952
|
+
--shift;
|
|
1953
|
+
++res.exponent();
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
eval_left_shift(res.bits(), static_cast<double_limb_type>(shift));
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
|
1960
|
+
inline void eval_ceil(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
|
1961
|
+
{
|
|
1962
|
+
using default_ops::eval_increment;
|
|
1963
|
+
switch (arg.exponent())
|
|
1964
|
+
{
|
|
1965
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
|
1966
|
+
errno = EDOM;
|
|
1967
|
+
// fallthrough...
|
|
1968
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
|
1969
|
+
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
|
1970
|
+
res = arg;
|
|
1971
|
+
return;
|
|
1972
|
+
}
|
|
1973
|
+
using shift_type = typename std::conditional<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type;
|
|
1974
|
+
shift_type shift = (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - arg.exponent() - 1;
|
|
1975
|
+
if ((arg.exponent() > (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent) || (shift <= 0))
|
|
1976
|
+
{
|
|
1977
|
+
// Either arg is already an integer, or a special value:
|
|
1978
|
+
res = arg;
|
|
1979
|
+
return;
|
|
1980
|
+
}
|
|
1981
|
+
if (shift >= (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
|
|
1982
|
+
{
|
|
1983
|
+
bool s = arg.sign(); // takes care of signed zeros
|
|
1984
|
+
res = static_cast<signed_limb_type>(arg.sign() ? 0 : 1);
|
|
1985
|
+
res.sign() = s;
|
|
1986
|
+
return;
|
|
1987
|
+
}
|
|
1988
|
+
bool fractional = (shift_type)eval_lsb(arg.bits()) < shift;
|
|
1989
|
+
res = arg;
|
|
1990
|
+
eval_right_shift(res.bits(), shift);
|
|
1991
|
+
if (fractional && !res.sign())
|
|
1992
|
+
{
|
|
1993
|
+
eval_increment(res.bits());
|
|
1994
|
+
if ((std::ptrdiff_t)eval_msb(res.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - shift)
|
|
1995
|
+
{
|
|
1996
|
+
// Must have extended result by one bit in the increment:
|
|
1997
|
+
--shift;
|
|
1998
|
+
++res.exponent();
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
eval_left_shift(res.bits(), shift);
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
template <unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2>
|
|
2005
|
+
int eval_signbit(const cpp_bin_float<D1, B1, A1, E1, M1, M2>& val)
|
|
2006
|
+
{
|
|
2007
|
+
return val.sign();
|
|
2008
|
+
}
|
|
2009
|
+
|
|
2010
|
+
template <unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2>
|
|
2011
|
+
inline std::size_t hash_value(const cpp_bin_float<D1, B1, A1, E1, M1, M2>& val)
|
|
2012
|
+
{
|
|
2013
|
+
std::size_t result = hash_value(val.bits());
|
|
2014
|
+
boost::multiprecision::detail::hash_combine(result, val.exponent(), val.sign());
|
|
2015
|
+
return result;
|
|
2016
|
+
}
|
|
2017
|
+
|
|
2018
|
+
} // namespace backends
|
|
2019
|
+
|
|
2020
|
+
namespace detail {
|
|
2021
|
+
|
|
2022
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinExponent, Exponent MaxExponent>
|
|
2023
|
+
struct transcendental_reduction_type<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> >
|
|
2024
|
+
{
|
|
2025
|
+
//
|
|
2026
|
+
// The type used for trigonometric reduction needs 3 times the precision of the base type.
|
|
2027
|
+
// This is double the precision of the original type, plus the largest exponent supported.
|
|
2028
|
+
// As a practical measure the largest argument supported is 1/eps, as supporting larger
|
|
2029
|
+
// arguments requires the division of argument by PI/2 to also be done at higher precision,
|
|
2030
|
+
// otherwise the result (an integer) can not be represented exactly.
|
|
2031
|
+
//
|
|
2032
|
+
// See ARGUMENT REDUCTION FOR HUGE ARGUMENTS. K C Ng.
|
|
2033
|
+
//
|
|
2034
|
+
using type = boost::multiprecision::backends::cpp_bin_float<
|
|
2035
|
+
boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent>::bit_count * 3,
|
|
2036
|
+
boost::multiprecision::backends::digit_base_2,
|
|
2037
|
+
Allocator, Exponent, MinExponent, MaxExponent>;
|
|
2038
|
+
};
|
|
2039
|
+
#ifdef BOOST_HAS_INT128
|
|
2040
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinExponent, Exponent MaxExponent>
|
|
2041
|
+
struct is_convertible_arithmetic<int128_type, boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> > : public std::true_type
|
|
2042
|
+
{};
|
|
2043
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinExponent, Exponent MaxExponent>
|
|
2044
|
+
struct is_convertible_arithmetic<uint128_type, boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> > : public std::true_type
|
|
2045
|
+
{};
|
|
2046
|
+
#endif
|
|
2047
|
+
|
|
2048
|
+
} // namespace detail
|
|
2049
|
+
|
|
2050
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2051
|
+
inline boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>
|
|
2052
|
+
copysign BOOST_PREVENT_MACRO_SUBSTITUTION(
|
|
2053
|
+
const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& a,
|
|
2054
|
+
const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& b)
|
|
2055
|
+
{
|
|
2056
|
+
boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> res(a);
|
|
2057
|
+
res.backend().sign() = b.backend().sign();
|
|
2058
|
+
return res;
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
template <unsigned Digits, backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator>
|
|
2062
|
+
struct number_category<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > : public std::integral_constant<int, boost::multiprecision::number_kind_floating_point>
|
|
2063
|
+
{};
|
|
2064
|
+
|
|
2065
|
+
template <unsigned Digits, backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2>
|
|
2066
|
+
struct is_equivalent_number_type<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2> >
|
|
2067
|
+
: public std::integral_constant<bool, true> {};
|
|
2068
|
+
|
|
2069
|
+
} // namespace multiprecision
|
|
2070
|
+
|
|
2071
|
+
namespace math {
|
|
2072
|
+
|
|
2073
|
+
using boost::multiprecision::copysign;
|
|
2074
|
+
using boost::multiprecision::signbit;
|
|
2075
|
+
|
|
2076
|
+
} // namespace math
|
|
2077
|
+
|
|
2078
|
+
} // namespace boost
|
|
2079
|
+
|
|
2080
|
+
#include <boost/multiprecision/cpp_bin_float/io.hpp>
|
|
2081
|
+
#include <boost/multiprecision/cpp_bin_float/transcendental.hpp>
|
|
2082
|
+
|
|
2083
|
+
namespace std {
|
|
2084
|
+
|
|
2085
|
+
//
|
|
2086
|
+
// numeric_limits [partial] specializations for the types declared in this header:
|
|
2087
|
+
//
|
|
2088
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2089
|
+
class numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >
|
|
2090
|
+
{
|
|
2091
|
+
using number_type = boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>;
|
|
2092
|
+
|
|
2093
|
+
private:
|
|
2094
|
+
//
|
|
2095
|
+
// Functions to calculate cached values stored in static values:
|
|
2096
|
+
//
|
|
2097
|
+
static number_type get_min()
|
|
2098
|
+
{
|
|
2099
|
+
using ui_type = typename std::tuple_element<0, typename number_type::backend_type::unsigned_types>::type;
|
|
2100
|
+
number_type value(ui_type(1u));
|
|
2101
|
+
value.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
|
|
2102
|
+
return value;
|
|
2103
|
+
}
|
|
2104
|
+
#ifdef BOOST_MSVC
|
|
2105
|
+
#pragma warning(push)
|
|
2106
|
+
#pragma warning(disable : 4127) // conditional expression is constant
|
|
2107
|
+
#endif
|
|
2108
|
+
static number_type get_max()
|
|
2109
|
+
{
|
|
2110
|
+
number_type value;
|
|
2111
|
+
BOOST_IF_CONSTEXPR(std::is_void<Allocator>::value)
|
|
2112
|
+
eval_complement(value.backend().bits(), value.backend().bits());
|
|
2113
|
+
else
|
|
2114
|
+
{
|
|
2115
|
+
// We jump through hoops here using the backend type directly just to keep VC12 happy
|
|
2116
|
+
// (ie compiler workaround, for very strange compiler bug):
|
|
2117
|
+
using boost::multiprecision::default_ops::eval_add;
|
|
2118
|
+
using boost::multiprecision::default_ops::eval_decrement;
|
|
2119
|
+
using boost::multiprecision::default_ops::eval_left_shift;
|
|
2120
|
+
using int_backend_type = typename number_type::backend_type::rep_type;
|
|
2121
|
+
using ui_type = typename std::tuple_element<0, typename int_backend_type::unsigned_types>::type;
|
|
2122
|
+
int_backend_type i;
|
|
2123
|
+
i = ui_type(1u);
|
|
2124
|
+
eval_left_shift(i, boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1);
|
|
2125
|
+
int_backend_type j(i);
|
|
2126
|
+
eval_decrement(i);
|
|
2127
|
+
eval_add(j, i);
|
|
2128
|
+
value.backend().bits() = j;
|
|
2129
|
+
}
|
|
2130
|
+
value.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
|
|
2131
|
+
return value;
|
|
2132
|
+
}
|
|
2133
|
+
#ifdef BOOST_MSVC
|
|
2134
|
+
#pragma warning(pop)
|
|
2135
|
+
#endif
|
|
2136
|
+
static number_type get_epsilon()
|
|
2137
|
+
{
|
|
2138
|
+
using ui_type = typename std::tuple_element<0, typename number_type::backend_type::unsigned_types>::type;
|
|
2139
|
+
number_type value(ui_type(1u));
|
|
2140
|
+
return ldexp(value, 1 - static_cast<int>(digits));
|
|
2141
|
+
}
|
|
2142
|
+
// What value should this be????
|
|
2143
|
+
static number_type get_round_error()
|
|
2144
|
+
{
|
|
2145
|
+
// returns 0.5
|
|
2146
|
+
return ldexp(number_type(1u), -1);
|
|
2147
|
+
}
|
|
2148
|
+
static number_type get_infinity()
|
|
2149
|
+
{
|
|
2150
|
+
number_type value;
|
|
2151
|
+
value.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
|
|
2152
|
+
return value;
|
|
2153
|
+
}
|
|
2154
|
+
static number_type get_quiet_NaN()
|
|
2155
|
+
{
|
|
2156
|
+
number_type value;
|
|
2157
|
+
value.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan;
|
|
2158
|
+
return value;
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
public:
|
|
2162
|
+
static constexpr bool is_specialized = true;
|
|
2163
|
+
static number_type(min)()
|
|
2164
|
+
{
|
|
2165
|
+
// C++11 thread safe static initialization:
|
|
2166
|
+
static number_type value = get_min();
|
|
2167
|
+
return value;
|
|
2168
|
+
}
|
|
2169
|
+
static number_type(max)()
|
|
2170
|
+
{
|
|
2171
|
+
// C++11 thread safe static initialization:
|
|
2172
|
+
static number_type value = get_max();
|
|
2173
|
+
return value;
|
|
2174
|
+
}
|
|
2175
|
+
static constexpr number_type lowest()
|
|
2176
|
+
{
|
|
2177
|
+
return -(max)();
|
|
2178
|
+
}
|
|
2179
|
+
static constexpr int digits = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count;
|
|
2180
|
+
static constexpr int digits10 = boost::multiprecision::detail::calc_digits10<static_cast<unsigned>(digits)>::value;
|
|
2181
|
+
// Is this really correct???
|
|
2182
|
+
static constexpr int max_digits10 = boost::multiprecision::detail::calc_max_digits10<static_cast<unsigned>(digits)>::value;
|
|
2183
|
+
static constexpr bool is_signed = true;
|
|
2184
|
+
static constexpr bool is_integer = false;
|
|
2185
|
+
static constexpr bool is_exact = false;
|
|
2186
|
+
static constexpr int radix = 2;
|
|
2187
|
+
static number_type epsilon()
|
|
2188
|
+
{
|
|
2189
|
+
// C++11 thread safe static initialization:
|
|
2190
|
+
static number_type value = get_epsilon();
|
|
2191
|
+
return value;
|
|
2192
|
+
}
|
|
2193
|
+
// What value should this be????
|
|
2194
|
+
static number_type round_error()
|
|
2195
|
+
{
|
|
2196
|
+
// returns 0.5
|
|
2197
|
+
// C++11 thread safe static initialization:
|
|
2198
|
+
static number_type value = get_round_error();
|
|
2199
|
+
return value;
|
|
2200
|
+
}
|
|
2201
|
+
static constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type min_exponent = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
|
|
2202
|
+
static constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type min_exponent10 = (min_exponent / 1000) * 301L;
|
|
2203
|
+
static constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type max_exponent = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
|
|
2204
|
+
static constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type max_exponent10 = (max_exponent / 1000) * 301L;
|
|
2205
|
+
static constexpr bool has_infinity = true;
|
|
2206
|
+
static constexpr bool has_quiet_NaN = true;
|
|
2207
|
+
static constexpr bool has_signaling_NaN = false;
|
|
2208
|
+
#ifdef _MSC_VER
|
|
2209
|
+
#pragma warning(push)
|
|
2210
|
+
#pragma warning(disable:4996)
|
|
2211
|
+
#endif
|
|
2212
|
+
static constexpr float_denorm_style has_denorm = denorm_absent;
|
|
2213
|
+
#ifdef _MSC_VER
|
|
2214
|
+
#pragma warning(pop)
|
|
2215
|
+
#endif
|
|
2216
|
+
static constexpr bool has_denorm_loss = false;
|
|
2217
|
+
static number_type infinity()
|
|
2218
|
+
{
|
|
2219
|
+
// C++11 thread safe static initialization:
|
|
2220
|
+
static number_type value = get_infinity();
|
|
2221
|
+
return value;
|
|
2222
|
+
}
|
|
2223
|
+
static number_type quiet_NaN()
|
|
2224
|
+
{
|
|
2225
|
+
// C++11 thread safe static initialization:
|
|
2226
|
+
static number_type value = get_quiet_NaN();
|
|
2227
|
+
return value;
|
|
2228
|
+
}
|
|
2229
|
+
static constexpr number_type signaling_NaN()
|
|
2230
|
+
{
|
|
2231
|
+
return number_type(0);
|
|
2232
|
+
}
|
|
2233
|
+
static constexpr number_type denorm_min() { return get_min(); }
|
|
2234
|
+
static constexpr bool is_iec559 = false;
|
|
2235
|
+
static constexpr bool is_bounded = true;
|
|
2236
|
+
static constexpr bool is_modulo = false;
|
|
2237
|
+
static constexpr bool traps = true;
|
|
2238
|
+
static constexpr bool tinyness_before = false;
|
|
2239
|
+
static constexpr float_round_style round_style = round_to_nearest;
|
|
2240
|
+
};
|
|
2241
|
+
|
|
2242
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2243
|
+
constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::digits;
|
|
2244
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2245
|
+
constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::digits10;
|
|
2246
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2247
|
+
constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_digits10;
|
|
2248
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2249
|
+
constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_signed;
|
|
2250
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2251
|
+
constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_integer;
|
|
2252
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2253
|
+
constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_exact;
|
|
2254
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2255
|
+
constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::radix;
|
|
2256
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2257
|
+
constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::min_exponent;
|
|
2258
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2259
|
+
constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::min_exponent10;
|
|
2260
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2261
|
+
constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_exponent;
|
|
2262
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2263
|
+
constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_exponent10;
|
|
2264
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2265
|
+
constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_infinity;
|
|
2266
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2267
|
+
constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_quiet_NaN;
|
|
2268
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2269
|
+
constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_signaling_NaN;
|
|
2270
|
+
#ifdef _MSC_VER
|
|
2271
|
+
#pragma warning(push)
|
|
2272
|
+
#pragma warning(disable:4996)
|
|
2273
|
+
#endif
|
|
2274
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2275
|
+
constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_denorm;
|
|
2276
|
+
#ifdef _MSC_VER
|
|
2277
|
+
#pragma warning(pop)
|
|
2278
|
+
#endif
|
|
2279
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2280
|
+
constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_denorm_loss;
|
|
2281
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2282
|
+
constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_iec559;
|
|
2283
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2284
|
+
constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_bounded;
|
|
2285
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2286
|
+
constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_modulo;
|
|
2287
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2288
|
+
constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::traps;
|
|
2289
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2290
|
+
constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::tinyness_before;
|
|
2291
|
+
template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
|
2292
|
+
constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::round_style;
|
|
2293
|
+
|
|
2294
|
+
|
|
2295
|
+
} // namespace std
|
|
2296
|
+
|
|
2297
|
+
#endif
|