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