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