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,848 @@
1
+ ///////////////////////////////////////////////////////////////
2
+ // Copyright 2012-20 John Maddock.
3
+ // Copyright 2019-20 Christopher Kormanyos.
4
+ // Copyright 2019-20 Madhur Chauhan.
5
+ // Distributed under the Boost Software License, Version 1.0.
6
+ // (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
7
+ //
8
+ // Comparison operators for cpp_int_backend:
9
+ //
10
+ #ifndef BOOST_MP_CPP_INT_MULTIPLY_HPP
11
+ #define BOOST_MP_CPP_INT_MULTIPLY_HPP
12
+
13
+ #include <limits>
14
+ #include <boost/multiprecision/detail/standalone_config.hpp>
15
+ #include <boost/multiprecision/detail/endian.hpp>
16
+ #include <boost/multiprecision/detail/assert.hpp>
17
+ #include <boost/multiprecision/integer.hpp>
18
+
19
+ namespace boost { namespace multiprecision { namespace backends {
20
+
21
+ #ifdef BOOST_MSVC
22
+ #pragma warning(push)
23
+ #pragma warning(disable : 4127) // conditional expression is constant
24
+ #endif
25
+ //
26
+ // Multiplication by a single limb:
27
+ //
28
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
29
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
30
+ eval_multiply(
31
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
32
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
33
+ const limb_type& val) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
34
+ {
35
+ if (!val)
36
+ {
37
+ result = static_cast<limb_type>(0);
38
+ return;
39
+ }
40
+ if ((void*)&a != (void*)&result)
41
+ result.resize(a.size(), a.size());
42
+ double_limb_type carry = 0;
43
+ typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer p = result.limbs();
44
+ typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer pe = result.limbs() + result.size();
45
+ typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::const_limb_pointer pa = a.limbs();
46
+ while (p != pe)
47
+ {
48
+ carry += static_cast<double_limb_type>(*pa) * static_cast<double_limb_type>(val);
49
+ #ifdef __MSVC_RUNTIME_CHECKS
50
+ *p = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
51
+ #else
52
+ *p = static_cast<limb_type>(carry);
53
+ #endif
54
+ carry >>= cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
55
+ ++p, ++pa;
56
+ }
57
+ if (carry)
58
+ {
59
+ std::size_t i = result.size();
60
+ result.resize(i + 1, i + 1);
61
+ if (result.size() > i)
62
+ result.limbs()[i] = static_cast<limb_type>(carry);
63
+ }
64
+ result.sign(a.sign());
65
+ if (is_fixed_precision<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
66
+ result.normalize();
67
+ }
68
+
69
+ //
70
+ // resize_for_carry forces a resize of the underlying buffer only if a previous request
71
+ // for "required" elements could possibly have failed, *and* we have checking enabled.
72
+ // This will cause an overflow error inside resize():
73
+ //
74
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
75
+ inline BOOST_MP_CXX14_CONSTEXPR void resize_for_carry(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& /*result*/, std::size_t /*required*/) {}
76
+
77
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, class Allocator1>
78
+ inline BOOST_MP_CXX14_CONSTEXPR void resize_for_carry(cpp_int_backend<MinBits1, MaxBits1, SignType1, checked, Allocator1>& result, std::size_t required)
79
+ {
80
+ if (result.size() < required)
81
+ result.resize(required, required);
82
+ }
83
+ //
84
+ // Minimum number of limbs required for Karatsuba to be worthwhile:
85
+ //
86
+ #ifdef BOOST_MP_KARATSUBA_CUTOFF
87
+ const size_t karatsuba_cutoff = BOOST_MP_KARATSUBA_CUTOFF;
88
+ #else
89
+ const size_t karatsuba_cutoff = 40;
90
+ #endif
91
+ //
92
+ // Core (recursive) Karatsuba multiplication, all the storage required is allocated upfront and
93
+ // passed down the stack in this routine. Note that all the cpp_int_backend's must be the same type
94
+ // and full variable precision. Karatsuba really doesn't play nice with fixed-size integers. If necessary
95
+ // fixed precision integers will get aliased as variable-precision types before this is called.
96
+ //
97
+ template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
98
+ inline void multiply_karatsuba(
99
+ cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& result,
100
+ const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a,
101
+ const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& b,
102
+ typename cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>::scoped_shared_storage& storage)
103
+ {
104
+ using cpp_int_type = cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>;
105
+
106
+ std::size_t as = a.size();
107
+ std::size_t bs = b.size();
108
+ //
109
+ // Termination condition: if either argument is smaller than karatsuba_cutoff
110
+ // then schoolboy multiplication will be faster:
111
+ //
112
+ if ((as < karatsuba_cutoff) || (bs < karatsuba_cutoff))
113
+ {
114
+ eval_multiply(result, a, b);
115
+ return;
116
+ }
117
+ //
118
+ // Partitioning size: split the larger of a and b into 2 halves
119
+ //
120
+ std::size_t n = (as > bs ? as : bs) / 2 + 1;
121
+ //
122
+ // Partition a and b into high and low parts.
123
+ // ie write a, b as a = a_h * 2^n + a_l, b = b_h * 2^n + b_l
124
+ //
125
+ // We could copy the high and low parts into new variables, but we'll
126
+ // use aliasing to reference the internal limbs of a and b. There is one wart here:
127
+ // if a and b are mismatched in size, then n may be larger than the smaller
128
+ // of a and b. In that situation the high part is zero, and we have no limbs
129
+ // to alias, so instead alias a local variable.
130
+ // This raises 2 questions:
131
+ // * Is this the best way to partition a and b?
132
+ // * Since we have one high part zero, the arithmetic simplifies considerably,
133
+ // so should we have a special routine for this?
134
+ //
135
+ std::size_t sz = (std::min)(as, n);
136
+ const cpp_int_type a_l(a.limbs(), 0, sz);
137
+
138
+ sz = (std::min)(bs, n);
139
+ const cpp_int_type b_l(b.limbs(), 0, sz);
140
+
141
+ limb_type zero = 0;
142
+ const cpp_int_type a_h(as > n ? a.limbs() + n : &zero, 0, as > n ? as - n : 1);
143
+ const cpp_int_type b_h(bs > n ? b.limbs() + n : &zero, 0, bs > n ? bs - n : 1);
144
+ //
145
+ // The basis for the Karatsuba algorithm is as follows:
146
+ //
147
+ // let x = a_h * b_ h
148
+ // y = a_l * b_l
149
+ // z = (a_h + a_l)*(b_h + b_l) - x - y
150
+ // and therefore a * b = x * (2 ^ (2 * n))+ z * (2 ^ n) + y
151
+ //
152
+ // Begin by allocating our temporaries, these alias the memory already allocated in the shared storage:
153
+ //
154
+ cpp_int_type t1(storage, 2 * n + 2);
155
+ cpp_int_type t2(storage, n + 1);
156
+ cpp_int_type t3(storage, n + 1);
157
+ //
158
+ // Now we want:
159
+ //
160
+ // result = | a_h*b_h | a_l*b_l |
161
+ // (bits) <-- 2*n -->
162
+ //
163
+ // We create aliases for the low and high parts of result, and multiply directly into them:
164
+ //
165
+ cpp_int_type result_low(result.limbs(), 0, 2 * n);
166
+ cpp_int_type result_high(result.limbs(), 2 * n, result.size() - 2 * n);
167
+ //
168
+ // low part of result is a_l * b_l:
169
+ //
170
+ multiply_karatsuba(result_low, a_l, b_l, storage);
171
+ //
172
+ // We haven't zeroed out memory in result, so set to zero any unused limbs,
173
+ // if a_l and b_l have mostly random bits then nothing happens here, but if
174
+ // one is zero or nearly so, then a memset might be faster... it's not clear
175
+ // that it's worth the extra logic though (and is darn hard to measure
176
+ // what the "average" case is).
177
+ //
178
+ for (std::size_t i = result_low.size(); i < 2 * n; ++i)
179
+ result.limbs()[i] = 0;
180
+ //
181
+ // Set the high part of result to a_h * b_h:
182
+ //
183
+ multiply_karatsuba(result_high, a_h, b_h, storage);
184
+ for (std::size_t i = result_high.size() + 2 * n; i < result.size(); ++i)
185
+ result.limbs()[i] = 0;
186
+ //
187
+ // Now calculate (a_h+a_l)*(b_h+b_l):
188
+ //
189
+ add_unsigned(t2, a_l, a_h);
190
+ add_unsigned(t3, b_l, b_h);
191
+ multiply_karatsuba(t1, t2, t3, storage); // t1 = (a_h+a_l)*(b_h+b_l)
192
+ //
193
+ // There is now a slight deviation from Karatsuba, we want to subtract
194
+ // a_l*b_l + a_h*b_h from t1, but rather than use an addition and a subtraction
195
+ // plus one temporary, we'll use 2 subtractions. On the minus side, a subtraction
196
+ // is on average slightly slower than an addition, but we save a temporary (ie memory)
197
+ // and also hammer the same piece of memory over and over rather than 2 disparate
198
+ // memory regions. Overall it seems to be a slight win.
199
+ //
200
+ subtract_unsigned(t1, t1, result_high);
201
+ subtract_unsigned(t1, t1, result_low);
202
+ //
203
+ // The final step is to left shift t1 by n bits and add to the result.
204
+ // Rather than do an actual left shift, we can simply alias the result
205
+ // and add to the alias:
206
+ //
207
+ cpp_int_type result_alias(result.limbs(), n, result.size() - n);
208
+ add_unsigned(result_alias, result_alias, t1);
209
+ //
210
+ // Free up storage for use by sister branches to this one:
211
+ //
212
+ storage.deallocate(t1.capacity() + t2.capacity() + t3.capacity());
213
+
214
+ result.normalize();
215
+ }
216
+
217
+ inline std::size_t karatsuba_storage_size(std::size_t s)
218
+ {
219
+ //
220
+ // This estimates how much memory we will need based on
221
+ // s-limb multiplication. In an ideal world the number of limbs
222
+ // would halve with each recursion, and our storage requirements
223
+ // would be 4s in the limit, and rather less in practice since
224
+ // we bail out long before we reach one limb. In the real world
225
+ // we don't quite halve s in each recursion, so this is an heuristic
226
+ // which over-estimates how much we need. We could compute an exact
227
+ // value, but it would be rather time consuming.
228
+ //
229
+ return 5 * s;
230
+ }
231
+ //
232
+ // There are 2 entry point routines for Karatsuba multiplication:
233
+ // one for variable precision types, and one for fixed precision types.
234
+ // These are responsible for allocating all the storage required for the recursive
235
+ // routines above, and are always at the outermost level.
236
+ //
237
+ // Normal variable precision case comes first:
238
+ //
239
+ template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
240
+ inline typename std::enable_if<!is_fixed_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value>::type
241
+ setup_karatsuba(
242
+ cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& result,
243
+ const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& a,
244
+ const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& b)
245
+ {
246
+ std::size_t as = a.size();
247
+ std::size_t bs = b.size();
248
+ std::size_t s = as > bs ? as : bs;
249
+ std::size_t storage_size = karatsuba_storage_size(s);
250
+ if (storage_size < 300)
251
+ {
252
+ //
253
+ // Special case: if we don't need too much memory, we can use stack based storage
254
+ // and save a call to the allocator, this allows us to use Karatsuba multiply
255
+ // at lower limb counts than would otherwise be possible:
256
+ //
257
+ limb_type limbs[300];
258
+ typename cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::scoped_shared_storage storage(limbs, storage_size);
259
+ multiply_karatsuba(result, a, b, storage);
260
+ }
261
+ else
262
+ {
263
+ typename cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::scoped_shared_storage storage(result.allocator(), storage_size);
264
+ multiply_karatsuba(result, a, b, storage);
265
+ }
266
+ }
267
+
268
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
269
+ inline typename std::enable_if<is_fixed_precision<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_fixed_precision<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value || is_fixed_precision<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
270
+ setup_karatsuba(
271
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
272
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
273
+ const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
274
+ {
275
+ //
276
+ // Now comes the fixed precision case.
277
+ // In fact Karatsuba doesn't really work with fixed precision since the logic
278
+ // requires that we calculate all the bits of the result (especially in the
279
+ // temporaries used internally). So... we'll convert all the arguments
280
+ // to variable precision types by aliasing them, this also
281
+ // reduce the number of template instantations:
282
+ //
283
+ using variable_precision_type = cpp_int_backend<0, 0, signed_magnitude, unchecked, std::allocator<limb_type> >;
284
+ variable_precision_type a_t(a.limbs(), 0, a.size()), b_t(b.limbs(), 0, b.size());
285
+ std::size_t as = a.size();
286
+ std::size_t bs = b.size();
287
+ std::size_t s = as > bs ? as : bs;
288
+ std::size_t sz = as + bs;
289
+ std::size_t storage_size = karatsuba_storage_size(s);
290
+
291
+ if (!is_fixed_precision<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || (sz * sizeof(limb_type) * CHAR_BIT <= MaxBits1))
292
+ {
293
+ // Result is large enough for all the bits of the result, so we can use aliasing:
294
+ result.resize(sz, sz);
295
+ variable_precision_type t(result.limbs(), 0, result.size());
296
+ typename variable_precision_type::scoped_shared_storage storage(t.allocator(), storage_size);
297
+ multiply_karatsuba(t, a_t, b_t, storage);
298
+ result.resize(t.size(), t.size());
299
+ }
300
+ else
301
+ {
302
+ //
303
+ // Not enough bit in result for the answer, so we must use a temporary
304
+ // and then truncate (ie modular arithmetic):
305
+ //
306
+ typename variable_precision_type::scoped_shared_storage storage(variable_precision_type::allocator_type(), sz + storage_size);
307
+ variable_precision_type t(storage, sz);
308
+ multiply_karatsuba(t, a_t, b_t, storage);
309
+ //
310
+ // If there is truncation, and result is a checked type then this will throw:
311
+ //
312
+ result = t;
313
+ }
314
+ }
315
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
316
+ inline typename std::enable_if<!is_fixed_precision<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_fixed_precision<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_fixed_precision<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
317
+ setup_karatsuba(
318
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
319
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
320
+ const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
321
+ {
322
+ //
323
+ // Variable precision, mixed arguments, just alias and forward:
324
+ //
325
+ using variable_precision_type = cpp_int_backend<0, 0, signed_magnitude, unchecked, std::allocator<limb_type> >;
326
+ variable_precision_type a_t(a.limbs(), 0, a.size()), b_t(b.limbs(), 0, b.size());
327
+ std::size_t as = a.size();
328
+ std::size_t bs = b.size();
329
+ std::size_t s = as > bs ? as : bs;
330
+ std::size_t sz = as + bs;
331
+ std::size_t storage_size = karatsuba_storage_size(s);
332
+
333
+ result.resize(sz, sz);
334
+ variable_precision_type t(result.limbs(), 0, result.size());
335
+ typename variable_precision_type::scoped_shared_storage storage(t.allocator(), storage_size);
336
+ multiply_karatsuba(t, a_t, b_t, storage);
337
+ }
338
+
339
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
340
+ inline BOOST_MP_CXX14_CONSTEXPR void
341
+ eval_multiply_comba(
342
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
343
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
344
+ const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
345
+ {
346
+ //
347
+ // see PR #182
348
+ // Comba Multiplier - based on Paul Comba's
349
+ // Exponentiation cryptosystems on the IBM PC, 1990
350
+ //
351
+ std::ptrdiff_t as = a.size(),
352
+ bs = b.size(),
353
+ rs = result.size();
354
+ typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer pr = result.limbs();
355
+
356
+ double_limb_type carry = 0,
357
+ temp = 0;
358
+ limb_type overflow = 0;
359
+ const std::size_t limb_bits = sizeof(limb_type) * CHAR_BIT;
360
+ const bool must_throw = rs < as + bs - 1;
361
+ for (std::ptrdiff_t r = 0, lim = (std::min)(rs, as + bs - 1); r < lim; ++r, overflow = 0)
362
+ {
363
+ std::ptrdiff_t i = r >= as ? as - 1 : r,
364
+ j = r - i,
365
+ k = i < bs - j ? i + 1 : bs - j; // min(i+1, bs-j);
366
+
367
+ typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::const_limb_pointer pa = a.limbs() + i;
368
+ typename cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>::const_limb_pointer pb = b.limbs() + j;
369
+
370
+ temp = carry;
371
+ carry += static_cast<double_limb_type>(*(pa)) * (*(pb));
372
+ overflow += carry < temp;
373
+ for (--k; k; k--)
374
+ {
375
+ temp = carry;
376
+ carry += static_cast<double_limb_type>(*(--pa)) * (*(++pb));
377
+ overflow += carry < temp;
378
+ }
379
+ *(pr++) = static_cast<limb_type>(carry);
380
+ carry = (static_cast<double_limb_type>(overflow) << limb_bits) | (carry >> limb_bits);
381
+ }
382
+ if (carry || must_throw)
383
+ {
384
+ resize_for_carry(result, as + bs);
385
+ if (static_cast<int>(result.size()) >= as + bs)
386
+ *pr = static_cast<limb_type>(carry);
387
+ }
388
+ }
389
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
390
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
391
+ eval_multiply(
392
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
393
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
394
+ const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
395
+ noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
396
+ && (karatsuba_cutoff * sizeof(limb_type) * CHAR_BIT > MaxBits1)
397
+ && (karatsuba_cutoff * sizeof(limb_type)* CHAR_BIT > MaxBits2)
398
+ && (karatsuba_cutoff * sizeof(limb_type)* CHAR_BIT > MaxBits3)))
399
+ {
400
+ // Uses simple (O(n^2)) multiplication when the limbs are less
401
+ // otherwise switches to karatsuba algorithm based on experimental value (~40 limbs)
402
+ //
403
+ // Trivial cases first:
404
+ //
405
+ std::size_t as = a.size();
406
+ std::size_t bs = b.size();
407
+ typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::const_limb_pointer pa = a.limbs();
408
+ typename cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>::const_limb_pointer pb = b.limbs();
409
+ if (as == 1)
410
+ {
411
+ bool s = b.sign() != a.sign();
412
+ if (bs == 1)
413
+ {
414
+ result = static_cast<double_limb_type>(*pa) * static_cast<double_limb_type>(*pb);
415
+ }
416
+ else
417
+ {
418
+ limb_type l = *pa;
419
+ eval_multiply(result, b, l);
420
+ }
421
+ result.sign(s);
422
+ return;
423
+ }
424
+ if (bs == 1)
425
+ {
426
+ bool s = b.sign() != a.sign();
427
+ limb_type l = *pb;
428
+ eval_multiply(result, a, l);
429
+ result.sign(s);
430
+ return;
431
+ }
432
+
433
+ if ((void*)&result == (void*)&a)
434
+ {
435
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(a);
436
+ eval_multiply(result, t, b);
437
+ return;
438
+ }
439
+ if ((void*)&result == (void*)&b)
440
+ {
441
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(b);
442
+ eval_multiply(result, a, t);
443
+ return;
444
+ }
445
+
446
+ constexpr double_limb_type limb_max = static_cast<double_limb_type>(~static_cast<limb_type>(0u));
447
+ constexpr double_limb_type double_limb_max = static_cast<double_limb_type>(~static_cast<double_limb_type>(0u));
448
+
449
+ result.resize(as + bs, as + bs - 1);
450
+ #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
451
+ if (!BOOST_MP_IS_CONST_EVALUATED(as) && (as >= karatsuba_cutoff && bs >= karatsuba_cutoff))
452
+ #else
453
+ if (as >= karatsuba_cutoff && bs >= karatsuba_cutoff)
454
+ #endif
455
+ {
456
+ setup_karatsuba(result, a, b);
457
+ //
458
+ // Set the sign of the result:
459
+ //
460
+ result.sign(a.sign() != b.sign());
461
+ return;
462
+ }
463
+ typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer pr = result.limbs();
464
+ static_assert(double_limb_max - 2 * limb_max >= limb_max * limb_max, "failed limb size sanity check");
465
+
466
+ #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
467
+ if (BOOST_MP_IS_CONST_EVALUATED(as))
468
+ {
469
+ for (std::size_t i = 0; i < result.size(); ++i)
470
+ pr[i] = 0;
471
+ }
472
+ else
473
+ #endif
474
+ std::memset(pr, 0, result.size() * sizeof(limb_type));
475
+
476
+ #if defined(BOOST_MP_COMBA)
477
+ //
478
+ // Comba Multiplier might not be efficient because of less efficient assembly
479
+ // by the compiler as of 09/01/2020 (DD/MM/YY). See PR #182
480
+ // Till then this will lay dormant :(
481
+ //
482
+ eval_multiply_comba(result, a, b);
483
+ #else
484
+
485
+ double_limb_type carry = 0;
486
+ for (std::size_t i = 0; i < as; ++i)
487
+ {
488
+ BOOST_MP_ASSERT(result.size() > i);
489
+ std::size_t inner_limit = !is_fixed_precision<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value ? bs : (std::min)(result.size() - i, bs);
490
+ std::size_t j = 0;
491
+ for (; j < inner_limit; ++j)
492
+ {
493
+ BOOST_MP_ASSERT(i + j < result.size());
494
+ #if (!defined(__GLIBCXX__) && !defined(__GLIBCPP__)) || !BOOST_WORKAROUND(BOOST_GCC_VERSION, <= 50100)
495
+ BOOST_MP_ASSERT(!std::numeric_limits<double_limb_type>::is_specialized || ((std::numeric_limits<double_limb_type>::max)() - carry >
496
+ static_cast<double_limb_type>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value) * static_cast<double_limb_type>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value)));
497
+ #endif
498
+ carry += static_cast<double_limb_type>(pa[i]) * static_cast<double_limb_type>(pb[j]);
499
+ BOOST_MP_ASSERT(!std::numeric_limits<double_limb_type>::is_specialized || ((std::numeric_limits<double_limb_type>::max)() - carry >= pr[i + j]));
500
+ carry += pr[i + j];
501
+ #ifdef __MSVC_RUNTIME_CHECKS
502
+ pr[i + j] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
503
+ #else
504
+ pr[i + j] = static_cast<limb_type>(carry);
505
+ #endif
506
+ carry >>= cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
507
+ BOOST_MP_ASSERT(carry <= (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value));
508
+ }
509
+ if (carry)
510
+ {
511
+ resize_for_carry(result, i + j + 1); // May throw if checking is enabled
512
+ if (i + j < result.size())
513
+ #ifdef __MSVC_RUNTIME_CHECKS
514
+ pr[i + j] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
515
+ #else
516
+ pr[i + j] = static_cast<limb_type>(carry);
517
+ #endif
518
+ }
519
+ carry = 0;
520
+ }
521
+ #endif // ifdef(BOOST_MP_COMBA) ends
522
+
523
+ result.normalize();
524
+ //
525
+ // Set the sign of the result:
526
+ //
527
+ result.sign(a.sign() != b.sign());
528
+ }
529
+
530
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
531
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
532
+ eval_multiply(
533
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
534
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a)
535
+ noexcept((noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>&>()))))
536
+ {
537
+ eval_multiply(result, result, a);
538
+ }
539
+
540
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
541
+ 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
542
+ eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const limb_type& val)
543
+ noexcept((noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const limb_type&>()))))
544
+ {
545
+ eval_multiply(result, result, val);
546
+ }
547
+
548
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
549
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
550
+ eval_multiply(
551
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
552
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
553
+ const double_limb_type& val)
554
+ noexcept(
555
+ (noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>&>(), std::declval<const limb_type&>())))
556
+ && (noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>())))
557
+ )
558
+ {
559
+ if (val <= (std::numeric_limits<limb_type>::max)())
560
+ {
561
+ eval_multiply(result, a, static_cast<limb_type>(val));
562
+ }
563
+ else
564
+ {
565
+ #if BOOST_MP_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
566
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(val);
567
+ #else
568
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
569
+ t = val;
570
+ #endif
571
+ eval_multiply(result, a, t);
572
+ }
573
+ }
574
+
575
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
576
+ 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
577
+ eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const double_limb_type& val)
578
+ noexcept((noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const double_limb_type&>()))))
579
+ {
580
+ eval_multiply(result, result, val);
581
+ }
582
+
583
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
584
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
585
+ eval_multiply(
586
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
587
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
588
+ const signed_limb_type& val)
589
+ noexcept((noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>&>(), std::declval<const limb_type&>()))))
590
+ {
591
+ if (val > 0)
592
+ eval_multiply(result, a, static_cast<limb_type>(val));
593
+ else
594
+ {
595
+ eval_multiply(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(val)));
596
+ result.negate();
597
+ }
598
+ }
599
+
600
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
601
+ 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
602
+ eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const signed_limb_type& val)
603
+ noexcept((noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const limb_type&>()))))
604
+ {
605
+ eval_multiply(result, result, val);
606
+ }
607
+
608
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
609
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
610
+ eval_multiply(
611
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
612
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
613
+ const signed_double_limb_type& val)
614
+ noexcept(
615
+ (noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>&>(), std::declval<const limb_type&>())))
616
+ && (noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>())))
617
+ )
618
+ {
619
+ if (val > 0)
620
+ {
621
+ if (val <= (std::numeric_limits<limb_type>::max)())
622
+ {
623
+ eval_multiply(result, a, static_cast<limb_type>(val));
624
+ return;
625
+ }
626
+ }
627
+ else if (val >= -static_cast<signed_double_limb_type>((std::numeric_limits<limb_type>::max)()))
628
+ {
629
+ eval_multiply(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(val)));
630
+ result.negate();
631
+ return;
632
+ }
633
+ #if BOOST_MP_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
634
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(val);
635
+ #else
636
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
637
+ t = val;
638
+ #endif
639
+ eval_multiply(result, a, t);
640
+ }
641
+
642
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
643
+ 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
644
+ eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const signed_double_limb_type& val)
645
+ noexcept(
646
+ (noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const limb_type&>())))
647
+ && (noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>())))
648
+ )
649
+ {
650
+ eval_multiply(result, result, val);
651
+ }
652
+
653
+ //
654
+ // Now over again for trivial cpp_int's:
655
+ //
656
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
657
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
658
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && 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 || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)>::type
659
+ eval_multiply(
660
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
661
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
662
+ {
663
+ *result.limbs() = detail::checked_multiply(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
664
+ result.sign(result.sign() != o.sign());
665
+ result.normalize();
666
+ }
667
+
668
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
669
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
670
+ 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>::type
671
+ eval_multiply(
672
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
673
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
674
+ {
675
+ *result.limbs() = detail::checked_multiply(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
676
+ result.normalize();
677
+ }
678
+
679
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
680
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
681
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && 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 || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)>::type
682
+ eval_multiply(
683
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
684
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
685
+ 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))
686
+ {
687
+ *result.limbs() = detail::checked_multiply(*a.limbs(), *b.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
688
+ result.sign(a.sign() != b.sign());
689
+ result.normalize();
690
+ }
691
+
692
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
693
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
694
+ 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>::type
695
+ eval_multiply(
696
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
697
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
698
+ 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))
699
+ {
700
+ *result.limbs() = detail::checked_multiply(*a.limbs(), *b.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
701
+ result.normalize();
702
+ }
703
+
704
+ //
705
+ // Special routines for multiplying two integers to obtain a multiprecision result:
706
+ //
707
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
708
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
709
+ !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
710
+ eval_multiply(
711
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
712
+ signed_double_limb_type a, signed_double_limb_type b)
713
+ {
714
+ constexpr signed_double_limb_type mask = static_cast<signed_double_limb_type>(~static_cast<limb_type>(0));
715
+ constexpr std::size_t limb_bits = static_cast<std::size_t>(sizeof(limb_type) * CHAR_BIT);
716
+
717
+ bool s = false;
718
+ if (a < 0)
719
+ {
720
+ a = -a;
721
+ s = true;
722
+ }
723
+ if (b < 0)
724
+ {
725
+ b = -b;
726
+ s = !s;
727
+ }
728
+ double_limb_type w = a & mask;
729
+ double_limb_type x = static_cast<double_limb_type>(a >> limb_bits);
730
+ double_limb_type y = b & mask;
731
+ double_limb_type z = static_cast<double_limb_type>(b >> limb_bits);
732
+
733
+ result.resize(4, 4);
734
+ limb_type* pr = result.limbs();
735
+
736
+ double_limb_type carry = w * y;
737
+ #ifdef __MSVC_RUNTIME_CHECKS
738
+ pr[0] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
739
+ carry >>= limb_bits;
740
+ carry += w * z + x * y;
741
+ pr[1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
742
+ carry >>= limb_bits;
743
+ carry += x * z;
744
+ pr[2] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
745
+ pr[3] = static_cast<limb_type>(carry >> limb_bits);
746
+ #else
747
+ pr[0] = static_cast<limb_type>(carry);
748
+ carry >>= limb_bits;
749
+ carry += w * z + x * y;
750
+ pr[1] = static_cast<limb_type>(carry);
751
+ carry >>= limb_bits;
752
+ carry += x * z;
753
+ pr[2] = static_cast<limb_type>(carry);
754
+ pr[3] = static_cast<limb_type>(carry >> limb_bits);
755
+ #endif
756
+ result.sign(s);
757
+ result.normalize();
758
+ }
759
+
760
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
761
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
762
+ !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
763
+ eval_multiply(
764
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
765
+ double_limb_type a, double_limb_type b)
766
+ {
767
+ constexpr signed_double_limb_type mask = static_cast<signed_double_limb_type>(~static_cast<limb_type>(0));
768
+ constexpr std::size_t limb_bits = static_cast<std::size_t>(sizeof(limb_type) * CHAR_BIT);
769
+
770
+ double_limb_type w = a & mask;
771
+ double_limb_type x = a >> limb_bits;
772
+ double_limb_type y = b & mask;
773
+ double_limb_type z = b >> limb_bits;
774
+
775
+ result.resize(4, 4);
776
+ limb_type* pr = result.limbs();
777
+
778
+ double_limb_type carry = w * y;
779
+ #ifdef __MSVC_RUNTIME_CHECKS
780
+ pr[0] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
781
+ carry >>= limb_bits;
782
+ carry += w * z;
783
+ pr[1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
784
+ carry >>= limb_bits;
785
+ pr[2] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
786
+ carry = x * y + pr[1];
787
+ pr[1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
788
+ carry >>= limb_bits;
789
+ carry += pr[2] + x * z;
790
+ pr[2] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
791
+ pr[3] = static_cast<limb_type>(carry >> limb_bits);
792
+ #else
793
+ pr[0] = static_cast<limb_type>(carry);
794
+ carry >>= limb_bits;
795
+ carry += w * z;
796
+ pr[1] = static_cast<limb_type>(carry);
797
+ carry >>= limb_bits;
798
+ pr[2] = static_cast<limb_type>(carry);
799
+ carry = x * y + pr[1];
800
+ pr[1] = static_cast<limb_type>(carry);
801
+ carry >>= limb_bits;
802
+ carry += pr[2] + x * z;
803
+ pr[2] = static_cast<limb_type>(carry);
804
+ pr[3] = static_cast<limb_type>(carry >> limb_bits);
805
+ #endif
806
+ result.sign(false);
807
+ result.normalize();
808
+ }
809
+
810
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1,
811
+ std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
812
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
813
+ !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
814
+ eval_multiply(
815
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
816
+ cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> const& a,
817
+ cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> const& b)
818
+ {
819
+ using canonical_type = typename boost::multiprecision::detail::canonical<typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::local_limb_type, cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::type;
820
+ eval_multiply(result, static_cast<canonical_type>(*a.limbs()), static_cast<canonical_type>(*b.limbs()));
821
+ result.sign(a.sign() != b.sign());
822
+ }
823
+
824
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class SI>
825
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_signed<SI>::value && boost::multiprecision::detail::is_integral<SI>::value && (sizeof(SI) <= sizeof(signed_double_limb_type) / 2)>::type
826
+ eval_multiply(
827
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
828
+ SI a, SI b)
829
+ {
830
+ result = static_cast<signed_double_limb_type>(a) * static_cast<signed_double_limb_type>(b);
831
+ }
832
+
833
+ template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class UI>
834
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_unsigned<UI>::value && (sizeof(UI) <= sizeof(signed_double_limb_type) / 2)>::type
835
+ eval_multiply(
836
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
837
+ UI a, UI b)
838
+ {
839
+ result = static_cast<double_limb_type>(a) * static_cast<double_limb_type>(b);
840
+ }
841
+
842
+ #ifdef BOOST_MSVC
843
+ #pragma warning(pop)
844
+ #endif
845
+
846
+ }}} // namespace boost::multiprecision::backends
847
+
848
+ #endif