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,4052 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright 2011-21 John Maddock.
3
+ // Copyright 2021 Iskandarov Lev. Distributed under the Boost
4
+ // Software License, Version 1.0. (See accompanying file
5
+ // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
+
7
+ #ifndef BOOST_MP_DEFAULT_OPS
8
+ #define BOOST_MP_DEFAULT_OPS
9
+
10
+ #include <boost/multiprecision/detail/standalone_config.hpp>
11
+ #include <boost/multiprecision/detail/no_exceptions_support.hpp>
12
+ #include <boost/multiprecision/detail/number_base.hpp>
13
+ #include <boost/multiprecision/detail/assert.hpp>
14
+ #include <boost/multiprecision/traits/is_backend.hpp>
15
+ #include <boost/multiprecision/detail/fpclassify.hpp>
16
+ #include <cstdint>
17
+ #include <complex>
18
+ #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
19
+ #include <string_view>
20
+ #endif
21
+
22
+ #ifdef BOOST_MP_MATH_AVAILABLE
23
+ #include <boost/math/special_functions/fpclassify.hpp>
24
+ #include <boost/math/special_functions/next.hpp>
25
+ #include <boost/math/special_functions/hypot.hpp>
26
+ #include <boost/math/policies/error_handling.hpp>
27
+ #endif
28
+
29
+ #ifndef INSTRUMENT_BACKEND
30
+ #ifndef BOOST_MP_INSTRUMENT
31
+ #define INSTRUMENT_BACKEND(x)
32
+ #else
33
+ #define INSTRUMENT_BACKEND(x) \
34
+ std::cout << BOOST_STRINGIZE(x) << " = " << x.str(0, std::ios_base::scientific) << std::endl;
35
+ #endif
36
+ #endif
37
+
38
+ namespace boost {
39
+ namespace multiprecision {
40
+
41
+ namespace detail {
42
+
43
+ template <class To, class From>
44
+ void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/);
45
+ template <class To, class From>
46
+ void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_integer>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/);
47
+ template <class To, class From>
48
+ void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_floating_point>& /*from_type*/);
49
+ template <class To, class From>
50
+ void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_rational>& /*from_type*/);
51
+ template <class To, class From>
52
+ void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/);
53
+
54
+ template <class Integer>
55
+ BOOST_MP_CXX14_CONSTEXPR Integer karatsuba_sqrt(const Integer& x, Integer& r, size_t bits);
56
+
57
+ } // namespace detail
58
+
59
+ namespace default_ops {
60
+
61
+ template <class T>
62
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_backend<T>::value, int>::type eval_signbit(const T& val);
63
+
64
+ template <class T>
65
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!boost::multiprecision::detail::is_backend<T>::value, int>::type eval_signbit(const T& val) { return val < 0; }
66
+
67
+ inline int eval_signbit(float val) { return (std::signbit)(val); }
68
+ inline int eval_signbit(double val) { return (std::signbit)(val); }
69
+ inline int eval_signbit(long double val) { return (std::signbit)(val); }
70
+ #ifdef BOOST_HAS_FLOAT128
71
+ extern "C" int signbitq(float128_type) throw();
72
+ inline int eval_signbit(float128_type val) { return signbitq(val); }
73
+ #endif
74
+
75
+ template <class T>
76
+ BOOST_MP_CXX14_CONSTEXPR bool eval_is_zero(const T& val);
77
+
78
+ #ifdef BOOST_MSVC
79
+ // warning C4127: conditional expression is constant
80
+ // warning C4146: unary minus operator applied to unsigned type, result still unsigned
81
+ #pragma warning(push)
82
+ #pragma warning(disable : 4127 4146)
83
+ #endif
84
+ //
85
+ // Default versions of mixed arithmetic, these just construct a temporary
86
+ // from the arithmetic value and then do the arithmetic on that, two versions
87
+ // of each depending on whether the backend can be directly constructed from type V.
88
+ //
89
+ // Note that we have to provide *all* the template parameters to class number when used in
90
+ // enable_if as MSVC-10 won't compile the code if we rely on a computed-default parameter.
91
+ // Since the result of the test doesn't depend on whether expression templates are on or off
92
+ // we just use et_on everywhere. We could use a BOOST_WORKAROUND but that just obfuscates the
93
+ // code even more....
94
+ //
95
+ template <class T, class V>
96
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<V, T>::value>::type
97
+ eval_add(T& result, V const& v)
98
+ {
99
+ T t;
100
+ t = v;
101
+ eval_add(result, t);
102
+ }
103
+ template <class T, class V>
104
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, T>::value>::type
105
+ eval_add(T& result, V const& v)
106
+ {
107
+ T t(v);
108
+ eval_add(result, t);
109
+ }
110
+ template <class T, class V>
111
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<V, T>::value>::type
112
+ eval_subtract(T& result, V const& v)
113
+ {
114
+ T t;
115
+ t = v;
116
+ eval_subtract(result, t);
117
+ }
118
+ template <class T, class V>
119
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, T>::value>::type
120
+ eval_subtract(T& result, V const& v)
121
+ {
122
+ T t(v);
123
+ eval_subtract(result, t);
124
+ }
125
+ template <class T, class V>
126
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<V, T>::value>::type
127
+ eval_multiply(T& result, V const& v)
128
+ {
129
+ T t;
130
+ t = v;
131
+ eval_multiply(result, t);
132
+ }
133
+ template <class T, class V>
134
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, T>::value>::type
135
+ eval_multiply(T& result, V const& v)
136
+ {
137
+ T t(v);
138
+ eval_multiply(result, t);
139
+ }
140
+
141
+ template <class T, class U, class V>
142
+ BOOST_MP_CXX14_CONSTEXPR void eval_multiply(T& t, const U& u, const V& v);
143
+
144
+ template <class T, class U, class V>
145
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::value)>::type eval_multiply_add(T& t, const U& u, const V& v)
146
+ {
147
+ T z;
148
+ eval_multiply(z, u, v);
149
+ eval_add(t, z);
150
+ }
151
+ template <class T, class U, class V>
152
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
153
+ {
154
+ eval_multiply_add(t, v, u);
155
+ }
156
+ template <class T, class U, class V>
157
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::value)>::type eval_multiply_subtract(T& t, const U& u, const V& v)
158
+ {
159
+ T z;
160
+ eval_multiply(z, u, v);
161
+ eval_subtract(t, z);
162
+ }
163
+ template <class T, class U, class V>
164
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
165
+ {
166
+ eval_multiply_subtract(t, v, u);
167
+ }
168
+ template <class T, class V>
169
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
170
+ eval_divide(T& result, V const& v)
171
+ {
172
+ T t;
173
+ t = v;
174
+ eval_divide(result, t);
175
+ }
176
+ template <class T, class V>
177
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
178
+ eval_divide(T& result, V const& v)
179
+ {
180
+ T t(v);
181
+ eval_divide(result, t);
182
+ }
183
+ template <class T, class V>
184
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
185
+ eval_modulus(T& result, V const& v)
186
+ {
187
+ T t;
188
+ t = v;
189
+ eval_modulus(result, t);
190
+ }
191
+ template <class T, class V>
192
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
193
+ eval_modulus(T& result, V const& v)
194
+ {
195
+ T t(v);
196
+ eval_modulus(result, t);
197
+ }
198
+ template <class T, class V>
199
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
200
+ eval_bitwise_and(T& result, V const& v)
201
+ {
202
+ T t;
203
+ t = v;
204
+ eval_bitwise_and(result, t);
205
+ }
206
+ template <class T, class V>
207
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
208
+ eval_bitwise_and(T& result, V const& v)
209
+ {
210
+ T t(v);
211
+ eval_bitwise_and(result, t);
212
+ }
213
+ template <class T, class V>
214
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
215
+ eval_bitwise_or(T& result, V const& v)
216
+ {
217
+ T t;
218
+ t = v;
219
+ eval_bitwise_or(result, t);
220
+ }
221
+ template <class T, class V>
222
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
223
+ eval_bitwise_or(T& result, V const& v)
224
+ {
225
+ T t(v);
226
+ eval_bitwise_or(result, t);
227
+ }
228
+ template <class T, class V>
229
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
230
+ eval_bitwise_xor(T& result, V const& v)
231
+ {
232
+ T t;
233
+ t = v;
234
+ eval_bitwise_xor(result, t);
235
+ }
236
+ template <class T, class V>
237
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
238
+ eval_bitwise_xor(T& result, V const& v)
239
+ {
240
+ T t(v);
241
+ eval_bitwise_xor(result, t);
242
+ }
243
+
244
+ template <class T, class V>
245
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
246
+ eval_complement(T& result, V const& v)
247
+ {
248
+ T t;
249
+ t = v;
250
+ eval_complement(result, t);
251
+ }
252
+ template <class T, class V>
253
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
254
+ eval_complement(T& result, V const& v)
255
+ {
256
+ T t(v);
257
+ eval_complement(result, t);
258
+ }
259
+
260
+ //
261
+ // Default versions of 3-arg arithmetic functions, these mostly just forward to the 2 arg versions:
262
+ //
263
+ template <class T, class U, class V>
264
+ BOOST_MP_CXX14_CONSTEXPR void eval_add(T& t, const U& u, const V& v);
265
+
266
+ template <class T>
267
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_add_default(T& t, const T& u, const T& v)
268
+ {
269
+ if (&t == &v)
270
+ {
271
+ eval_add(t, u);
272
+ }
273
+ else if (&t == &u)
274
+ {
275
+ eval_add(t, v);
276
+ }
277
+ else
278
+ {
279
+ t = u;
280
+ eval_add(t, v);
281
+ }
282
+ }
283
+ template <class T, class U>
284
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
285
+ {
286
+ T vv;
287
+ vv = v;
288
+ eval_add(t, u, vv);
289
+ }
290
+ template <class T, class U>
291
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
292
+ {
293
+ T vv(v);
294
+ eval_add(t, u, vv);
295
+ }
296
+ template <class T, class U>
297
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_add_default(T& t, const U& u, const T& v)
298
+ {
299
+ eval_add(t, v, u);
300
+ }
301
+ template <class T, class U, class V>
302
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_add_default(T& t, const U& u, const V& v)
303
+ {
304
+ BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
305
+ {
306
+ if ((void*)&t == (void*)&v)
307
+ {
308
+ eval_add(t, u);
309
+ }
310
+ else
311
+ {
312
+ t = u;
313
+ eval_add(t, v);
314
+ }
315
+ }
316
+ else
317
+ {
318
+ t = u;
319
+ eval_add(t, v);
320
+ }
321
+ }
322
+ template <class T, class U, class V>
323
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_add(T& t, const U& u, const V& v)
324
+ {
325
+ eval_add_default(t, u, v);
326
+ }
327
+
328
+ template <class T, class U, class V>
329
+ void BOOST_MP_CXX14_CONSTEXPR eval_subtract(T& t, const U& u, const V& v);
330
+
331
+ template <class T>
332
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract_default(T& t, const T& u, const T& v)
333
+ {
334
+ if ((&t == &v) && is_signed_number<T>::value)
335
+ {
336
+ eval_subtract(t, u);
337
+ t.negate();
338
+ }
339
+ else if (&t == &u)
340
+ {
341
+ eval_subtract(t, v);
342
+ }
343
+ else
344
+ {
345
+ t = u;
346
+ eval_subtract(t, v);
347
+ }
348
+ }
349
+ template <class T, class U>
350
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
351
+ {
352
+ T vv;
353
+ vv = v;
354
+ eval_subtract(t, u, vv);
355
+ }
356
+ template <class T, class U>
357
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
358
+ {
359
+ T vv(v);
360
+ eval_subtract(t, u, vv);
361
+ }
362
+ template <class T, class U>
363
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && is_signed_number<T>::value && (number_category<T>::value != number_kind_complex)>::type eval_subtract_default(T& t, const U& u, const T& v)
364
+ {
365
+ eval_subtract(t, v, u);
366
+ if(!eval_is_zero(t) || (eval_signbit(u) != eval_signbit(v)))
367
+ t.negate();
368
+ }
369
+ template <class T, class U>
370
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && is_signed_number<T>::value && (number_category<T>::value == number_kind_complex)>::type eval_subtract_default(T& t, const U& u, const T& v)
371
+ {
372
+ eval_subtract(t, v, u);
373
+ t.negate();
374
+ }
375
+ template <class T, class U>
376
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
377
+ {
378
+ T temp;
379
+ temp = u;
380
+ eval_subtract(t, temp, v);
381
+ }
382
+ template <class T, class U>
383
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
384
+ {
385
+ T temp(u);
386
+ eval_subtract(t, temp, v);
387
+ }
388
+ template <class T, class U, class V>
389
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract_default(T& t, const U& u, const V& v)
390
+ {
391
+ BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
392
+ {
393
+ if ((void*)&t == (void*)&v)
394
+ {
395
+ eval_subtract(t, u);
396
+ t.negate();
397
+ }
398
+ else
399
+ {
400
+ t = u;
401
+ eval_subtract(t, v);
402
+ }
403
+ }
404
+ else
405
+ {
406
+ t = u;
407
+ eval_subtract(t, v);
408
+ }
409
+ }
410
+ template <class T, class U, class V>
411
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(T& t, const U& u, const V& v)
412
+ {
413
+ eval_subtract_default(t, u, v);
414
+ }
415
+
416
+ template <class T>
417
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_default(T& t, const T& u, const T& v)
418
+ {
419
+ if (&t == &v)
420
+ {
421
+ eval_multiply(t, u);
422
+ }
423
+ else if (&t == &u)
424
+ {
425
+ eval_multiply(t, v);
426
+ }
427
+ else
428
+ {
429
+ t = u;
430
+ eval_multiply(t, v);
431
+ }
432
+ }
433
+ #if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
434
+ template <class T, class U>
435
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
436
+ {
437
+ T vv;
438
+ vv = v;
439
+ eval_multiply(t, u, vv);
440
+ }
441
+ template <class T, class U>
442
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
443
+ {
444
+ T vv(v);
445
+ eval_multiply(t, u, vv);
446
+ }
447
+ template <class T, class U>
448
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_multiply_default(T& t, const U& u, const T& v)
449
+ {
450
+ eval_multiply(t, v, u);
451
+ }
452
+ #endif
453
+ template <class T, class U, class V>
454
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_default(T& t, const U& u, const V& v)
455
+ {
456
+ BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
457
+ {
458
+ if ((void*)&t == (void*)&v)
459
+ {
460
+ eval_multiply(t, u);
461
+ }
462
+ else
463
+ {
464
+ t = number<T>::canonical_value(u);
465
+ eval_multiply(t, v);
466
+ }
467
+ }
468
+ else
469
+ {
470
+ t = number<T>::canonical_value(u);
471
+ eval_multiply(t, v);
472
+ }
473
+ }
474
+ template <class T, class U, class V>
475
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(T& t, const U& u, const V& v)
476
+ {
477
+ eval_multiply_default(t, u, v);
478
+ }
479
+
480
+ template <class T>
481
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_add(T& t, const T& u, const T& v, const T& x)
482
+ {
483
+ if ((void*)&x == (void*)&t)
484
+ {
485
+ T z;
486
+ z = number<T>::canonical_value(x);
487
+ eval_multiply_add(t, u, v, z);
488
+ }
489
+ else
490
+ {
491
+ eval_multiply(t, u, v);
492
+ eval_add(t, x);
493
+ }
494
+ }
495
+
496
+ template <class T, class U>
497
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_same<T, U>::value, T>::type make_T(const U& u)
498
+ {
499
+ T t;
500
+ t = number<T>::canonical_value(u);
501
+ return t;
502
+ }
503
+ template <class T>
504
+ inline BOOST_MP_CXX14_CONSTEXPR const T& make_T(const T& t)
505
+ {
506
+ return t;
507
+ }
508
+
509
+ template <class T, class U, class V, class X>
510
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::value)>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
511
+ {
512
+ eval_multiply_add(t, make_T<T>(u), make_T<T>(v), make_T<T>(x));
513
+ }
514
+ template <class T, class U, class V, class X>
515
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
516
+ {
517
+ eval_multiply_add(t, v, u, x);
518
+ }
519
+ template <class T, class U, class V, class X>
520
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::value)>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
521
+ {
522
+ if ((void*)&x == (void*)&t)
523
+ {
524
+ T z;
525
+ z = x;
526
+ eval_multiply_subtract(t, u, v, z);
527
+ }
528
+ else
529
+ {
530
+ eval_multiply(t, u, v);
531
+ eval_subtract(t, x);
532
+ }
533
+ }
534
+ template <class T, class U, class V, class X>
535
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
536
+ {
537
+ eval_multiply_subtract(t, v, u, x);
538
+ }
539
+
540
+ template <class T, class U, class V>
541
+ BOOST_MP_CXX14_CONSTEXPR void eval_divide(T& t, const U& u, const V& v);
542
+
543
+ template <class T>
544
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_divide_default(T& t, const T& u, const T& v)
545
+ {
546
+ if (&t == &u)
547
+ eval_divide(t, v);
548
+ else if (&t == &v)
549
+ {
550
+ T temp;
551
+ eval_divide(temp, u, v);
552
+ temp.swap(t);
553
+ }
554
+ else
555
+ {
556
+ t = u;
557
+ eval_divide(t, v);
558
+ }
559
+ }
560
+ #if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
561
+ template <class T, class U>
562
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
563
+ {
564
+ T vv;
565
+ vv = v;
566
+ eval_divide(t, u, vv);
567
+ }
568
+ template <class T, class U>
569
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
570
+ {
571
+ T vv(v);
572
+ eval_divide(t, u, vv);
573
+ }
574
+ template <class T, class U>
575
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
576
+ {
577
+ T uu;
578
+ uu = u;
579
+ eval_divide(t, uu, v);
580
+ }
581
+ template <class T, class U>
582
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
583
+ {
584
+ T uu(u);
585
+ eval_divide(t, uu, v);
586
+ }
587
+ #endif
588
+ template <class T, class U, class V>
589
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_divide_default(T& t, const U& u, const V& v)
590
+ {
591
+ BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
592
+ {
593
+ if ((void*)&t == (void*)&v)
594
+ {
595
+ T temp;
596
+ temp = u;
597
+ eval_divide(temp, v);
598
+ t = temp;
599
+ }
600
+ else
601
+ {
602
+ t = u;
603
+ eval_divide(t, v);
604
+ }
605
+ }
606
+ else
607
+ {
608
+ t = u;
609
+ eval_divide(t, v);
610
+ }
611
+ }
612
+ template <class T, class U, class V>
613
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(T& t, const U& u, const V& v)
614
+ {
615
+ eval_divide_default(t, u, v);
616
+ }
617
+
618
+ template <class T, class U, class V>
619
+ BOOST_MP_CXX14_CONSTEXPR void eval_modulus(T& t, const U& u, const V& v);
620
+
621
+ template <class T>
622
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus_default(T& t, const T& u, const T& v)
623
+ {
624
+ if (&t == &u)
625
+ eval_modulus(t, v);
626
+ else if (&t == &v)
627
+ {
628
+ T temp;
629
+ eval_modulus(temp, u, v);
630
+ temp.swap(t);
631
+ }
632
+ else
633
+ {
634
+ t = u;
635
+ eval_modulus(t, v);
636
+ }
637
+ }
638
+ template <class T, class U>
639
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
640
+ {
641
+ T vv;
642
+ vv = v;
643
+ eval_modulus(t, u, vv);
644
+ }
645
+ template <class T, class U>
646
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
647
+ {
648
+ T vv(v);
649
+ eval_modulus(t, u, vv);
650
+ }
651
+ template <class T, class U>
652
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
653
+ {
654
+ T uu;
655
+ uu = u;
656
+ eval_modulus(t, uu, v);
657
+ }
658
+ template <class T, class U>
659
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
660
+ {
661
+ T uu(u);
662
+ eval_modulus(t, uu, v);
663
+ }
664
+ template <class T, class U, class V>
665
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus_default(T& t, const U& u, const V& v)
666
+ {
667
+ BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
668
+ {
669
+ if ((void*)&t == (void*)&v)
670
+ {
671
+ T temp(u);
672
+ eval_modulus(temp, v);
673
+ t = temp;
674
+ }
675
+ else
676
+ {
677
+ t = u;
678
+ eval_modulus(t, v);
679
+ }
680
+ }
681
+ else
682
+ {
683
+ t = u;
684
+ eval_modulus(t, v);
685
+ }
686
+ }
687
+ template <class T, class U, class V>
688
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus(T& t, const U& u, const V& v)
689
+ {
690
+ eval_modulus_default(t, u, v);
691
+ }
692
+
693
+ template <class T, class U, class V>
694
+ BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and(T& t, const U& u, const V& v);
695
+
696
+ template <class T>
697
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and_default(T& t, const T& u, const T& v)
698
+ {
699
+ if (&t == &v)
700
+ {
701
+ eval_bitwise_and(t, u);
702
+ }
703
+ else if (&t == &u)
704
+ {
705
+ eval_bitwise_and(t, v);
706
+ }
707
+ else
708
+ {
709
+ t = u;
710
+ eval_bitwise_and(t, v);
711
+ }
712
+ }
713
+ template <class T, class U>
714
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
715
+ {
716
+ T vv;
717
+ vv = v;
718
+ eval_bitwise_and(t, u, vv);
719
+ }
720
+ template <class T, class U>
721
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
722
+ {
723
+ T vv(v);
724
+ eval_bitwise_and(t, u, vv);
725
+ }
726
+ template <class T, class U>
727
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_and_default(T& t, const U& u, const T& v)
728
+ {
729
+ eval_bitwise_and(t, v, u);
730
+ }
731
+ template <class T, class U, class V>
732
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value || std::is_same<T, V>::value>::type eval_bitwise_and_default(T& t, const U& u, const V& v)
733
+ {
734
+ t = u;
735
+ eval_bitwise_and(t, v);
736
+ }
737
+ template <class T, class U, class V>
738
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and(T& t, const U& u, const V& v)
739
+ {
740
+ eval_bitwise_and_default(t, u, v);
741
+ }
742
+
743
+ template <class T, class U, class V>
744
+ BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or(T& t, const U& u, const V& v);
745
+
746
+ template <class T>
747
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or_default(T& t, const T& u, const T& v)
748
+ {
749
+ if (&t == &v)
750
+ {
751
+ eval_bitwise_or(t, u);
752
+ }
753
+ else if (&t == &u)
754
+ {
755
+ eval_bitwise_or(t, v);
756
+ }
757
+ else
758
+ {
759
+ t = u;
760
+ eval_bitwise_or(t, v);
761
+ }
762
+ }
763
+ template <class T, class U>
764
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
765
+ {
766
+ T vv;
767
+ vv = v;
768
+ eval_bitwise_or(t, u, vv);
769
+ }
770
+ template <class T, class U>
771
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
772
+ {
773
+ T vv(v);
774
+ eval_bitwise_or(t, u, vv);
775
+ }
776
+ template <class T, class U>
777
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_or_default(T& t, const U& u, const T& v)
778
+ {
779
+ eval_bitwise_or(t, v, u);
780
+ }
781
+ template <class T, class U, class V>
782
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or_default(T& t, const U& u, const V& v)
783
+ {
784
+ BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
785
+ {
786
+ if ((void*)&t == (void*)&v)
787
+ {
788
+ eval_bitwise_or(t, u);
789
+ }
790
+ else
791
+ {
792
+ t = u;
793
+ eval_bitwise_or(t, v);
794
+ }
795
+ }
796
+ else
797
+ {
798
+ t = u;
799
+ eval_bitwise_or(t, v);
800
+ }
801
+ }
802
+ template <class T, class U, class V>
803
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or(T& t, const U& u, const V& v)
804
+ {
805
+ eval_bitwise_or_default(t, u, v);
806
+ }
807
+
808
+ template <class T, class U, class V>
809
+ BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor(T& t, const U& u, const V& v);
810
+
811
+ template <class T>
812
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor_default(T& t, const T& u, const T& v)
813
+ {
814
+ if (&t == &v)
815
+ {
816
+ eval_bitwise_xor(t, u);
817
+ }
818
+ else if (&t == &u)
819
+ {
820
+ eval_bitwise_xor(t, v);
821
+ }
822
+ else
823
+ {
824
+ t = u;
825
+ eval_bitwise_xor(t, v);
826
+ }
827
+ }
828
+ template <class T, class U>
829
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
830
+ {
831
+ T vv;
832
+ vv = v;
833
+ eval_bitwise_xor(t, u, vv);
834
+ }
835
+ template <class T, class U>
836
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
837
+ {
838
+ T vv(v);
839
+ eval_bitwise_xor(t, u, vv);
840
+ }
841
+ template <class T, class U>
842
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_xor_default(T& t, const U& u, const T& v)
843
+ {
844
+ eval_bitwise_xor(t, v, u);
845
+ }
846
+ template <class T, class U, class V>
847
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor_default(T& t, const U& u, const V& v)
848
+ {
849
+ BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
850
+ {
851
+ if ((void*)&t == (void*)&v)
852
+ {
853
+ eval_bitwise_xor(t, u);
854
+ }
855
+ else
856
+ {
857
+ t = u;
858
+ eval_bitwise_xor(t, v);
859
+ }
860
+ }
861
+ else
862
+ {
863
+ t = u;
864
+ eval_bitwise_xor(t, v);
865
+ }
866
+ }
867
+ template <class T, class U, class V>
868
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor(T& t, const U& u, const V& v)
869
+ {
870
+ eval_bitwise_xor_default(t, u, v);
871
+ }
872
+
873
+ template <class T>
874
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_increment(T& val)
875
+ {
876
+ using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
877
+ eval_add(val, static_cast<ui_type>(1u));
878
+ }
879
+ template <class T>
880
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_decrement(T& val)
881
+ {
882
+ using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
883
+ eval_subtract(val, static_cast<ui_type>(1u));
884
+ }
885
+
886
+ template <class T, class U, class V>
887
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_left_shift(T& result, const U& arg, const V val)
888
+ {
889
+ result = arg;
890
+ eval_left_shift(result, val);
891
+ }
892
+
893
+ template <class T, class U, class V>
894
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_right_shift(T& result, const U& arg, const V val)
895
+ {
896
+ result = arg;
897
+ eval_right_shift(result, val);
898
+ }
899
+
900
+ template <class T>
901
+ inline BOOST_MP_CXX14_CONSTEXPR bool eval_is_zero(const T& val)
902
+ {
903
+ using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
904
+ return val.compare(static_cast<ui_type>(0)) == 0;
905
+ }
906
+ template <class T>
907
+ inline BOOST_MP_CXX14_CONSTEXPR int eval_get_sign(const T& val)
908
+ {
909
+ using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
910
+ return val.compare(static_cast<ui_type>(0));
911
+ }
912
+
913
+ template <class T, class V, class U>
914
+ inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::false_type&, const std::false_type&)
915
+ {
916
+ using component_number_type = typename component_type<number<T> >::type;
917
+
918
+ boost::multiprecision::detail::scoped_precision_options<component_number_type> sp(result);
919
+ (void)sp;
920
+
921
+ component_number_type x(v1), y(v2);
922
+ assign_components(result, x.backend(), y.backend());
923
+ }
924
+ template <class T, class V, class U>
925
+ inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::true_type&, const std::false_type&)
926
+ {
927
+ boost::multiprecision::detail::scoped_source_precision<number<V>> scope;
928
+ (void)scope;
929
+ assign_components_imp2(result, number<V>(v1), v2, std::false_type(), std::false_type());
930
+ }
931
+ template <class T, class V, class U>
932
+ inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::true_type&, const std::true_type&)
933
+ {
934
+ boost::multiprecision::detail::scoped_source_precision<number<V>> scope1;
935
+ boost::multiprecision::detail::scoped_source_precision<number<U>> scope2;
936
+ (void)scope1;
937
+ (void)scope2;
938
+ assign_components_imp2(result, number<V>(v1), number<U>(v2), std::false_type(), std::false_type());
939
+ }
940
+ template <class T, class V, class U>
941
+ inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::false_type&, const std::true_type&)
942
+ {
943
+ boost::multiprecision::detail::scoped_source_precision<number<U>> scope;
944
+ (void)scope;
945
+ assign_components_imp2(result, v1, number<U>(v2), std::false_type(), std::false_type());
946
+ }
947
+
948
+
949
+ template <class T, class V, class U>
950
+ inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp(T& result, const V& v1, const U& v2, const std::integral_constant<int, number_kind_rational>&)
951
+ {
952
+ result = v1;
953
+ T t;
954
+ t = v2;
955
+ eval_divide(result, t);
956
+ }
957
+
958
+ template <class T, class V, class U, int N>
959
+ inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp(T& result, const V& v1, const U& v2, const std::integral_constant<int, N>&)
960
+ {
961
+ assign_components_imp2(result, v1, v2, boost::multiprecision::detail::is_backend<V>(), boost::multiprecision::detail::is_backend<U>());
962
+ }
963
+
964
+ template <class T, class V, class U>
965
+ inline BOOST_MP_CXX14_CONSTEXPR void assign_components(T& result, const V& v1, const U& v2)
966
+ {
967
+ return assign_components_imp(result, v1, v2, typename number_category<T>::type());
968
+ }
969
+ #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
970
+ template <class Result, class Traits>
971
+ inline void assign_from_string_view(Result& result, const std::basic_string_view<char, Traits>& view)
972
+ {
973
+ // since most (all?) backends require a const char* to construct from, we just
974
+ // convert to that:
975
+ std::string s(view);
976
+ result = s.c_str();
977
+ }
978
+ template <class Result, class Traits>
979
+ inline void assign_from_string_view(Result& result, const std::basic_string_view<char, Traits>& view_x, const std::basic_string_view<char, Traits>& view_y)
980
+ {
981
+ // since most (all?) backends require a const char* to construct from, we just
982
+ // convert to that:
983
+ std::string x(view_x), y(view_y);
984
+ assign_components(result, x.c_str(), y.c_str());
985
+ }
986
+ #endif
987
+ template <class R, int b>
988
+ struct has_enough_bits
989
+ {
990
+ template <class T>
991
+ struct type : public std::integral_constant<bool, !std::is_same<R, T>::value && (std::numeric_limits<T>::digits >= b)>
992
+ {};
993
+ };
994
+
995
+ template <class R>
996
+ struct terminal
997
+ {
998
+ BOOST_MP_CXX14_CONSTEXPR terminal(const R& v) : value(v) {}
999
+ BOOST_MP_CXX14_CONSTEXPR terminal() {}
1000
+ BOOST_MP_CXX14_CONSTEXPR terminal& operator=(R val)
1001
+ {
1002
+ value = val;
1003
+ return *this;
1004
+ }
1005
+ R value;
1006
+ BOOST_MP_CXX14_CONSTEXPR operator R() const { return value; }
1007
+ };
1008
+
1009
+ template <class Tuple, int i, class T, bool = (i == std::tuple_size<Tuple>::value)>
1010
+ struct find_index_of_type
1011
+ {
1012
+ static constexpr int value =
1013
+ std::is_same<T, typename std::tuple_element<static_cast<std::size_t>(i), Tuple>::type>::value
1014
+ ? i
1015
+ : find_index_of_type<Tuple, i + 1, T>::value;
1016
+ };
1017
+ template <class Tuple, int i, class T>
1018
+ struct find_index_of_type<Tuple, i, T, true>
1019
+ {
1020
+ static constexpr int value = -1;
1021
+ };
1022
+
1023
+
1024
+ template <class R, class B>
1025
+ struct calculate_next_larger_type
1026
+ {
1027
+ // Find which list we're looking through:
1028
+ using list_type = typename std::conditional<
1029
+ boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value,
1030
+ typename B::signed_types,
1031
+ typename std::conditional<
1032
+ boost::multiprecision::detail::is_unsigned<R>::value,
1033
+ typename B::unsigned_types,
1034
+ typename B::float_types>::type>::type;
1035
+ static constexpr int start = find_index_of_type<list_type, 0, R>::value;
1036
+ static constexpr int index_of_type = boost::multiprecision::detail::find_index_of_large_enough_type<list_type, start == INT_MAX ? 0 : start + 1, boost::multiprecision::detail::bits_of<R>::value> ::value;
1037
+ using type = typename boost::multiprecision::detail::dereference_tuple<index_of_type, list_type, terminal<R> >::type;
1038
+ };
1039
+
1040
+ template <class R, class T>
1041
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<R>::value, bool>::type check_in_range(const T& t)
1042
+ {
1043
+ // Can t fit in an R?
1044
+ if ((t > 0) && std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (t > (std::numeric_limits<R>::max)()))
1045
+ return true;
1046
+ else
1047
+ return false;
1048
+ }
1049
+
1050
+ template <class R, class B>
1051
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<R>::value>::type eval_convert_to(R* result, const B& backend)
1052
+ {
1053
+ using next_type = typename calculate_next_larger_type<R, B>::type;
1054
+ next_type n = next_type();
1055
+ eval_convert_to(&n, backend);
1056
+ BOOST_IF_CONSTEXPR(!boost::multiprecision::detail::is_unsigned<R>::value && std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded)
1057
+ {
1058
+ if(n > static_cast<next_type>((std::numeric_limits<R>::max)()))
1059
+ {
1060
+ *result = (std::numeric_limits<R>::max)();
1061
+ return;
1062
+ }
1063
+ }
1064
+ BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized&& std::numeric_limits<R>::is_bounded)
1065
+ {
1066
+ if (n < static_cast<next_type>((std::numeric_limits<R>::min)()))
1067
+ {
1068
+ *result = (std::numeric_limits<R>::min)();
1069
+ return;
1070
+ }
1071
+ }
1072
+ *result = static_cast<R>(n);
1073
+ }
1074
+
1075
+ template <class R, class B>
1076
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !boost::multiprecision::detail::is_integral<R>::value && !std::is_enum<R>::value>::type eval_convert_to(R* result, const B& backend)
1077
+ {
1078
+ using next_type = typename calculate_next_larger_type<R, B>::type;
1079
+ next_type n = next_type();
1080
+ eval_convert_to(&n, backend);
1081
+ BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded)
1082
+ {
1083
+ if ((n > (next_type)(std::numeric_limits<R>::max)() || (n < (next_type) - (std::numeric_limits<R>::max)())))
1084
+ {
1085
+ *result = n > 0 ? (std::numeric_limits<R>::max)() : -(std::numeric_limits<R>::max)();
1086
+ }
1087
+ else
1088
+ *result = static_cast<R>(n);
1089
+ }
1090
+ else
1091
+ *result = static_cast<R>(n);
1092
+ }
1093
+
1094
+ template <class R, class B>
1095
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_enum<R>::value>::type eval_convert_to(R* result, const B& backend)
1096
+ {
1097
+ typename std::underlying_type<R>::type t{};
1098
+ eval_convert_to(&t, backend);
1099
+ *result = static_cast<R>(t);
1100
+ }
1101
+
1102
+ #ifndef BOOST_MP_STANDALONE
1103
+ template <class R, class B>
1104
+ inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const std::integral_constant<bool, false>&)
1105
+ {
1106
+ //
1107
+ // We ran out of types to try for the conversion, try
1108
+ // a lexical_cast and hope for the best:
1109
+ //
1110
+ BOOST_IF_CONSTEXPR (std::numeric_limits<R>::is_integer && !std::numeric_limits<R>::is_signed)
1111
+ if (eval_get_sign(backend) < 0)
1112
+ BOOST_MP_THROW_EXCEPTION(std::range_error("Attempt to convert negative value to an unsigned integer results in undefined behaviour"));
1113
+ BOOST_MP_TRY {
1114
+ result->value = boost::lexical_cast<R>(backend.str(0, std::ios_base::fmtflags(0)));
1115
+ }
1116
+ BOOST_MP_CATCH (const bad_lexical_cast&)
1117
+ {
1118
+ if (eval_get_sign(backend) < 0)
1119
+ {
1120
+ BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_integer && !std::numeric_limits<R>::is_signed)
1121
+ *result = (std::numeric_limits<R>::max)(); // we should never get here, exception above will be raised.
1122
+ else BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_integer)
1123
+ *result = (std::numeric_limits<R>::min)();
1124
+ else
1125
+ *result = -(std::numeric_limits<R>::max)();
1126
+ }
1127
+ else
1128
+ *result = (std::numeric_limits<R>::max)();
1129
+ }
1130
+ BOOST_MP_CATCH_END
1131
+ }
1132
+
1133
+ template <class R, class B>
1134
+ inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const std::integral_constant<bool, true>&)
1135
+ {
1136
+ //
1137
+ // Last chance conversion to an unsigned integer.
1138
+ // We ran out of types to try for the conversion, try
1139
+ // a lexical_cast and hope for the best:
1140
+ //
1141
+ if (eval_get_sign(backend) < 0)
1142
+ BOOST_MP_THROW_EXCEPTION(std::range_error("Attempt to convert negative value to an unsigned integer results in undefined behaviour"));
1143
+ BOOST_MP_TRY {
1144
+ B t(backend);
1145
+ R mask = ~static_cast<R>(0u);
1146
+ eval_bitwise_and(t, mask);
1147
+ result->value = boost::lexical_cast<R>(t.str(0, std::ios_base::fmtflags(0)));
1148
+ }
1149
+ BOOST_MP_CATCH (const bad_lexical_cast&)
1150
+ {
1151
+ // We should never really get here...
1152
+ *result = (std::numeric_limits<R>::max)();
1153
+ }
1154
+ BOOST_MP_CATCH_END
1155
+ }
1156
+ #else // Using standalone mode
1157
+
1158
+ template <class R, class B>
1159
+ inline void last_chance_eval_convert_to(terminal<R>*, const B&, const std::integral_constant<bool, false>&)
1160
+ {
1161
+ static_assert(sizeof(R) == 1, "This type can not be used in standalone mode. Please de-activate and file a bug at https://github.com/boostorg/multiprecision/");
1162
+ }
1163
+
1164
+ template <class R, class B>
1165
+ inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const std::integral_constant<bool, true>&)
1166
+ {
1167
+ static_cast<void>(result);
1168
+ static_cast<void>(backend);
1169
+
1170
+ static_assert(sizeof(R) == 1, "This type can not be used in standalone mode. Please de-activate and file a bug at https://github.com/boostorg/multiprecision/");
1171
+ }
1172
+ #endif
1173
+
1174
+ template <class R, class B>
1175
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(terminal<R>* result, const B& backend)
1176
+ {
1177
+ using tag_type = std::integral_constant<bool, boost::multiprecision::detail::is_unsigned<R>::value && number_category<B>::value == number_kind_integer>;
1178
+ last_chance_eval_convert_to(result, backend, tag_type());
1179
+ }
1180
+
1181
+ template <class B1, class B2, expression_template_option et>
1182
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(terminal<number<B1, et> >* result, const B2& backend)
1183
+ {
1184
+ //
1185
+ // We ran out of types to try for the conversion, try
1186
+ // a generic conversion and hope for the best:
1187
+ //
1188
+ boost::multiprecision::detail::generic_interconvert(result->value.backend(), backend, number_category<B1>(), number_category<B2>());
1189
+ }
1190
+
1191
+ template <class B>
1192
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::string* result, const B& backend)
1193
+ {
1194
+ *result = backend.str(0, std::ios_base::fmtflags(0));
1195
+ }
1196
+
1197
+ template <class B>
1198
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<float>* result, const B& backend)
1199
+ {
1200
+ using scalar_type = typename scalar_result_from_possible_complex<multiprecision::number<B> >::type;
1201
+ scalar_type re, im;
1202
+ eval_real(re.backend(), backend);
1203
+ eval_imag(im.backend(), backend);
1204
+
1205
+ *result = std::complex<float>(re.template convert_to<float>(), im.template convert_to<float>());
1206
+ }
1207
+
1208
+ template <class B>
1209
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<double>* result, const B& backend)
1210
+ {
1211
+ using scalar_type = typename scalar_result_from_possible_complex<multiprecision::number<B> >::type;
1212
+ scalar_type re, im;
1213
+ eval_real(re.backend(), backend);
1214
+ eval_imag(im.backend(), backend);
1215
+
1216
+ *result = std::complex<double>(re.template convert_to<double>(), im.template convert_to<double>());
1217
+ }
1218
+
1219
+ template <class B>
1220
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<long double>* result, const B& backend)
1221
+ {
1222
+ using scalar_type = typename scalar_result_from_possible_complex<multiprecision::number<B> >::type;
1223
+ scalar_type re, im;
1224
+ eval_real(re.backend(), backend);
1225
+ eval_imag(im.backend(), backend);
1226
+
1227
+ *result = std::complex<long double>(re.template convert_to<long double>(), im.template convert_to<long double>());
1228
+ }
1229
+
1230
+ //
1231
+ // Functions:
1232
+ //
1233
+ template <class T, class U>
1234
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_abs(T& result, const U& arg)
1235
+ {
1236
+ using type_list = typename U::signed_types ;
1237
+ using front = typename std::tuple_element<0, type_list>::type;
1238
+ result = arg;
1239
+ if (arg.compare(front(0)) < 0)
1240
+ result.negate();
1241
+ }
1242
+ template <class T, class U>
1243
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_fabs(T& result, const U& arg)
1244
+ {
1245
+ static_assert(number_category<T>::value == number_kind_floating_point, "The fabs function is only valid for floating point types.");
1246
+ using type_list = typename U::signed_types ;
1247
+ using front = typename std::tuple_element<0, type_list>::type;
1248
+ result = arg;
1249
+ if (arg.compare(front(0)) < 0)
1250
+ result.negate();
1251
+ }
1252
+
1253
+ template <class Backend>
1254
+ inline BOOST_MP_CXX14_CONSTEXPR int eval_fpclassify(const Backend& arg)
1255
+ {
1256
+ static_assert(number_category<Backend>::value == number_kind_floating_point, "The fpclassify function is only valid for floating point types.");
1257
+ return eval_is_zero(arg) ? FP_ZERO : FP_NORMAL;
1258
+ }
1259
+
1260
+ template <class T>
1261
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_fmod(T& result, const T& a, const T& b)
1262
+ {
1263
+ static_assert(number_category<T>::value == number_kind_floating_point, "The fmod function is only valid for floating point types.");
1264
+ if ((&result == &a) || (&result == &b))
1265
+ {
1266
+ T temp;
1267
+ eval_fmod(temp, a, b);
1268
+ result = temp;
1269
+ return;
1270
+ }
1271
+ switch (eval_fpclassify(a))
1272
+ {
1273
+ case FP_ZERO:
1274
+ result = a;
1275
+ return;
1276
+ case FP_INFINITE:
1277
+ case FP_NAN:
1278
+ result = std::numeric_limits<number<T> >::quiet_NaN().backend();
1279
+ errno = EDOM;
1280
+ return;
1281
+ }
1282
+ switch (eval_fpclassify(b))
1283
+ {
1284
+ case FP_ZERO:
1285
+ case FP_NAN:
1286
+ result = std::numeric_limits<number<T> >::quiet_NaN().backend();
1287
+ errno = EDOM;
1288
+ return;
1289
+ }
1290
+ T n;
1291
+ eval_divide(result, a, b);
1292
+ if (eval_get_sign(result) < 0)
1293
+ eval_ceil(n, result);
1294
+ else
1295
+ eval_floor(n, result);
1296
+ eval_multiply(n, b);
1297
+ eval_subtract(result, a, n);
1298
+ if (eval_get_sign(result) != 0)
1299
+ {
1300
+ //
1301
+ // Sanity check, that due to rounding errors in division,
1302
+ // we haven't accidently calculated the wrong value:
1303
+ // See https://github.com/boostorg/multiprecision/issues/604 for an example.
1304
+ //
1305
+ if (eval_get_sign(result) == eval_get_sign(b))
1306
+ {
1307
+ if (result.compare(b) >= 0)
1308
+ {
1309
+ eval_subtract(result, b);
1310
+ }
1311
+ }
1312
+ else
1313
+ {
1314
+ n = b;
1315
+ n.negate();
1316
+ if (result.compare(n) >= 0)
1317
+ {
1318
+ eval_subtract(result, n);
1319
+ }
1320
+ }
1321
+ }
1322
+ }
1323
+ template <class T, class A>
1324
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_fmod(T& result, const T& x, const A& a)
1325
+ {
1326
+ using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
1327
+ using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
1328
+ cast_type c;
1329
+ c = a;
1330
+ eval_fmod(result, x, c);
1331
+ }
1332
+
1333
+ template <class T, class A>
1334
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_fmod(T& result, const A& x, const T& a)
1335
+ {
1336
+ using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
1337
+ using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
1338
+ cast_type c;
1339
+ c = x;
1340
+ eval_fmod(result, c, a);
1341
+ }
1342
+
1343
+ template <class T>
1344
+ BOOST_MP_CXX14_CONSTEXPR void eval_round(T& result, const T& a);
1345
+
1346
+ template <class T>
1347
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_remquo(T& result, const T& a, const T& b, int* pi)
1348
+ {
1349
+ static_assert(number_category<T>::value == number_kind_floating_point, "The remquo function is only valid for floating point types.");
1350
+ if ((&result == &a) || (&result == &b))
1351
+ {
1352
+ T temp;
1353
+ eval_remquo(temp, a, b, pi);
1354
+ result = temp;
1355
+ return;
1356
+ }
1357
+ T n;
1358
+ eval_divide(result, a, b);
1359
+ eval_round(n, result);
1360
+ eval_convert_to(pi, n);
1361
+ eval_multiply(n, b);
1362
+ eval_subtract(result, a, n);
1363
+ if (eval_is_zero(result))
1364
+ {
1365
+ if (eval_signbit(a))
1366
+ result.negate();
1367
+ }
1368
+ }
1369
+ template <class T, class A>
1370
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_remquo(T& result, const T& x, const A& a, int* pi)
1371
+ {
1372
+ using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
1373
+ using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
1374
+ cast_type c = cast_type();
1375
+ c = a;
1376
+ eval_remquo(result, x, c, pi);
1377
+ }
1378
+ template <class T, class A>
1379
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_remquo(T& result, const A& x, const T& a, int* pi)
1380
+ {
1381
+ using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
1382
+ using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
1383
+ cast_type c = cast_type();
1384
+ c = x;
1385
+ eval_remquo(result, c, a, pi);
1386
+ }
1387
+ template <class T, class U, class V>
1388
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_remainder(T& result, const U& a, const V& b)
1389
+ {
1390
+ int i(0);
1391
+ eval_remquo(result, a, b, &i);
1392
+ }
1393
+
1394
+ template <class B>
1395
+ BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const B& a, const B& b);
1396
+ template <class T, class U>
1397
+ BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const T& a, const U& b);
1398
+ template <class B>
1399
+ BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const B& a, const B& b);
1400
+ template <class T, class U>
1401
+ BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const T& a, const U& b);
1402
+
1403
+ template <class T>
1404
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_fdim(T& result, const T& a, const T& b)
1405
+ {
1406
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1407
+ const ui_type zero = 0u;
1408
+ switch (eval_fpclassify(b))
1409
+ {
1410
+ case FP_NAN:
1411
+ case FP_INFINITE:
1412
+ result = zero;
1413
+ return;
1414
+ }
1415
+ switch (eval_fpclassify(a))
1416
+ {
1417
+ case FP_NAN:
1418
+ result = zero;
1419
+ return;
1420
+ case FP_INFINITE:
1421
+ result = a;
1422
+ return;
1423
+ }
1424
+ if (eval_gt(a, b))
1425
+ {
1426
+ eval_subtract(result, a, b);
1427
+ }
1428
+ else
1429
+ result = zero;
1430
+ }
1431
+
1432
+ template <class T, class A>
1433
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value>::type eval_fdim(T& result, const T& a, const A& b)
1434
+ {
1435
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1436
+ using arithmetic_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
1437
+ const ui_type zero = 0u;
1438
+ arithmetic_type canonical_b = b;
1439
+ switch (BOOST_MP_FPCLASSIFY(b))
1440
+ {
1441
+ case FP_NAN:
1442
+ case FP_INFINITE:
1443
+ result = zero;
1444
+ return;
1445
+ }
1446
+ switch (eval_fpclassify(a))
1447
+ {
1448
+ case FP_NAN:
1449
+ result = zero;
1450
+ return;
1451
+ case FP_INFINITE:
1452
+ result = a;
1453
+ return;
1454
+ }
1455
+ if (eval_gt(a, canonical_b))
1456
+ {
1457
+ eval_subtract(result, a, canonical_b);
1458
+ }
1459
+ else
1460
+ result = zero;
1461
+ }
1462
+
1463
+ template <class T, class A>
1464
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value>::type eval_fdim(T& result, const A& a, const T& b)
1465
+ {
1466
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1467
+ using arithmetic_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
1468
+ const ui_type zero = 0u;
1469
+ arithmetic_type canonical_a = a;
1470
+ switch (eval_fpclassify(b))
1471
+ {
1472
+ case FP_NAN:
1473
+ case FP_INFINITE:
1474
+ result = zero;
1475
+ return;
1476
+ }
1477
+ switch (BOOST_MP_FPCLASSIFY(a))
1478
+ {
1479
+ case FP_NAN:
1480
+ result = zero;
1481
+ return;
1482
+ case FP_INFINITE:
1483
+ result = std::numeric_limits<number<T> >::infinity().backend();
1484
+ return;
1485
+ }
1486
+ if (eval_gt(canonical_a, b))
1487
+ {
1488
+ eval_subtract(result, canonical_a, b);
1489
+ }
1490
+ else
1491
+ result = zero;
1492
+ }
1493
+
1494
+ template <class T>
1495
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_trunc(T& result, const T& a)
1496
+ {
1497
+ static_assert(number_category<T>::value == number_kind_floating_point, "The trunc function is only valid for floating point types.");
1498
+ switch (eval_fpclassify(a))
1499
+ {
1500
+ case FP_NAN:
1501
+ errno = EDOM;
1502
+ // fallthrough...
1503
+ case FP_ZERO:
1504
+ case FP_INFINITE:
1505
+ result = a;
1506
+ return;
1507
+ }
1508
+ if (eval_get_sign(a) < 0)
1509
+ eval_ceil(result, a);
1510
+ else
1511
+ eval_floor(result, a);
1512
+ }
1513
+
1514
+ template <class T>
1515
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_modf(T& result, T const& arg, T* pipart)
1516
+ {
1517
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1518
+ int c = eval_fpclassify(arg);
1519
+ if (c == static_cast<int>(FP_NAN))
1520
+ {
1521
+ if (pipart)
1522
+ *pipart = arg;
1523
+ result = arg;
1524
+ return;
1525
+ }
1526
+ else if (c == static_cast<int>(FP_INFINITE))
1527
+ {
1528
+ if (pipart)
1529
+ *pipart = arg;
1530
+ result = ui_type(0u);
1531
+ return;
1532
+ }
1533
+ if (pipart)
1534
+ {
1535
+ eval_trunc(*pipart, arg);
1536
+ eval_subtract(result, arg, *pipart);
1537
+ }
1538
+ else
1539
+ {
1540
+ T ipart;
1541
+ eval_trunc(ipart, arg);
1542
+ eval_subtract(result, arg, ipart);
1543
+ }
1544
+ }
1545
+
1546
+ template <class T>
1547
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_round(T& result, const T& a)
1548
+ {
1549
+ static_assert(number_category<T>::value == number_kind_floating_point, "The round function is only valid for floating point types.");
1550
+ using fp_type = typename boost::multiprecision::detail::canonical<float, T>::type;
1551
+ int c = eval_fpclassify(a);
1552
+ if (c == static_cast<int>(FP_NAN))
1553
+ {
1554
+ result = a;
1555
+ errno = EDOM;
1556
+ return;
1557
+ }
1558
+ if ((c == FP_ZERO) || (c == static_cast<int>(FP_INFINITE)))
1559
+ {
1560
+ result = a;
1561
+ }
1562
+ else if (eval_get_sign(a) < 0)
1563
+ {
1564
+ eval_subtract(result, a, fp_type(0.5f));
1565
+ eval_ceil(result, result);
1566
+ }
1567
+ else
1568
+ {
1569
+ eval_add(result, a, fp_type(0.5f));
1570
+ eval_floor(result, result);
1571
+ }
1572
+ }
1573
+
1574
+ template <class B>
1575
+ BOOST_MP_CXX14_CONSTEXPR void eval_lcm(B& result, const B& a, const B& b);
1576
+ template <class B>
1577
+ BOOST_MP_CXX14_CONSTEXPR void eval_gcd(B& result, const B& a, const B& b);
1578
+
1579
+ template <class T, class Arithmetic>
1580
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_gcd(T& result, const T& a, const Arithmetic& b)
1581
+ {
1582
+ using si_type = typename boost::multiprecision::detail::canonical<Arithmetic, T>::type;
1583
+ using default_ops::eval_gcd;
1584
+ T t;
1585
+ t = static_cast<si_type>(b);
1586
+ eval_gcd(result, a, t);
1587
+ }
1588
+ template <class T, class Arithmetic>
1589
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_gcd(T& result, const Arithmetic& a, const T& b)
1590
+ {
1591
+ eval_gcd(result, b, a);
1592
+ }
1593
+ template <class T, class Arithmetic>
1594
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_lcm(T& result, const T& a, const Arithmetic& b)
1595
+ {
1596
+ using si_type = typename boost::multiprecision::detail::canonical<Arithmetic, T>::type;
1597
+ using default_ops::eval_lcm;
1598
+ T t;
1599
+ t = static_cast<si_type>(b);
1600
+ eval_lcm(result, a, t);
1601
+ }
1602
+ template <class T, class Arithmetic>
1603
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_lcm(T& result, const Arithmetic& a, const T& b)
1604
+ {
1605
+ eval_lcm(result, b, a);
1606
+ }
1607
+
1608
+ template <class T>
1609
+ inline BOOST_MP_CXX14_CONSTEXPR std::size_t eval_lsb(const T& val)
1610
+ {
1611
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1612
+ int c = eval_get_sign(val);
1613
+ if (c == 0)
1614
+ {
1615
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
1616
+ }
1617
+ if (c < 0)
1618
+ {
1619
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
1620
+ }
1621
+ std::size_t result = 0;
1622
+ T mask, t;
1623
+ mask = ui_type(1);
1624
+ do
1625
+ {
1626
+ eval_bitwise_and(t, mask, val);
1627
+ ++result;
1628
+ eval_left_shift(mask, 1);
1629
+ } while (eval_is_zero(t));
1630
+
1631
+ return --result;
1632
+ }
1633
+
1634
+ template <class T>
1635
+ inline BOOST_MP_CXX14_CONSTEXPR std::ptrdiff_t eval_msb(const T& val)
1636
+ {
1637
+ int c = eval_get_sign(val);
1638
+ if (c == 0)
1639
+ {
1640
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
1641
+ }
1642
+ if (c < 0)
1643
+ {
1644
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
1645
+ }
1646
+ //
1647
+ // This implementation is really really rubbish - it does
1648
+ // a linear scan for the most-significant-bit. We should really
1649
+ // do a binary search, but as none of our backends actually needs
1650
+ // this implementation, we'll leave it for now. In fact for most
1651
+ // backends it's likely that there will always be a more efficient
1652
+ // native implementation possible.
1653
+ //
1654
+ std::size_t result = 0;
1655
+ T t(val);
1656
+ while (!eval_is_zero(t))
1657
+ {
1658
+ eval_right_shift(t, 1);
1659
+ ++result;
1660
+ }
1661
+ --result;
1662
+
1663
+ return static_cast<std::ptrdiff_t>(result);
1664
+ }
1665
+
1666
+ template <class T>
1667
+ inline BOOST_MP_CXX14_CONSTEXPR bool eval_bit_test(const T& val, std::size_t index)
1668
+ {
1669
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1670
+ T mask, t;
1671
+ mask = ui_type(1);
1672
+ eval_left_shift(mask, index);
1673
+ eval_bitwise_and(t, mask, val);
1674
+ return !eval_is_zero(t);
1675
+ }
1676
+
1677
+ template <class T>
1678
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_set(T& val, std::size_t index)
1679
+ {
1680
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1681
+ T mask;
1682
+ mask = ui_type(1);
1683
+ eval_left_shift(mask, index);
1684
+ eval_bitwise_or(val, mask);
1685
+ }
1686
+
1687
+ template <class T>
1688
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_flip(T& val, std::size_t index)
1689
+ {
1690
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1691
+ T mask;
1692
+ mask = ui_type(1);
1693
+ eval_left_shift(mask, index);
1694
+ eval_bitwise_xor(val, mask);
1695
+ }
1696
+
1697
+ template <class T>
1698
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_unset(T& val, std::size_t index)
1699
+ {
1700
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1701
+ T mask, t;
1702
+ mask = ui_type(1);
1703
+ eval_left_shift(mask, index);
1704
+ eval_bitwise_and(t, mask, val);
1705
+ if (!eval_is_zero(t))
1706
+ eval_bitwise_xor(val, mask);
1707
+ }
1708
+
1709
+ template <class Backend>
1710
+ BOOST_MP_CXX14_CONSTEXPR void eval_qr(const Backend& x, const Backend& y, Backend& q, Backend& r);
1711
+
1712
+ template <class Backend>
1713
+ BOOST_MP_CXX14_CONSTEXPR void eval_karatsuba_sqrt(Backend& result, const Backend& x, Backend& r, Backend& t, size_t bits)
1714
+ {
1715
+ using default_ops::eval_is_zero;
1716
+ using default_ops::eval_subtract;
1717
+ using default_ops::eval_right_shift;
1718
+ using default_ops::eval_left_shift;
1719
+ using default_ops::eval_bit_set;
1720
+ using default_ops::eval_decrement;
1721
+ using default_ops::eval_bitwise_and;
1722
+ using default_ops::eval_add;
1723
+ using default_ops::eval_qr;
1724
+
1725
+ using small_uint = typename std::tuple_element<0, typename Backend::unsigned_types>::type;
1726
+
1727
+ constexpr small_uint zero = 0u;
1728
+
1729
+ // we can calculate it faster with std::sqrt
1730
+ #ifdef BOOST_HAS_INT128
1731
+ if (bits <= 128)
1732
+ {
1733
+ uint128_type a{}, b{}, c{};
1734
+ eval_convert_to(&a, x);
1735
+ c = boost::multiprecision::detail::karatsuba_sqrt(a, b, bits);
1736
+ r = number<Backend>::canonical_value(b);
1737
+ result = number<Backend>::canonical_value(c);
1738
+ return;
1739
+ }
1740
+ #else
1741
+ if (bits <= std::numeric_limits<std::uintmax_t>::digits)
1742
+ {
1743
+ std::uintmax_t a{ 0 }, b{ 0 }, c{ 0 };
1744
+ eval_convert_to(&a, x);
1745
+ c = boost::multiprecision::detail::karatsuba_sqrt(a, b, bits);
1746
+ r = number<Backend>::canonical_value(b);
1747
+ result = number<Backend>::canonical_value(c);
1748
+ return;
1749
+ }
1750
+ #endif
1751
+ // https://hal.inria.fr/file/index/docid/72854/filename/RR-3805.pdf
1752
+ std::size_t b = bits / 4;
1753
+ Backend q(x);
1754
+ eval_right_shift(q, b * 2);
1755
+ Backend s;
1756
+ eval_karatsuba_sqrt(s, q, r, t, bits - b * 2);
1757
+ t = zero;
1758
+ eval_bit_set(t, static_cast<unsigned>(b * 2));
1759
+ eval_left_shift(r, b);
1760
+ eval_decrement(t);
1761
+ eval_bitwise_and(t, x);
1762
+ eval_right_shift(t, b);
1763
+ eval_add(t, r);
1764
+ eval_left_shift(s, 1u);
1765
+ eval_qr(t, s, q, r);
1766
+ eval_left_shift(r, b);
1767
+ t = zero;
1768
+ eval_bit_set(t, static_cast<unsigned>(b));
1769
+ eval_decrement(t);
1770
+ eval_bitwise_and(t, x);
1771
+ eval_add(r, t);
1772
+ eval_left_shift(s, b - 1);
1773
+ eval_add(s, q);
1774
+ eval_multiply(q, q);
1775
+ // we substract after, so it works for unsigned integers too
1776
+ if (r.compare(q) < 0)
1777
+ {
1778
+ t = s;
1779
+ eval_left_shift(t, 1u);
1780
+ eval_decrement(t);
1781
+ eval_add(r, t);
1782
+ eval_decrement(s);
1783
+ }
1784
+ eval_subtract(r, q);
1785
+ result = s;
1786
+ }
1787
+
1788
+ template <class B>
1789
+ void BOOST_MP_CXX14_CONSTEXPR eval_integer_sqrt_bitwise(B& s, B& r, const B& x)
1790
+ {
1791
+ //
1792
+ // This is slow bit-by-bit integer square root, see for example
1793
+ // http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29
1794
+ // There are better methods such as http://hal.inria.fr/docs/00/07/28/54/PDF/RR-3805.pdf
1795
+ // and http://hal.inria.fr/docs/00/07/21/13/PDF/RR-4475.pdf which should be implemented
1796
+ // at some point.
1797
+ //
1798
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned char, B>::type;
1799
+
1800
+ s = ui_type(0u);
1801
+ if (eval_get_sign(x) == 0)
1802
+ {
1803
+ r = ui_type(0u);
1804
+ return;
1805
+ }
1806
+ std::ptrdiff_t g = static_cast<std::ptrdiff_t>(eval_msb(x));
1807
+ if (g <= 1)
1808
+ {
1809
+ s = ui_type(1);
1810
+ eval_subtract(r, x, s);
1811
+ return;
1812
+ }
1813
+
1814
+ B t;
1815
+ r = x;
1816
+ g /= 2;
1817
+ std::ptrdiff_t org_g = g;
1818
+ eval_bit_set(s, static_cast<std::size_t>(g));
1819
+ eval_bit_set(t, static_cast<std::size_t>(2 * g));
1820
+ eval_subtract(r, x, t);
1821
+ --g;
1822
+ if (eval_get_sign(r) == 0)
1823
+ return;
1824
+ std::ptrdiff_t msbr = static_cast<std::ptrdiff_t>(eval_msb(r));
1825
+ do
1826
+ {
1827
+ if (msbr >= org_g + g + 1)
1828
+ {
1829
+ t = s;
1830
+ eval_left_shift(t, static_cast<std::size_t>(g + 1));
1831
+ eval_bit_set(t, static_cast<std::size_t>(2 * g));
1832
+ if (t.compare(r) <= 0)
1833
+ {
1834
+ BOOST_MP_ASSERT(g >= 0);
1835
+ eval_bit_set(s, static_cast<std::size_t>(g));
1836
+ eval_subtract(r, t);
1837
+ if (eval_get_sign(r) == 0)
1838
+ return;
1839
+ msbr = static_cast<std::ptrdiff_t>(eval_msb(r));
1840
+ }
1841
+ }
1842
+ --g;
1843
+ } while (g >= 0);
1844
+ }
1845
+
1846
+ template <class Backend>
1847
+ BOOST_MP_CXX14_CONSTEXPR void eval_integer_sqrt(Backend& result, Backend& r, const Backend& x)
1848
+ {
1849
+ #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
1850
+ // recursive Karatsuba sqrt can cause issues in constexpr context:
1851
+ if (BOOST_MP_IS_CONST_EVALUATED(result.size()))
1852
+ return eval_integer_sqrt_bitwise(result, r, x);
1853
+ #endif
1854
+ using small_uint = typename std::tuple_element<0, typename Backend::unsigned_types>::type;
1855
+
1856
+ constexpr small_uint zero = 0u;
1857
+
1858
+ if (eval_is_zero(x))
1859
+ {
1860
+ r = zero;
1861
+ result = zero;
1862
+ return;
1863
+ }
1864
+ Backend t;
1865
+ eval_karatsuba_sqrt(result, x, r, t, eval_msb(x) + 1);
1866
+ }
1867
+
1868
+ template <class B>
1869
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_conj(B& result, const B& val)
1870
+ {
1871
+ result = val; // assume non-complex result.
1872
+ }
1873
+ template <class B>
1874
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_proj(B& result, const B& val)
1875
+ {
1876
+ result = val; // assume non-complex result.
1877
+ }
1878
+
1879
+ //
1880
+ // These have to implemented by the backend, declared here so that our macro generated code compiles OK.
1881
+ //
1882
+ template <class T>
1883
+ typename std::enable_if<sizeof(T) == 0>::type eval_floor();
1884
+ template <class T>
1885
+ typename std::enable_if<sizeof(T) == 0>::type eval_ceil();
1886
+ template <class T>
1887
+ typename std::enable_if<sizeof(T) == 0>::type eval_trunc();
1888
+ template <class T>
1889
+ typename std::enable_if<sizeof(T) == 0>::type eval_sqrt();
1890
+ template <class T>
1891
+ typename std::enable_if<sizeof(T) == 0>::type eval_ldexp();
1892
+ template <class T>
1893
+ typename std::enable_if<sizeof(T) == 0>::type eval_frexp();
1894
+ // TODO implement default versions of these:
1895
+ template <class T>
1896
+ typename std::enable_if<sizeof(T) == 0>::type eval_asinh();
1897
+ template <class T>
1898
+ typename std::enable_if<sizeof(T) == 0>::type eval_acosh();
1899
+ template <class T>
1900
+ typename std::enable_if<sizeof(T) == 0>::type eval_atanh();
1901
+
1902
+ //
1903
+ // eval_logb and eval_scalbn simply assume base 2 and forward to
1904
+ // eval_ldexp and eval_frexp:
1905
+ //
1906
+ template <class B>
1907
+ inline BOOST_MP_CXX14_CONSTEXPR typename B::exponent_type eval_ilogb(const B& val)
1908
+ {
1909
+ static_assert(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of ilogb requires a base 2 number type");
1910
+ typename B::exponent_type e(0);
1911
+ switch (eval_fpclassify(val))
1912
+ {
1913
+ case FP_NAN:
1914
+ #ifdef FP_ILOGBNAN
1915
+ return FP_ILOGBNAN > 0 ? (std::numeric_limits<typename B::exponent_type>::max)() : (std::numeric_limits<typename B::exponent_type>::min)();
1916
+ #else
1917
+ return (std::numeric_limits<typename B::exponent_type>::max)();
1918
+ #endif
1919
+ case FP_INFINITE:
1920
+ return (std::numeric_limits<typename B::exponent_type>::max)();
1921
+ case FP_ZERO:
1922
+ return (std::numeric_limits<typename B::exponent_type>::min)();
1923
+ }
1924
+ B result;
1925
+ eval_frexp(result, val, &e);
1926
+ return e - 1;
1927
+ }
1928
+
1929
+ template <class B>
1930
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_logb(B& result, const B& val)
1931
+ {
1932
+ switch (eval_fpclassify(val))
1933
+ {
1934
+ case FP_NAN:
1935
+ result = val;
1936
+ errno = EDOM;
1937
+ return;
1938
+ case FP_ZERO:
1939
+ result = std::numeric_limits<number<B> >::infinity().backend();
1940
+ result.negate();
1941
+ errno = ERANGE;
1942
+ return;
1943
+ case FP_INFINITE:
1944
+ result = val;
1945
+ if (eval_signbit(val))
1946
+ result.negate();
1947
+ return;
1948
+ }
1949
+ using max_t = typename std::conditional<std::is_same<std::intmax_t, long>::value, long long, std::intmax_t>::type;
1950
+ result = static_cast<max_t>(eval_ilogb(val));
1951
+ }
1952
+ template <class B, class A>
1953
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_scalbn(B& result, const B& val, A e)
1954
+ {
1955
+ static_assert(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of scalbn requires a base 2 number type");
1956
+ eval_ldexp(result, val, static_cast<typename B::exponent_type>(e));
1957
+ }
1958
+ template <class B, class A>
1959
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_scalbln(B& result, const B& val, A e)
1960
+ {
1961
+ eval_scalbn(result, val, e);
1962
+ }
1963
+
1964
+ template <class T>
1965
+ inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val, std::integral_constant<bool, true> const&, const std::integral_constant<bool, false>&)
1966
+ {
1967
+ return eval_fpclassify(val) == FP_NAN;
1968
+ }
1969
+ template <class T>
1970
+ inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val, std::integral_constant<bool, false> const&, const std::integral_constant<bool, true>&)
1971
+ {
1972
+ return BOOST_MP_ISNAN(val);
1973
+ }
1974
+ template <class T>
1975
+ inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T&, std::integral_constant<bool, false> const&, const std::integral_constant<bool, false>&)
1976
+ {
1977
+ return false;
1978
+ }
1979
+
1980
+ template <class T>
1981
+ inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val)
1982
+ {
1983
+ return is_arg_nan(val, std::integral_constant<bool, boost::multiprecision::detail::is_backend<T>::value>(), std::is_floating_point<T>());
1984
+ }
1985
+
1986
+ template <class T, class U, class V>
1987
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_fmax(T& result, const U& a, const V& b)
1988
+ {
1989
+ if (is_arg_nan(a))
1990
+ result = number<T>::canonical_value(b);
1991
+ else if (is_arg_nan(b))
1992
+ result = number<T>::canonical_value(a);
1993
+ else if (eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
1994
+ result = number<T>::canonical_value(b);
1995
+ else
1996
+ result = number<T>::canonical_value(a);
1997
+ }
1998
+ template <class T, class U, class V>
1999
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_fmin(T& result, const U& a, const V& b)
2000
+ {
2001
+ if (is_arg_nan(a))
2002
+ result = number<T>::canonical_value(b);
2003
+ else if (is_arg_nan(b))
2004
+ result = number<T>::canonical_value(a);
2005
+ else if (eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
2006
+ result = number<T>::canonical_value(a);
2007
+ else
2008
+ result = number<T>::canonical_value(b);
2009
+ }
2010
+
2011
+ template <class R, class T, class U>
2012
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_hypot(R& result, const T& a, const U& b)
2013
+ {
2014
+ //
2015
+ // Normalize x and y, so that both are positive and x >= y:
2016
+ //
2017
+ R x, y;
2018
+ x = number<R>::canonical_value(a);
2019
+ y = number<R>::canonical_value(b);
2020
+ if (eval_get_sign(x) < 0)
2021
+ x.negate();
2022
+ if (eval_get_sign(y) < 0)
2023
+ y.negate();
2024
+
2025
+ // Special case, see C99 Annex F.
2026
+ // The order of the if's is important: do not change!
2027
+ int c1 = eval_fpclassify(x);
2028
+ int c2 = eval_fpclassify(y);
2029
+
2030
+ if (c1 == FP_ZERO)
2031
+ {
2032
+ result = y;
2033
+ return;
2034
+ }
2035
+ if (c2 == FP_ZERO)
2036
+ {
2037
+ result = x;
2038
+ return;
2039
+ }
2040
+ if (c1 == FP_INFINITE)
2041
+ {
2042
+ result = x;
2043
+ return;
2044
+ }
2045
+ if ((c2 == FP_INFINITE) || (c2 == FP_NAN))
2046
+ {
2047
+ result = y;
2048
+ return;
2049
+ }
2050
+ if (c1 == FP_NAN)
2051
+ {
2052
+ result = x;
2053
+ return;
2054
+ }
2055
+
2056
+ if (eval_gt(y, x))
2057
+ x.swap(y);
2058
+
2059
+ eval_multiply(result, x, std::numeric_limits<number<R> >::epsilon().backend());
2060
+
2061
+ if (eval_gt(result, y))
2062
+ {
2063
+ result = x;
2064
+ return;
2065
+ }
2066
+
2067
+ R rat;
2068
+ eval_divide(rat, y, x);
2069
+ eval_multiply(result, rat, rat);
2070
+ eval_increment(result);
2071
+ eval_sqrt(rat, result);
2072
+ eval_multiply(result, rat, x);
2073
+ }
2074
+
2075
+ template <class R, class T>
2076
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_nearbyint(R& result, const T& a)
2077
+ {
2078
+ eval_round(result, a);
2079
+ }
2080
+ template <class R, class T>
2081
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_rint(R& result, const T& a)
2082
+ {
2083
+ eval_nearbyint(result, a);
2084
+ }
2085
+
2086
+ template <class T>
2087
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_backend<T>::value, int>::type eval_signbit(const T& val)
2088
+ {
2089
+ return eval_get_sign(val) < 0 ? 1 : 0;
2090
+ }
2091
+
2092
+ //
2093
+ // Real and imaginary parts:
2094
+ //
2095
+ template <class To, class From>
2096
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_real(To& to, const From& from)
2097
+ {
2098
+ to = from;
2099
+ }
2100
+ template <class To, class From>
2101
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_imag(To& to, const From&)
2102
+ {
2103
+ using ui_type = typename std::tuple_element<0, typename To::unsigned_types>::type;
2104
+ to = ui_type(0);
2105
+ }
2106
+
2107
+ } // namespace default_ops
2108
+ namespace default_ops_adl {
2109
+
2110
+ template <class To, class From>
2111
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real_imp(To& to, const From& from)
2112
+ {
2113
+ using to_component_type = typename component_type<number<To> >::type;
2114
+ typename to_component_type::backend_type to_component;
2115
+ to_component = from;
2116
+ eval_set_real(to, to_component);
2117
+ }
2118
+ template <class To, class From>
2119
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag_imp(To& to, const From& from)
2120
+ {
2121
+ using to_component_type = typename component_type<number<To> >::type;
2122
+ typename to_component_type::backend_type to_component;
2123
+ to_component = from;
2124
+ eval_set_imag(to, to_component);
2125
+ }
2126
+
2127
+ } // namespace default_ops_adl
2128
+ namespace default_ops {
2129
+
2130
+ template <class To, class From>
2131
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<To>::value == number_kind_complex>::type eval_set_real(To& to, const From& from)
2132
+ {
2133
+ default_ops_adl::eval_set_real_imp(to, from);
2134
+ }
2135
+ template <class To, class From>
2136
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<To>::value != number_kind_complex>::type eval_set_real(To& to, const From& from)
2137
+ {
2138
+ to = from;
2139
+ }
2140
+
2141
+ template <class To, class From>
2142
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(To& to, const From& from)
2143
+ {
2144
+ default_ops_adl::eval_set_imag_imp(to, from);
2145
+ }
2146
+
2147
+ template <class T>
2148
+ inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(T& to, const T& from)
2149
+ {
2150
+ to = from;
2151
+ }
2152
+ template <class T>
2153
+ void BOOST_MP_CXX14_CONSTEXPR eval_set_imag(T&, const T&)
2154
+ {
2155
+ static_assert(sizeof(T) == INT_MAX, "eval_set_imag needs to be specialised for each specific backend");
2156
+ }
2157
+
2158
+ //
2159
+ // These functions are implemented in separate files, but expanded inline here,
2160
+ // DO NOT CHANGE THE ORDER OF THESE INCLUDES:
2161
+ //
2162
+ #include <boost/multiprecision/detail/functions/constants.hpp>
2163
+ #include <boost/multiprecision/detail/functions/pow.hpp>
2164
+ #include <boost/multiprecision/detail/functions/trig.hpp>
2165
+
2166
+ } // namespace default_ops
2167
+
2168
+ //
2169
+ // Default versions of floating point classification routines:
2170
+ //
2171
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2172
+ inline BOOST_MP_CXX14_CONSTEXPR int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2173
+ {
2174
+ using multiprecision::default_ops::eval_fpclassify;
2175
+ return eval_fpclassify(arg.backend());
2176
+ }
2177
+ template <class tag, class A1, class A2, class A3, class A4>
2178
+ inline BOOST_MP_CXX14_CONSTEXPR int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2179
+ {
2180
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2181
+ return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
2182
+ }
2183
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2184
+ inline BOOST_MP_CXX14_CONSTEXPR bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2185
+ {
2186
+ int v = fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg);
2187
+ return (v != static_cast<int>(FP_INFINITE)) && (v != static_cast<int>(FP_NAN));
2188
+ }
2189
+ template <class tag, class A1, class A2, class A3, class A4>
2190
+ inline BOOST_MP_CXX14_CONSTEXPR bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2191
+ {
2192
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2193
+ return isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
2194
+ }
2195
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2196
+ inline BOOST_MP_CXX14_CONSTEXPR bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2197
+ {
2198
+ return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == static_cast<int>(FP_NAN);
2199
+ }
2200
+ template <class tag, class A1, class A2, class A3, class A4>
2201
+ inline BOOST_MP_CXX14_CONSTEXPR bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2202
+ {
2203
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2204
+ return isnan BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
2205
+ }
2206
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2207
+ inline BOOST_MP_CXX14_CONSTEXPR bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2208
+ {
2209
+ return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == static_cast<int>(FP_INFINITE);
2210
+ }
2211
+ template <class tag, class A1, class A2, class A3, class A4>
2212
+ inline BOOST_MP_CXX14_CONSTEXPR bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2213
+ {
2214
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2215
+ return isinf BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
2216
+ }
2217
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2218
+ inline BOOST_MP_CXX14_CONSTEXPR bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2219
+ {
2220
+ return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == static_cast<int>(FP_NORMAL);
2221
+ }
2222
+ template <class tag, class A1, class A2, class A3, class A4>
2223
+ inline BOOST_MP_CXX14_CONSTEXPR bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2224
+ {
2225
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2226
+ return isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
2227
+ }
2228
+
2229
+ // Default versions of sign manipulation functions, if individual backends can do better than this
2230
+ // (for example with signed zero), then they should overload these functions further:
2231
+
2232
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2233
+ inline BOOST_MP_CXX14_CONSTEXPR int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2234
+ {
2235
+ return arg.sign();
2236
+ }
2237
+ template <class tag, class A1, class A2, class A3, class A4>
2238
+ inline BOOST_MP_CXX14_CONSTEXPR int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2239
+ {
2240
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2241
+ return sign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
2242
+ }
2243
+
2244
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2245
+ inline BOOST_MP_CXX14_CONSTEXPR bool signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2246
+ {
2247
+ using default_ops::eval_signbit;
2248
+ return static_cast<bool>(eval_signbit(arg.backend()));
2249
+ }
2250
+ template <class tag, class A1, class A2, class A3, class A4>
2251
+ inline BOOST_MP_CXX14_CONSTEXPR bool signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2252
+ {
2253
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2254
+ return static_cast<bool>(signbit BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)));
2255
+ }
2256
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2257
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2258
+ {
2259
+ return -arg;
2260
+ }
2261
+ template <class tag, class A1, class A2, class A3, class A4>
2262
+ inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2263
+ {
2264
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2265
+ return changesign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
2266
+ }
2267
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2268
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
2269
+ {
2270
+ return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? (boost::multiprecision::changesign)(a) : a;
2271
+ }
2272
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
2273
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
2274
+ {
2275
+ return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
2276
+ }
2277
+ template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
2278
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
2279
+ {
2280
+ return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
2281
+ }
2282
+ template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
2283
+ inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
2284
+ {
2285
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2286
+ return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
2287
+ }
2288
+ //
2289
+ // real and imag:
2290
+ //
2291
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2292
+ inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type
2293
+ real(const multiprecision::number<Backend, ExpressionTemplates>& a)
2294
+ {
2295
+ using default_ops::eval_real;
2296
+ using result_type = typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type;
2297
+ boost::multiprecision::detail::scoped_default_precision<result_type> precision_guard(a);
2298
+ result_type result;
2299
+ eval_real(result.backend(), a.backend());
2300
+ return result;
2301
+ }
2302
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2303
+ inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type
2304
+ imag(const multiprecision::number<Backend, ExpressionTemplates>& a)
2305
+ {
2306
+ using default_ops::eval_imag;
2307
+ using result_type = typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type;
2308
+ boost::multiprecision::detail::scoped_default_precision<result_type> precision_guard(a);
2309
+ result_type result;
2310
+ eval_imag(result.backend(), a.backend());
2311
+ return result;
2312
+ }
2313
+
2314
+ template <class tag, class A1, class A2, class A3, class A4>
2315
+ inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2316
+ real(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2317
+ {
2318
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2319
+ detail::scoped_default_precision<value_type> precision_guard(arg);
2320
+ return real(value_type(arg));
2321
+ }
2322
+
2323
+ template <class tag, class A1, class A2, class A3, class A4>
2324
+ inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2325
+ imag(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2326
+ {
2327
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2328
+ detail::scoped_default_precision<value_type> precision_guard(arg);
2329
+ return imag(value_type(arg));
2330
+ }
2331
+
2332
+ //
2333
+ // Complex number functions, these are overloaded at the Backend level, we just provide the
2334
+ // expression template versions here, plus overloads for non-complex types:
2335
+ //
2336
+ #ifdef BOOST_MP_MATH_AVAILABLE
2337
+ template <class T, expression_template_option ExpressionTemplates>
2338
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_complex, component_type<number<T, ExpressionTemplates>>>::type::type
2339
+ abs(const number<T, ExpressionTemplates>& v)
2340
+ {
2341
+ return std::move(boost::math::hypot(real(v), imag(v)));
2342
+ }
2343
+ template <class tag, class A1, class A2, class A3, class A4>
2344
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_complex, component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type>>::type::type
2345
+ abs(const detail::expression<tag, A1, A2, A3, A4>& v)
2346
+ {
2347
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2348
+ return std::move(abs(static_cast<number_type>(v)));
2349
+ }
2350
+
2351
+ template <class T, expression_template_option ExpressionTemplates>
2352
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_complex, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
2353
+ arg(const number<T, ExpressionTemplates>& v)
2354
+ {
2355
+ return std::move(atan2(imag(v), real(v)));
2356
+ }
2357
+ template <class T, expression_template_option ExpressionTemplates>
2358
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
2359
+ arg(const number<T, ExpressionTemplates>&)
2360
+ {
2361
+ return 0;
2362
+ }
2363
+ template <class tag, class A1, class A2, class A3, class A4>
2364
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_complex || number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename scalar_result_from_possible_complex<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
2365
+ arg(const detail::expression<tag, A1, A2, A3, A4>& v)
2366
+ {
2367
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2368
+ return std::move(arg(static_cast<number_type>(v)));
2369
+ }
2370
+ #endif // BOOST_MP_MATH_AVAILABLE
2371
+
2372
+ template <class T, expression_template_option ExpressionTemplates>
2373
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_complex, component_type<number<T, ExpressionTemplates>>>::type::type
2374
+ norm(const number<T, ExpressionTemplates>& v)
2375
+ {
2376
+ typename component_type<number<T, ExpressionTemplates> >::type a(real(v)), b(imag(v));
2377
+ return std::move(a * a + b * b);
2378
+ }
2379
+ template <class T, expression_template_option ExpressionTemplates>
2380
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value != number_kind_complex, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
2381
+ norm(const number<T, ExpressionTemplates>& v)
2382
+ {
2383
+ return v * v;
2384
+ }
2385
+ template <class tag, class A1, class A2, class A3, class A4>
2386
+ inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2387
+ norm(const detail::expression<tag, A1, A2, A3, A4>& v)
2388
+ {
2389
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2390
+ return std::move(norm(static_cast<number_type>(v)));
2391
+ }
2392
+
2393
+ template <class Backend, expression_template_option ExpressionTemplates>
2394
+ BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type polar(number<Backend, ExpressionTemplates> const& r, number<Backend, ExpressionTemplates> const& theta)
2395
+ {
2396
+ return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2397
+ }
2398
+
2399
+ template <class tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
2400
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, ExpressionTemplates> >::value,
2401
+ typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
2402
+ polar(detail::expression<tag, A1, A2, A3, A4> const& r, number<Backend, ExpressionTemplates> const& theta)
2403
+ {
2404
+ return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2405
+ }
2406
+
2407
+ template <class Backend, expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
2408
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, ExpressionTemplates> >::value,
2409
+ typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
2410
+ polar(number<Backend, ExpressionTemplates> const& r, detail::expression<tag, A1, A2, A3, A4> const& theta)
2411
+ {
2412
+ return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2413
+ }
2414
+
2415
+ template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
2416
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, typename detail::expression<tagb, A1b, A2b, A3b, A4b>::result_type>::value,
2417
+ typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
2418
+ polar(detail::expression<tag, A1, A2, A3, A4> const& r, detail::expression<tagb, A1b, A2b, A3b, A4b> const& theta)
2419
+ {
2420
+ using scalar_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2421
+ return typename complex_result_from_scalar<scalar_type>::type(scalar_type(r * cos(theta)), scalar_type(r * sin(theta)));
2422
+ }
2423
+ //
2424
+ // We also allow the first argument to polar to be an arithmetic type (probably a literal):
2425
+ //
2426
+ template <class Scalar, class Backend, expression_template_option ExpressionTemplates>
2427
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<Scalar>::value, typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
2428
+ polar(Scalar const& r, number<Backend, ExpressionTemplates> const& theta)
2429
+ {
2430
+ return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2431
+ }
2432
+
2433
+ template <class tag, class A1, class A2, class A3, class A4, class Scalar>
2434
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<Scalar>::value,
2435
+ typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
2436
+ polar(Scalar const& r, detail::expression<tag, A1, A2, A3, A4> const& theta)
2437
+ {
2438
+ using scalar_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2439
+ return typename complex_result_from_scalar<scalar_type>::type(scalar_type(r * cos(theta)), scalar_type(r * sin(theta)));
2440
+ }
2441
+ //
2442
+ // Single argument overloads:
2443
+ //
2444
+ template <class Backend, expression_template_option ExpressionTemplates>
2445
+ BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type polar(number<Backend, ExpressionTemplates> const& r)
2446
+ {
2447
+ return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(r);
2448
+ }
2449
+
2450
+ template <class tag, class A1, class A2, class A3, class A4>
2451
+ BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2452
+ polar(detail::expression<tag, A1, A2, A3, A4> const& r)
2453
+ {
2454
+ return typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type(r);
2455
+ }
2456
+
2457
+ } // namespace multiprecision
2458
+
2459
+ namespace math {
2460
+
2461
+ //
2462
+ // Import Math functions here, so they can be found by Boost.Math:
2463
+ //
2464
+ using boost::multiprecision::changesign;
2465
+ using boost::multiprecision::copysign;
2466
+ using boost::multiprecision::fpclassify;
2467
+ using boost::multiprecision::isfinite;
2468
+ using boost::multiprecision::isinf;
2469
+ using boost::multiprecision::isnan;
2470
+ using boost::multiprecision::isnormal;
2471
+ using boost::multiprecision::sign;
2472
+ using boost::multiprecision::signbit;
2473
+
2474
+ #ifndef BOOST_MP_MATH_AVAILABLE
2475
+ namespace policies {
2476
+
2477
+ template <typename... Args>
2478
+ class policy {};
2479
+
2480
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
2481
+ void raise_rounding_error(T1, T2, T3, T4, T5)
2482
+ {
2483
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("Rounding error"));
2484
+ }
2485
+
2486
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
2487
+ void raise_overflow_error(T1, T2, T3, T4, T5)
2488
+ {
2489
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Overflow error"));
2490
+ }
2491
+
2492
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
2493
+ void raise_evaluation_error(T1, T2, T3, T4, T5)
2494
+ {
2495
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("Evaluation error"));
2496
+ }
2497
+
2498
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
2499
+ void raise_domain_error(T1, T2, T3, T4, T5)
2500
+ {
2501
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Domain error"));
2502
+ }
2503
+
2504
+ template <typename T, typename... Args>
2505
+ struct is_policy
2506
+ {
2507
+ static constexpr bool value = false;
2508
+ };
2509
+
2510
+ template <typename... Args>
2511
+ struct is_policy<policy<Args...>>
2512
+ {
2513
+ static constexpr bool value = true;
2514
+ };
2515
+
2516
+ } // namespace policies
2517
+ #endif
2518
+
2519
+ } // namespace math
2520
+
2521
+ namespace multiprecision {
2522
+ #ifdef BOOST_MP_MATH_AVAILABLE
2523
+ using c99_error_policy = ::boost::math::policies::policy<
2524
+ ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>,
2525
+ ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>,
2526
+ ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>,
2527
+ ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>,
2528
+ ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error> >;
2529
+
2530
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2531
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
2532
+ asinh
2533
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2534
+ {
2535
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2536
+ return boost::math::asinh(arg, c99_error_policy());
2537
+ }
2538
+ template <class tag, class A1, class A2, class A3, class A4>
2539
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2540
+ asinh
2541
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2542
+ {
2543
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2544
+ detail::scoped_default_precision<value_type> precision_guard(arg);
2545
+ return asinh(value_type(arg));
2546
+ }
2547
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2548
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
2549
+ acosh
2550
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2551
+ {
2552
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2553
+ return boost::math::acosh(arg, c99_error_policy());
2554
+ }
2555
+ template <class tag, class A1, class A2, class A3, class A4>
2556
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2557
+ acosh
2558
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2559
+ {
2560
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2561
+ detail::scoped_default_precision<value_type> precision_guard(arg);
2562
+ return acosh(value_type(arg));
2563
+ }
2564
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2565
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
2566
+ atanh
2567
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2568
+ {
2569
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2570
+ return boost::math::atanh(arg, c99_error_policy());
2571
+ }
2572
+ template <class tag, class A1, class A2, class A3, class A4>
2573
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2574
+ atanh
2575
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2576
+ {
2577
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2578
+ detail::scoped_default_precision<value_type> precision_guard(arg);
2579
+ return atanh(value_type(arg));
2580
+ }
2581
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2582
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2583
+ {
2584
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2585
+ return boost::math::cbrt(arg, c99_error_policy());
2586
+ }
2587
+ template <class tag, class A1, class A2, class A3, class A4>
2588
+ inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2589
+ {
2590
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2591
+ detail::scoped_default_precision<value_type> precision_guard(arg);
2592
+ return cbrt(value_type(arg));
2593
+ }
2594
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2595
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2596
+ {
2597
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2598
+ return boost::math::erf(arg, c99_error_policy());
2599
+ }
2600
+ template <class tag, class A1, class A2, class A3, class A4>
2601
+ inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2602
+ {
2603
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2604
+ detail::scoped_default_precision<value_type> precision_guard(arg);
2605
+ return erf(value_type(arg));
2606
+ }
2607
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2608
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2609
+ {
2610
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2611
+ return boost::math::erfc(arg, c99_error_policy());
2612
+ }
2613
+ template <class tag, class A1, class A2, class A3, class A4>
2614
+ inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2615
+ {
2616
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2617
+ detail::scoped_default_precision<value_type> precision_guard(arg);
2618
+ return erfc(value_type(arg));
2619
+ }
2620
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2621
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2622
+ {
2623
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2624
+ return boost::math::expm1(arg, c99_error_policy());
2625
+ }
2626
+ template <class tag, class A1, class A2, class A3, class A4>
2627
+ inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2628
+ {
2629
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2630
+ detail::scoped_default_precision<value_type> precision_guard(arg);
2631
+ return expm1(value_type(arg));
2632
+ }
2633
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2634
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2635
+ {
2636
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2637
+ multiprecision::number<Backend, ExpressionTemplates> result;
2638
+ result = boost::math::lgamma(arg, c99_error_policy());
2639
+ if ((boost::multiprecision::isnan)(result) && !(boost::multiprecision::isnan)(arg))
2640
+ {
2641
+ result = std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::infinity();
2642
+ errno = ERANGE;
2643
+ }
2644
+ return result;
2645
+ }
2646
+ template <class tag, class A1, class A2, class A3, class A4>
2647
+ inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2648
+ {
2649
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2650
+ detail::scoped_default_precision<value_type> precision_guard(arg);
2651
+ return lgamma(value_type(arg));
2652
+ }
2653
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2654
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2655
+ {
2656
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2657
+ if ((arg == 0) && std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::has_infinity)
2658
+ {
2659
+ errno = ERANGE;
2660
+ return 1 / arg;
2661
+ }
2662
+ return boost::math::tgamma(arg, c99_error_policy());
2663
+ }
2664
+ template <class tag, class A1, class A2, class A3, class A4>
2665
+ inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2666
+ {
2667
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2668
+ detail::scoped_default_precision<value_type> precision_guard(arg);
2669
+ return tgamma(value_type(arg));
2670
+ }
2671
+
2672
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2673
+ inline BOOST_MP_CXX14_CONSTEXPR long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2674
+ {
2675
+ return lround(arg);
2676
+ }
2677
+ template <class tag, class A1, class A2, class A3, class A4>
2678
+ inline BOOST_MP_CXX14_CONSTEXPR long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2679
+ {
2680
+ return lround(arg);
2681
+ }
2682
+ #ifndef BOOST_NO_LONG_LONG
2683
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2684
+ inline BOOST_MP_CXX14_CONSTEXPR long long llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2685
+ {
2686
+ return llround(arg);
2687
+ }
2688
+ template <class tag, class A1, class A2, class A3, class A4>
2689
+ inline BOOST_MP_CXX14_CONSTEXPR long long llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2690
+ {
2691
+ return llround(arg);
2692
+ }
2693
+ #endif
2694
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2695
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2696
+ {
2697
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2698
+ return boost::math::log1p(arg, c99_error_policy());
2699
+ }
2700
+ template <class tag, class A1, class A2, class A3, class A4>
2701
+ inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2702
+ {
2703
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2704
+ detail::scoped_default_precision<value_type> precision_guard(arg);
2705
+ return log1p(value_type(arg));
2706
+ }
2707
+
2708
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2709
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
2710
+ {
2711
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2712
+ return boost::math::nextafter(a, b, c99_error_policy());
2713
+ }
2714
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
2715
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
2716
+ {
2717
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2718
+ return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
2719
+ }
2720
+ template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
2721
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
2722
+ {
2723
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2724
+ return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
2725
+ }
2726
+ template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
2727
+ inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
2728
+ {
2729
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2730
+ detail::scoped_default_precision<value_type> precision_guard(a, b);
2731
+ return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
2732
+ }
2733
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2734
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
2735
+ {
2736
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2737
+ return boost::math::nextafter(a, b, c99_error_policy());
2738
+ }
2739
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
2740
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
2741
+ {
2742
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2743
+ return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
2744
+ }
2745
+ template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
2746
+ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
2747
+ {
2748
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2749
+ return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
2750
+ }
2751
+ template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
2752
+ inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
2753
+ {
2754
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2755
+ detail::scoped_default_precision<value_type> precision_guard(a, b);
2756
+ return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
2757
+ }
2758
+ #endif // BOOST_MP_MATH_AVAILABLE
2759
+
2760
+ template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
2761
+ inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& add(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
2762
+ {
2763
+ static_assert((std::is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
2764
+ static_assert((std::is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
2765
+ using default_ops::eval_add;
2766
+ eval_add(result.backend(), a.backend(), b.backend());
2767
+ return result;
2768
+ }
2769
+
2770
+ template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
2771
+ inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& subtract(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
2772
+ {
2773
+ static_assert((std::is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
2774
+ static_assert((std::is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
2775
+ using default_ops::eval_subtract;
2776
+ eval_subtract(result.backend(), a.backend(), b.backend());
2777
+ return result;
2778
+ }
2779
+
2780
+ template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
2781
+ inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& multiply(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
2782
+ {
2783
+ static_assert((std::is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
2784
+ static_assert((std::is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
2785
+ using default_ops::eval_multiply;
2786
+ eval_multiply(result.backend(), a.backend(), b.backend());
2787
+ return result;
2788
+ }
2789
+
2790
+ template <class B, expression_template_option ET, class I>
2791
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value, number<B, ET>&>::type
2792
+ add(number<B, ET>& result, const I& a, const I& b)
2793
+ {
2794
+ using default_ops::eval_add;
2795
+ using canonical_type = typename detail::canonical<I, B>::type;
2796
+ eval_add(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
2797
+ return result;
2798
+ }
2799
+
2800
+ template <class B, expression_template_option ET, class I>
2801
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value, number<B, ET>&>::type
2802
+ subtract(number<B, ET>& result, const I& a, const I& b)
2803
+ {
2804
+ using default_ops::eval_subtract;
2805
+ using canonical_type = typename detail::canonical<I, B>::type;
2806
+ eval_subtract(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
2807
+ return result;
2808
+ }
2809
+
2810
+ template <class B, expression_template_option ET, class I>
2811
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value, number<B, ET>&>::type
2812
+ multiply(number<B, ET>& result, const I& a, const I& b)
2813
+ {
2814
+ using default_ops::eval_multiply;
2815
+ using canonical_type = typename detail::canonical<I, B>::type;
2816
+ eval_multiply(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
2817
+ return result;
2818
+ }
2819
+
2820
+ template <class tag, class A1, class A2, class A3, class A4, class Policy>
2821
+ inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<tag, A1, A2, A3, A4>::result_type trunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2822
+ {
2823
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2824
+ return std::move(trunc(number_type(v), pol));
2825
+ }
2826
+
2827
+ template <class Backend, expression_template_option ExpressionTemplates, class Policy>
2828
+ inline BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates> trunc(const number<Backend, ExpressionTemplates>& v, const Policy&)
2829
+ {
2830
+ using default_ops::eval_trunc;
2831
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(v);
2832
+ number<Backend, ExpressionTemplates> result;
2833
+ eval_trunc(result.backend(), v.backend());
2834
+ return result;
2835
+ }
2836
+
2837
+ template <class tag, class A1, class A2, class A3, class A4, class Policy>
2838
+ inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2839
+ {
2840
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2841
+ number_type r(trunc(v, pol));
2842
+ if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_ISFINITE(v))
2843
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", nullptr, number_type(v), 0, pol);
2844
+ return r.template convert_to<int>();
2845
+ }
2846
+ template <class tag, class A1, class A2, class A3, class A4>
2847
+ inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
2848
+ {
2849
+ return itrunc(v, boost::math::policies::policy<>());
2850
+ }
2851
+ template <class Backend, expression_template_option ExpressionTemplates, class Policy>
2852
+ inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const number<Backend, ExpressionTemplates>& v, const Policy& pol)
2853
+ {
2854
+ number<Backend, ExpressionTemplates> r(trunc(v, pol));
2855
+ if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_ISFINITE(v))
2856
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", nullptr, v, 0, pol);
2857
+ return r.template convert_to<int>();
2858
+ }
2859
+ template <class Backend, expression_template_option ExpressionTemplates>
2860
+ inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const number<Backend, ExpressionTemplates>& v)
2861
+ {
2862
+ return itrunc(v, boost::math::policies::policy<>());
2863
+ }
2864
+ template <class tag, class A1, class A2, class A3, class A4, class Policy>
2865
+ inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2866
+ {
2867
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2868
+ number_type r(trunc(v, pol));
2869
+ if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_ISFINITE(v))
2870
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", nullptr, number_type(v), 0L, pol);
2871
+ return r.template convert_to<long>();
2872
+ }
2873
+ template <class tag, class A1, class A2, class A3, class A4>
2874
+ inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
2875
+ {
2876
+ return ltrunc(v, boost::math::policies::policy<>());
2877
+ }
2878
+ template <class T, expression_template_option ExpressionTemplates, class Policy>
2879
+ inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
2880
+ {
2881
+ number<T, ExpressionTemplates> r(trunc(v, pol));
2882
+ if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_ISFINITE(v))
2883
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", nullptr, v, 0L, pol);
2884
+ return r.template convert_to<long>();
2885
+ }
2886
+ template <class T, expression_template_option ExpressionTemplates>
2887
+ inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const number<T, ExpressionTemplates>& v)
2888
+ {
2889
+ return ltrunc(v, boost::math::policies::policy<>());
2890
+ }
2891
+ #ifndef BOOST_NO_LONG_LONG
2892
+ template <class tag, class A1, class A2, class A3, class A4, class Policy>
2893
+ inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2894
+ {
2895
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2896
+ number_type r(trunc(v, pol));
2897
+ if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_ISFINITE(v))
2898
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", nullptr, number_type(v), 0LL, pol);
2899
+ return r.template convert_to<long long>();
2900
+ }
2901
+ template <class tag, class A1, class A2, class A3, class A4>
2902
+ inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
2903
+ {
2904
+ return lltrunc(v, boost::math::policies::policy<>());
2905
+ }
2906
+ template <class T, expression_template_option ExpressionTemplates, class Policy>
2907
+ inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
2908
+ {
2909
+ number<T, ExpressionTemplates> r(trunc(v, pol));
2910
+ if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_ISFINITE(v))
2911
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", nullptr, v, 0LL, pol);
2912
+ return r.template convert_to<long long>();
2913
+ }
2914
+ template <class T, expression_template_option ExpressionTemplates>
2915
+ inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const number<T, ExpressionTemplates>& v)
2916
+ {
2917
+ return lltrunc(v, boost::math::policies::policy<>());
2918
+ }
2919
+ #endif
2920
+ template <class tag, class A1, class A2, class A3, class A4, class Policy>
2921
+ inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<tag, A1, A2, A3, A4>::result_type round(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2922
+ {
2923
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2924
+ return std::move(round(static_cast<number_type>(v), pol));
2925
+ }
2926
+ template <class T, expression_template_option ExpressionTemplates, class Policy>
2927
+ inline BOOST_MP_CXX14_CONSTEXPR number<T, ExpressionTemplates> round(const number<T, ExpressionTemplates>& v, const Policy&)
2928
+ {
2929
+ using default_ops::eval_round;
2930
+ detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2931
+ number<T, ExpressionTemplates> result;
2932
+ eval_round(result.backend(), v.backend());
2933
+ return result;
2934
+ }
2935
+
2936
+ template <class tag, class A1, class A2, class A3, class A4, class Policy>
2937
+ inline BOOST_MP_CXX14_CONSTEXPR int iround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2938
+ {
2939
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2940
+ number_type r(round(v, pol));
2941
+ if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_ISFINITE(v))
2942
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", nullptr, number_type(v), 0, pol);
2943
+ return r.template convert_to<int>();
2944
+ }
2945
+ template <class tag, class A1, class A2, class A3, class A4>
2946
+ inline BOOST_MP_CXX14_CONSTEXPR int iround(const detail::expression<tag, A1, A2, A3, A4>& v)
2947
+ {
2948
+ return iround(v, boost::math::policies::policy<>());
2949
+ }
2950
+ template <class T, expression_template_option ExpressionTemplates, class Policy>
2951
+ inline BOOST_MP_CXX14_CONSTEXPR int iround(const number<T, ExpressionTemplates>& v, const Policy& pol)
2952
+ {
2953
+ number<T, ExpressionTemplates> r(round(v, pol));
2954
+ if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_ISFINITE(v))
2955
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", nullptr, v, 0, pol);
2956
+ return r.template convert_to<int>();
2957
+ }
2958
+ template <class T, expression_template_option ExpressionTemplates>
2959
+ inline BOOST_MP_CXX14_CONSTEXPR int iround(const number<T, ExpressionTemplates>& v)
2960
+ {
2961
+ return iround(v, boost::math::policies::policy<>());
2962
+ }
2963
+ template <class tag, class A1, class A2, class A3, class A4, class Policy>
2964
+ inline BOOST_MP_CXX14_CONSTEXPR long lround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2965
+ {
2966
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2967
+ number_type r(round(v, pol));
2968
+ if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_ISFINITE(v))
2969
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", nullptr, number_type(v), 0L, pol);
2970
+ return r.template convert_to<long>();
2971
+ }
2972
+ template <class tag, class A1, class A2, class A3, class A4>
2973
+ inline BOOST_MP_CXX14_CONSTEXPR long lround(const detail::expression<tag, A1, A2, A3, A4>& v)
2974
+ {
2975
+ return lround(v, boost::math::policies::policy<>());
2976
+ }
2977
+ template <class T, expression_template_option ExpressionTemplates, class Policy>
2978
+ inline BOOST_MP_CXX14_CONSTEXPR long lround(const number<T, ExpressionTemplates>& v, const Policy& pol)
2979
+ {
2980
+ number<T, ExpressionTemplates> r(round(v, pol));
2981
+ if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_ISFINITE(v))
2982
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", nullptr, v, 0L, pol);
2983
+ return r.template convert_to<long>();
2984
+ }
2985
+ template <class T, expression_template_option ExpressionTemplates>
2986
+ inline BOOST_MP_CXX14_CONSTEXPR long lround(const number<T, ExpressionTemplates>& v)
2987
+ {
2988
+ return lround(v, boost::math::policies::policy<>());
2989
+ }
2990
+ #ifndef BOOST_NO_LONG_LONG
2991
+ template <class tag, class A1, class A2, class A3, class A4, class Policy>
2992
+ inline BOOST_MP_CXX14_CONSTEXPR long long llround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2993
+ {
2994
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2995
+ number_type r(round(v, pol));
2996
+ if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_ISFINITE(v))
2997
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", nullptr, number_type(v), 0LL, pol);
2998
+ return r.template convert_to<long long>();
2999
+ }
3000
+ template <class tag, class A1, class A2, class A3, class A4>
3001
+ inline BOOST_MP_CXX14_CONSTEXPR long long llround(const detail::expression<tag, A1, A2, A3, A4>& v)
3002
+ {
3003
+ return llround(v, boost::math::policies::policy<>());
3004
+ }
3005
+ template <class T, expression_template_option ExpressionTemplates, class Policy>
3006
+ inline BOOST_MP_CXX14_CONSTEXPR long long llround(const number<T, ExpressionTemplates>& v, const Policy& pol)
3007
+ {
3008
+ number<T, ExpressionTemplates> r(round(v, pol));
3009
+ if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_ISFINITE(v))
3010
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", nullptr, v, 0LL, pol);
3011
+ return r.template convert_to<long long>();
3012
+ }
3013
+ template <class T, expression_template_option ExpressionTemplates>
3014
+ inline BOOST_MP_CXX14_CONSTEXPR long long llround(const number<T, ExpressionTemplates>& v)
3015
+ {
3016
+ return llround(v, boost::math::policies::policy<>());
3017
+ }
3018
+ #endif
3019
+ //
3020
+ // frexp does not return an expression template since we require the
3021
+ // integer argument to be evaluated even if the returned value is
3022
+ // not assigned to anything...
3023
+ //
3024
+ template <class T, expression_template_option ExpressionTemplates>
3025
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, short* pint)
3026
+ {
3027
+ using default_ops::eval_frexp;
3028
+ detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
3029
+ number<T, ExpressionTemplates> result;
3030
+ eval_frexp(result.backend(), v.backend(), pint);
3031
+ return result;
3032
+ }
3033
+ template <class tag, class A1, class A2, class A3, class A4>
3034
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
3035
+ frexp(const detail::expression<tag, A1, A2, A3, A4>& v, short* pint)
3036
+ {
3037
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
3038
+ return std::move(frexp(static_cast<number_type>(v), pint));
3039
+ }
3040
+ template <class T, expression_template_option ExpressionTemplates>
3041
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, int* pint)
3042
+ {
3043
+ using default_ops::eval_frexp;
3044
+ detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
3045
+ number<T, ExpressionTemplates> result;
3046
+ eval_frexp(result.backend(), v.backend(), pint);
3047
+ return result;
3048
+ }
3049
+ template <class tag, class A1, class A2, class A3, class A4>
3050
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
3051
+ frexp(const detail::expression<tag, A1, A2, A3, A4>& v, int* pint)
3052
+ {
3053
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
3054
+ return std::move(frexp(static_cast<number_type>(v), pint));
3055
+ }
3056
+ template <class T, expression_template_option ExpressionTemplates>
3057
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long* pint)
3058
+ {
3059
+ using default_ops::eval_frexp;
3060
+ detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
3061
+ number<T, ExpressionTemplates> result;
3062
+ eval_frexp(result.backend(), v.backend(), pint);
3063
+ return result;
3064
+ }
3065
+ template <class tag, class A1, class A2, class A3, class A4>
3066
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
3067
+ frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long* pint)
3068
+ {
3069
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
3070
+ return std::move(frexp(static_cast<number_type>(v), pint));
3071
+ }
3072
+ template <class T, expression_template_option ExpressionTemplates>
3073
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long long* pint)
3074
+ {
3075
+ using default_ops::eval_frexp;
3076
+ detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
3077
+ number<T, ExpressionTemplates> result;
3078
+ eval_frexp(result.backend(), v.backend(), pint);
3079
+ return result;
3080
+ }
3081
+ template <class tag, class A1, class A2, class A3, class A4>
3082
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
3083
+ frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long long* pint)
3084
+ {
3085
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
3086
+ return std::move(frexp(static_cast<number_type>(v), pint));
3087
+ }
3088
+ //
3089
+ // modf does not return an expression template since we require the
3090
+ // second argument to be evaluated even if the returned value is
3091
+ // not assigned to anything...
3092
+ //
3093
+ template <class T, expression_template_option ExpressionTemplates>
3094
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type modf(const number<T, ExpressionTemplates>& v, number<T, ExpressionTemplates>* pipart)
3095
+ {
3096
+ using default_ops::eval_modf;
3097
+ detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
3098
+ number<T, ExpressionTemplates> result;
3099
+ eval_modf(result.backend(), v.backend(), pipart ? &pipart->backend() : nullptr);
3100
+ return result;
3101
+ }
3102
+ template <class T, expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
3103
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type modf(const detail::expression<tag, A1, A2, A3, A4>& v, number<T, ExpressionTemplates>* pipart)
3104
+ {
3105
+ using default_ops::eval_modf;
3106
+ detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
3107
+ number<T, ExpressionTemplates> result, arg(v);
3108
+ eval_modf(result.backend(), arg.backend(), pipart ? &pipart->backend() : nullptr);
3109
+ return result;
3110
+ }
3111
+
3112
+ //
3113
+ // Integer square root:
3114
+ //
3115
+ template <class B, expression_template_option ExpressionTemplates>
3116
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
3117
+ sqrt(const number<B, ExpressionTemplates>& x)
3118
+ {
3119
+ using default_ops::eval_integer_sqrt;
3120
+ number<B, ExpressionTemplates> s, r;
3121
+ eval_integer_sqrt(s.backend(), r.backend(), x.backend());
3122
+ return s;
3123
+ }
3124
+ template <class tag, class A1, class A2, class A3, class A4>
3125
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_integer, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
3126
+ sqrt(const detail::expression<tag, A1, A2, A3, A4>& arg)
3127
+ {
3128
+ using default_ops::eval_integer_sqrt;
3129
+ using result_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
3130
+ detail::scoped_default_precision<result_type> precision_guard(arg);
3131
+ result_type result, v(arg), r;
3132
+ eval_integer_sqrt(result.backend(), r.backend(), v.backend());
3133
+ return result;
3134
+ }
3135
+
3136
+ //
3137
+ // fma:
3138
+ //
3139
+
3140
+ namespace default_ops {
3141
+
3142
+ struct fma_func
3143
+ {
3144
+ template <class B, class T, class U, class V>
3145
+ BOOST_MP_CXX14_CONSTEXPR void operator()(B& result, const T& a, const U& b, const V& c) const
3146
+ {
3147
+ eval_multiply_add(result, a, b, c);
3148
+ }
3149
+ };
3150
+
3151
+ } // namespace default_ops
3152
+
3153
+ template <class Backend, class U, class V>
3154
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3155
+ (number_category<number<Backend, et_on> >::value == number_kind_floating_point) &&
3156
+ (is_number<U>::value || is_number_expression<U>::value || boost::multiprecision::detail::is_arithmetic<U>::value) &&
3157
+ (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
3158
+ detail::expression<detail::function, default_ops::fma_func, number<Backend, et_on>, U, V> >::type
3159
+ fma(const number<Backend, et_on>& a, const U& b, const V& c)
3160
+ {
3161
+ return detail::expression<detail::function, default_ops::fma_func, number<Backend, et_on>, U, V>(
3162
+ default_ops::fma_func(), a, b, c);
3163
+ }
3164
+
3165
+ template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class U, class V>
3166
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3167
+ (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) &&
3168
+ (is_number<U>::value || is_number_expression<U>::value || boost::multiprecision::detail::is_arithmetic<U>::value) &&
3169
+ (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
3170
+ detail::expression<detail::function, default_ops::fma_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, V> >::type
3171
+ fma(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const U& b, const V& c)
3172
+ {
3173
+ return detail::expression<detail::function, default_ops::fma_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, V>(
3174
+ default_ops::fma_func(), a, b, c);
3175
+ }
3176
+
3177
+ template <class Backend, class U, class V>
3178
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3179
+ (number_category<number<Backend, et_off> >::value == number_kind_floating_point) &&
3180
+ (is_number<U>::value || is_number_expression<U>::value || boost::multiprecision::detail::is_arithmetic<U>::value) &&
3181
+ (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
3182
+ number<Backend, et_off> >::type
3183
+ fma(const number<Backend, et_off>& a, const U& b, const V& c)
3184
+ {
3185
+ using default_ops::eval_multiply_add;
3186
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
3187
+ number<Backend, et_off> result;
3188
+ eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
3189
+ return result;
3190
+ }
3191
+
3192
+ template <class U, class Backend, class V>
3193
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3194
+ (number_category<number<Backend, et_on> >::value == number_kind_floating_point) &&
3195
+ boost::multiprecision::detail::is_arithmetic<U>::value &&
3196
+ (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
3197
+ detail::expression<detail::function, default_ops::fma_func, U, number<Backend, et_on>, V> >::type
3198
+ fma(const U& a, const number<Backend, et_on>& b, const V& c)
3199
+ {
3200
+ return detail::expression<detail::function, default_ops::fma_func, U, number<Backend, et_on>, V>(
3201
+ default_ops::fma_func(), a, b, c);
3202
+ }
3203
+
3204
+ template <class U, class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
3205
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3206
+ (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) &&
3207
+ boost::multiprecision::detail::is_arithmetic<U>::value &&
3208
+ (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
3209
+ detail::expression<detail::function, default_ops::fma_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
3210
+ fma(const U& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b, const V& c)
3211
+ {
3212
+ return detail::expression<detail::function, default_ops::fma_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(
3213
+ default_ops::fma_func(), a, b, c);
3214
+ }
3215
+
3216
+ template <class U, class Backend, class V>
3217
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3218
+ (number_category<number<Backend, et_off> >::value == number_kind_floating_point) &&
3219
+ boost::multiprecision::detail::is_arithmetic<U>::value &&
3220
+ (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
3221
+ number<Backend, et_off> >::type
3222
+ fma(const U& a, const number<Backend, et_off>& b, const V& c)
3223
+ {
3224
+ using default_ops::eval_multiply_add;
3225
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
3226
+ number<Backend, et_off> result;
3227
+ eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
3228
+ return result;
3229
+ }
3230
+
3231
+ template <class U, class V, class Backend>
3232
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3233
+ (number_category<number<Backend, et_on> >::value == number_kind_floating_point) &&
3234
+ boost::multiprecision::detail::is_arithmetic<U>::value &&
3235
+ boost::multiprecision::detail::is_arithmetic<V>::value,
3236
+ detail::expression<detail::function, default_ops::fma_func, U, V, number<Backend, et_on> > >::type
3237
+ fma(const U& a, const V& b, const number<Backend, et_on>& c)
3238
+ {
3239
+ return detail::expression<detail::function, default_ops::fma_func, U, V, number<Backend, et_on> >(
3240
+ default_ops::fma_func(), a, b, c);
3241
+ }
3242
+
3243
+ template <class U, class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
3244
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3245
+ (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) &&
3246
+ boost::multiprecision::detail::is_arithmetic<U>::value &&
3247
+ boost::multiprecision::detail::is_arithmetic<V>::value,
3248
+ detail::expression<detail::function, default_ops::fma_func, U, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
3249
+ fma(const U& a, const V& b, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& c)
3250
+ {
3251
+ return detail::expression<detail::function, default_ops::fma_func, U, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(
3252
+ default_ops::fma_func(), a, b, c);
3253
+ }
3254
+
3255
+ template <class U, class V, class Backend>
3256
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3257
+ (number_category<number<Backend, et_off> >::value == number_kind_floating_point) &&
3258
+ boost::multiprecision::detail::is_arithmetic<U>::value &&
3259
+ boost::multiprecision::detail::is_arithmetic<V>::value,
3260
+ number<Backend, et_off> >::type
3261
+ fma(const U& a, const V& b, const number<Backend, et_off>& c)
3262
+ {
3263
+ using default_ops::eval_multiply_add;
3264
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
3265
+ number<Backend, et_off> result;
3266
+ eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
3267
+ return result;
3268
+ }
3269
+
3270
+ namespace default_ops {
3271
+
3272
+ struct remquo_func
3273
+ {
3274
+ template <class B, class T, class U>
3275
+ BOOST_MP_CXX14_CONSTEXPR void operator()(B& result, const T& a, const U& b, int* pi) const
3276
+ {
3277
+ eval_remquo(result, a, b, pi);
3278
+ }
3279
+ };
3280
+
3281
+ } // namespace default_ops
3282
+
3283
+ template <class Backend, class U>
3284
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3285
+ number_category<number<Backend, et_on> >::value == number_kind_floating_point,
3286
+ detail::expression<detail::function, default_ops::remquo_func, number<Backend, et_on>, U, int*> >::type
3287
+ remquo(const number<Backend, et_on>& a, const U& b, int* pi)
3288
+ {
3289
+ return detail::expression<detail::function, default_ops::remquo_func, number<Backend, et_on>, U, int*>(
3290
+ default_ops::remquo_func(), a, b, pi);
3291
+ }
3292
+
3293
+ template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class U>
3294
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3295
+ number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point,
3296
+ detail::expression<detail::function, default_ops::remquo_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, int*> >::type
3297
+ remquo(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const U& b, int* pi)
3298
+ {
3299
+ return detail::expression<detail::function, default_ops::remquo_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, int*>(
3300
+ default_ops::remquo_func(), a, b, pi);
3301
+ }
3302
+
3303
+ template <class U, class Backend>
3304
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3305
+ (number_category<number<Backend, et_on> >::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
3306
+ detail::expression<detail::function, default_ops::remquo_func, U, number<Backend, et_on>, int*> >::type
3307
+ remquo(const U& a, const number<Backend, et_on>& b, int* pi)
3308
+ {
3309
+ return detail::expression<detail::function, default_ops::remquo_func, U, number<Backend, et_on>, int*>(
3310
+ default_ops::remquo_func(), a, b, pi);
3311
+ }
3312
+
3313
+ template <class U, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
3314
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3315
+ (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
3316
+ detail::expression<detail::function, default_ops::remquo_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, int*> >::type
3317
+ remquo(const U& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b, int* pi)
3318
+ {
3319
+ return detail::expression<detail::function, default_ops::remquo_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, int*>(
3320
+ default_ops::remquo_func(), a, b, pi);
3321
+ }
3322
+
3323
+ template <class Backend, class U>
3324
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3325
+ number_category<number<Backend, et_on> >::value == number_kind_floating_point,
3326
+ number<Backend, et_off> >::type
3327
+ remquo(const number<Backend, et_off>& a, const U& b, int* pi)
3328
+ {
3329
+ using default_ops::eval_remquo;
3330
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b);
3331
+ number<Backend, et_off> result;
3332
+ eval_remquo(result.backend(), a.backend(), number<Backend, et_off>::canonical_value(b), pi);
3333
+ return result;
3334
+ }
3335
+ template <class U, class Backend>
3336
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3337
+ (number_category<number<Backend, et_on> >::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
3338
+ number<Backend, et_off> >::type
3339
+ remquo(const U& a, const number<Backend, et_off>& b, int* pi)
3340
+ {
3341
+ using default_ops::eval_remquo;
3342
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b);
3343
+ number<Backend, et_off> result;
3344
+ eval_remquo(result.backend(), number<Backend, et_off>::canonical_value(a), b.backend(), pi);
3345
+ return result;
3346
+ }
3347
+
3348
+ template <class B, expression_template_option ExpressionTemplates>
3349
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
3350
+ sqrt(const number<B, ExpressionTemplates>& x, number<B, ExpressionTemplates>& r)
3351
+ {
3352
+ using default_ops::eval_integer_sqrt;
3353
+ detail::scoped_default_precision<multiprecision::number<B, ExpressionTemplates> > precision_guard(x, r);
3354
+ number<B, ExpressionTemplates> s;
3355
+ eval_integer_sqrt(s.backend(), r.backend(), x.backend());
3356
+ return s;
3357
+ }
3358
+ template <class B, expression_template_option ExpressionTemplates, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
3359
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
3360
+ sqrt(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& arg, number<B, ExpressionTemplates>& r)
3361
+ {
3362
+ using default_ops::eval_integer_sqrt;
3363
+ detail::scoped_default_precision<multiprecision::number<B, ExpressionTemplates> > precision_guard(r);
3364
+ number<B, ExpressionTemplates> s;
3365
+ number<B, ExpressionTemplates> x(arg);
3366
+ eval_integer_sqrt(s.backend(), r.backend(), x.backend());
3367
+ return s;
3368
+ }
3369
+
3370
+ // clang-format off
3371
+ //
3372
+ // Regrettably, when the argument to a function is an rvalue we must return by value, and not return an
3373
+ // expression template, otherwise we can end up with dangling references.
3374
+ // See https://github.com/boostorg/multiprecision/issues/175.
3375
+ //
3376
+ #define UNARY_OP_FUNCTOR_CXX11_RVALUE(func, category)\
3377
+ template <class Backend> \
3378
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> > ::type \
3379
+ func(number<Backend, et_on>&& arg) \
3380
+ { \
3381
+ detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg); \
3382
+ number<Backend, et_on> result; \
3383
+ using default_ops::BOOST_JOIN(eval_, func); \
3384
+ BOOST_JOIN(eval_, func)(result.backend(), arg.backend()); \
3385
+ return result; \
3386
+ } \
3387
+
3388
+ #define BINARY_OP_FUNCTOR_CXX11_RVALUE(func, category)\
3389
+ template <class Backend> \
3390
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> >::type func(number<Backend, et_on>&& arg, const number<Backend, et_on>& a) \
3391
+ { \
3392
+ detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg, a); \
3393
+ number<Backend, et_on> result; \
3394
+ using default_ops::BOOST_JOIN(eval_, func); \
3395
+ BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
3396
+ return result; \
3397
+ } \
3398
+ template <class Backend> \
3399
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> >::type func(const number<Backend, et_on>& arg, number<Backend, et_on>&& a) \
3400
+ { \
3401
+ detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg, a); \
3402
+ number<Backend, et_on> result; \
3403
+ using default_ops::BOOST_JOIN(eval_, func); \
3404
+ BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
3405
+ return result; \
3406
+ } \
3407
+ template <class Backend> \
3408
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> >::type func(number<Backend, et_on>&& arg, number<Backend, et_on>&& a) \
3409
+ { \
3410
+ detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg, a); \
3411
+ number<Backend, et_on> result; \
3412
+ using default_ops::BOOST_JOIN(eval_, func); \
3413
+ BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
3414
+ return result; \
3415
+ } \
3416
+ template <class Backend, class tag, class A1, class A2, class A3, class A4> \
3417
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
3418
+ number<Backend, et_on> > ::type \
3419
+ func(number<Backend, et_on>&& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
3420
+ { \
3421
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3422
+ number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3423
+ } \
3424
+ template <class tag, class A1, class A2, class A3, class A4, class Backend> \
3425
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
3426
+ number<Backend, et_on> > ::type \
3427
+ func(const detail::expression<tag, A1, A2, A3, A4>& arg, number<Backend, et_on>&& a) \
3428
+ { \
3429
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3430
+ detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3431
+ } \
3432
+ template <class Backend, class Arithmetic> \
3433
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3434
+ is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
3435
+ number<Backend, et_on> >::type \
3436
+ func(number<Backend, et_on>&& arg, const Arithmetic& a) \
3437
+ { \
3438
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, \
3439
+ number<Backend, et_on>, Arithmetic > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3440
+ } \
3441
+ template <class Backend, class Arithmetic> \
3442
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3443
+ is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
3444
+ number<Backend, et_on> > ::type \
3445
+ func(const Arithmetic& arg, number<Backend, et_on>&& a) \
3446
+ { \
3447
+ return detail::expression< \
3448
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3449
+ Arithmetic, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
3450
+ } \
3451
+
3452
+
3453
+ #define UNARY_OP_FUNCTOR(func, category) \
3454
+ namespace detail { \
3455
+ template <class Backend> \
3456
+ struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
3457
+ { \
3458
+ BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const \
3459
+ { \
3460
+ using default_ops::BOOST_JOIN(eval_, func); \
3461
+ BOOST_JOIN(eval_, func) \
3462
+ (result, arg); \
3463
+ } \
3464
+ template <class U> \
3465
+ BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg) const \
3466
+ { \
3467
+ using default_ops::BOOST_JOIN(eval_, func); \
3468
+ Backend temp; \
3469
+ BOOST_JOIN(eval_, func) \
3470
+ (temp, arg); \
3471
+ result = std::move(temp); \
3472
+ } \
3473
+ }; \
3474
+ } \
3475
+ \
3476
+ template <class tag, class A1, class A2, class A3, class A4> \
3477
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category, \
3478
+ detail::expression<detail::function, \
3479
+ detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3480
+ detail::expression<tag, A1, A2, A3, A4> > > ::type \
3481
+ func(const detail::expression<tag, A1, A2, A3, A4>& arg) \
3482
+ { \
3483
+ return detail::expression< \
3484
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3485
+ detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg); \
3486
+ } \
3487
+ template <class Backend> \
3488
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, \
3489
+ detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, number<Backend, et_on> > > ::type \
3490
+ func(const number<Backend, et_on>& arg) \
3491
+ { \
3492
+ return detail::expression< \
3493
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3494
+ number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg); \
3495
+ } \
3496
+ template <class Backend> \
3497
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3498
+ boost::multiprecision::number_category<Backend>::value == category, \
3499
+ number<Backend, et_off> >::type \
3500
+ func(const number<Backend, et_off>& arg) \
3501
+ { \
3502
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
3503
+ number<Backend, et_off> result; \
3504
+ using default_ops::BOOST_JOIN(eval_, func); \
3505
+ BOOST_JOIN(eval_, func)(result.backend(), arg.backend()); \
3506
+ return result; \
3507
+ }\
3508
+ UNARY_OP_FUNCTOR_CXX11_RVALUE(func, category)\
3509
+
3510
+ #define BINARY_OP_FUNCTOR(func, category) \
3511
+ namespace detail { \
3512
+ template <class Backend> \
3513
+ struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
3514
+ { \
3515
+ BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg, const Backend& a) const \
3516
+ { \
3517
+ using default_ops::BOOST_JOIN(eval_, func); \
3518
+ BOOST_JOIN(eval_, func) \
3519
+ (result, arg, a); \
3520
+ } \
3521
+ template <class Arithmetic> \
3522
+ BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg, const Arithmetic& a) const \
3523
+ { \
3524
+ using default_ops::BOOST_JOIN(eval_, func); \
3525
+ BOOST_JOIN(eval_, func) \
3526
+ (result, arg, number<Backend>::canonical_value(a)); \
3527
+ } \
3528
+ template <class Arithmetic> \
3529
+ BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Arithmetic& arg, const Backend& a) const \
3530
+ { \
3531
+ using default_ops::BOOST_JOIN(eval_, func); \
3532
+ BOOST_JOIN(eval_, func) \
3533
+ (result, number<Backend>::canonical_value(arg), a); \
3534
+ } \
3535
+ template <class U> \
3536
+ BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg, const Backend& a) const \
3537
+ { \
3538
+ using default_ops::BOOST_JOIN(eval_, func); \
3539
+ Backend r; \
3540
+ BOOST_JOIN(eval_, func) \
3541
+ (r, arg, a); \
3542
+ result = std::move(r); \
3543
+ } \
3544
+ template <class U, class Arithmetic> \
3545
+ BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg, const Arithmetic& a) const \
3546
+ { \
3547
+ using default_ops::BOOST_JOIN(eval_, func); \
3548
+ Backend r; \
3549
+ BOOST_JOIN(eval_, func) \
3550
+ (r, arg, number<Backend>::canonical_value(a)); \
3551
+ result = std::move(r); \
3552
+ } \
3553
+ template <class U, class Arithmetic> \
3554
+ BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Arithmetic& arg, const Backend& a) const \
3555
+ { \
3556
+ using default_ops::BOOST_JOIN(eval_, func); \
3557
+ Backend r; \
3558
+ BOOST_JOIN(eval_, func) \
3559
+ (r, number<Backend>::canonical_value(arg), a); \
3560
+ result = std::move(r); \
3561
+ } \
3562
+ }; \
3563
+ } \
3564
+ template <class Backend> \
3565
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, detail::expression<detail::function, \
3566
+ detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, number<Backend, et_on>, number<Backend, et_on> > > ::type \
3567
+ func(const number<Backend, et_on>& arg, const number<Backend, et_on>& a) \
3568
+ { \
3569
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3570
+ number<Backend, et_on>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3571
+ } \
3572
+ template <class Backend, class tag, class A1, class A2, class A3, class A4> \
3573
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
3574
+ detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > > ::type \
3575
+ func(const number<Backend, et_on>& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
3576
+ { \
3577
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3578
+ number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3579
+ } \
3580
+ template <class tag, class A1, class A2, class A3, class A4, class Backend> \
3581
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
3582
+ detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > > ::type \
3583
+ func(const detail::expression<tag, A1, A2, A3, A4>& arg, const number<Backend, et_on>& a) \
3584
+ { \
3585
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3586
+ detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3587
+ } \
3588
+ template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b> \
3589
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category) && (number_category<detail::expression<tagb, A1b, A2b, A3b, A4b> >::value == category), \
3590
+ detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3591
+ detail::expression<tag, A1, A2, A3, A4>, detail::expression<tagb, A1b, A2b, A3b, A4b> > > ::type \
3592
+ func(const detail::expression<tag, A1, A2, A3, A4>& arg, const detail::expression<tagb, A1b, A2b, A3b, A4b>& a) \
3593
+ { \
3594
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3595
+ detail::expression<tag, A1, A2, A3, A4>, detail::expression<tagb, A1b, A2b, A3b, A4b> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg, a); \
3596
+ } \
3597
+ template <class Backend, class Arithmetic> \
3598
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3599
+ is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
3600
+ detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3601
+ number<Backend, et_on>, Arithmetic> > ::type \
3602
+ func(const number<Backend, et_on>& arg, const Arithmetic& a) \
3603
+ { \
3604
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, \
3605
+ number<Backend, et_on>, Arithmetic > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3606
+ } \
3607
+ template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
3608
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3609
+ is_compatible_arithmetic_type<Arithmetic, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category), \
3610
+ detail::expression< \
3611
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3612
+ detail::expression<tag, A1, A2, A3, A4>, Arithmetic> > ::type \
3613
+ func(const detail::expression<tag, A1, A2, A3, A4>& arg, const Arithmetic& a) \
3614
+ { \
3615
+ return detail::expression< \
3616
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3617
+ detail::expression<tag, A1, A2, A3, A4>, Arithmetic > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg, a); \
3618
+ } \
3619
+ template <class Backend, class Arithmetic> \
3620
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3621
+ is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
3622
+ detail::expression< \
3623
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3624
+ Arithmetic, number<Backend, et_on> > > ::type \
3625
+ func(const Arithmetic& arg, const number<Backend, et_on>& a) \
3626
+ { \
3627
+ return detail::expression< \
3628
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3629
+ Arithmetic, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
3630
+ } \
3631
+ template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
3632
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3633
+ is_compatible_arithmetic_type<Arithmetic, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category), \
3634
+ detail::expression< \
3635
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3636
+ Arithmetic, detail::expression<tag, A1, A2, A3, A4> > > ::type \
3637
+ func(const Arithmetic& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
3638
+ { \
3639
+ return detail::expression< \
3640
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3641
+ Arithmetic, detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg, a); \
3642
+ } \
3643
+ template <class Backend> \
3644
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category), number<Backend, et_off> >::type \
3645
+ func(const number<Backend, et_off>& arg, const number<Backend, et_off>& a) \
3646
+ { \
3647
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg, a); \
3648
+ number<Backend, et_off> result; \
3649
+ using default_ops::BOOST_JOIN(eval_, func); \
3650
+ BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
3651
+ return result; \
3652
+ } \
3653
+ template <class Backend, class Arithmetic> \
3654
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3655
+ is_compatible_arithmetic_type<Arithmetic, number<Backend, et_off> >::value && (number_category<Backend>::value == category), \
3656
+ number<Backend, et_off> >::type \
3657
+ func(const number<Backend, et_off>& arg, const Arithmetic& a) \
3658
+ { \
3659
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
3660
+ number<Backend, et_off> result; \
3661
+ using default_ops::BOOST_JOIN(eval_, func); \
3662
+ BOOST_JOIN(eval_, func) \
3663
+ (result.backend(), arg.backend(), number<Backend, et_off>::canonical_value(a)); \
3664
+ return result; \
3665
+ } \
3666
+ template <class Backend, class Arithmetic> \
3667
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3668
+ is_compatible_arithmetic_type<Arithmetic, number<Backend, et_off> >::value && (number_category<Backend>::value == category), \
3669
+ number<Backend, et_off> >::type \
3670
+ func(const Arithmetic& a, const number<Backend, et_off>& arg) \
3671
+ { \
3672
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
3673
+ number<Backend, et_off> result; \
3674
+ using default_ops::BOOST_JOIN(eval_, func); \
3675
+ BOOST_JOIN(eval_, func) \
3676
+ (result.backend(), number<Backend, et_off>::canonical_value(a), arg.backend()); \
3677
+ return result; \
3678
+ }\
3679
+ BINARY_OP_FUNCTOR_CXX11_RVALUE(func, category)
3680
+
3681
+ #define HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category) \
3682
+ template <class tag, class A1, class A2, class A3, class A4> \
3683
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3684
+ (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category), \
3685
+ detail::expression< \
3686
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3687
+ detail::expression<tag, A1, A2, A3, A4>, Arg2> > ::type \
3688
+ func(const detail::expression<tag, A1, A2, A3, A4>& arg, Arg2 const& a) \
3689
+ { \
3690
+ return detail::expression< \
3691
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3692
+ detail::expression<tag, A1, A2, A3, A4>, Arg2 > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg, a); \
3693
+ } \
3694
+ template <class Backend> \
3695
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3696
+ (number_category<Backend>::value == category), \
3697
+ detail::expression< \
3698
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3699
+ number<Backend, et_on>, Arg2> > ::type \
3700
+ func(const number<Backend, et_on>& arg, Arg2 const& a) \
3701
+ { \
3702
+ return detail::expression< \
3703
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3704
+ number<Backend, et_on>, Arg2 > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
3705
+ } \
3706
+ template <class Backend> \
3707
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3708
+ (number_category<Backend>::value == category), \
3709
+ number<Backend, et_off> >::type \
3710
+ func(const number<Backend, et_off>& arg, Arg2 const& a) \
3711
+ { \
3712
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg, a); \
3713
+ number<Backend, et_off> result; \
3714
+ using default_ops::BOOST_JOIN(eval_, func); \
3715
+ BOOST_JOIN(eval_, func) \
3716
+ (result.backend(), arg.backend(), a); \
3717
+ return result; \
3718
+ }
3719
+
3720
+ #define HETERO_BINARY_OP_FUNCTOR(func, Arg2, category) \
3721
+ namespace detail { \
3722
+ template <class Backend> \
3723
+ struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
3724
+ { \
3725
+ template <class Arg> \
3726
+ BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, Backend const& arg, Arg a) const \
3727
+ { \
3728
+ using default_ops::BOOST_JOIN(eval_, func); \
3729
+ BOOST_JOIN(eval_, func) \
3730
+ (result, arg, a); \
3731
+ } \
3732
+ template <class U, class Arg> \
3733
+ BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, Backend const& arg, Arg a) const \
3734
+ { \
3735
+ using default_ops::BOOST_JOIN(eval_, func); \
3736
+ Backend temp; \
3737
+ BOOST_JOIN(eval_, func) \
3738
+ (temp, arg, a); \
3739
+ result = std::move(temp); \
3740
+ } \
3741
+ }; \
3742
+ } \
3743
+ \
3744
+ HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)
3745
+
3746
+ // clang-format on
3747
+
3748
+ namespace detail {
3749
+ template <class Backend>
3750
+ struct abs_funct
3751
+ {
3752
+ BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
3753
+ {
3754
+ using default_ops::eval_abs;
3755
+ eval_abs(result, arg);
3756
+ }
3757
+ };
3758
+ template <class Backend>
3759
+ struct conj_funct
3760
+ {
3761
+ BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
3762
+ {
3763
+ using default_ops::eval_conj;
3764
+ eval_conj(result, arg);
3765
+ }
3766
+ //
3767
+ // To allow for mixed complex/scalar arithmetic where conj is called on the scalar type (as in Eigen)
3768
+ // we provide an overload that will promote the arg to the distination type:
3769
+ //
3770
+ template <class Other>
3771
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_constructible<Other, Backend>::value>::type operator()(Other& result, const Backend& arg) const
3772
+ {
3773
+ using default_ops::eval_conj;
3774
+ Other t(arg);
3775
+ eval_conj(result, t);
3776
+ }
3777
+ };
3778
+ template <class Backend>
3779
+ struct proj_funct
3780
+ {
3781
+ BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
3782
+ {
3783
+ using default_ops::eval_proj;
3784
+ eval_proj(result, arg);
3785
+ }
3786
+ };
3787
+
3788
+ } // namespace detail
3789
+
3790
+ template <class tag, class A1, class A2, class A3, class A4>
3791
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex,
3792
+ detail::expression<
3793
+ detail::function, detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> > >::type
3794
+ abs(const detail::expression<tag, A1, A2, A3, A4>& arg)
3795
+ {
3796
+ return detail::expression<
3797
+ detail::function, detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
3798
+ detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
3799
+ }
3800
+ template <class Backend>
3801
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex,
3802
+ detail::expression<
3803
+ detail::function, detail::abs_funct<Backend>, number<Backend, et_on> > >::type
3804
+ abs(const number<Backend, et_on>& arg)
3805
+ {
3806
+ return detail::expression<
3807
+ detail::function, detail::abs_funct<Backend>, number<Backend, et_on> >(
3808
+ detail::abs_funct<Backend>(), arg);
3809
+ }
3810
+ template <class Backend>
3811
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, number<Backend, et_off> >::type
3812
+ abs(const number<Backend, et_off>& arg)
3813
+ {
3814
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
3815
+ number<Backend, et_off> result;
3816
+ using default_ops::eval_abs;
3817
+ eval_abs(result.backend(), arg.backend());
3818
+ return result;
3819
+ }
3820
+
3821
+ template <class tag, class A1, class A2, class A3, class A4>
3822
+ inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3823
+ detail::function, detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >
3824
+ conj(const detail::expression<tag, A1, A2, A3, A4>& arg)
3825
+ {
3826
+ return detail::expression<
3827
+ detail::function, detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
3828
+ detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
3829
+ }
3830
+ template <class Backend>
3831
+ inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3832
+ detail::function, detail::conj_funct<Backend>, number<Backend, et_on> >
3833
+ conj(const number<Backend, et_on>& arg)
3834
+ {
3835
+ return detail::expression<
3836
+ detail::function, detail::conj_funct<Backend>, number<Backend, et_on> >(
3837
+ detail::conj_funct<Backend>(), arg);
3838
+ }
3839
+ template <class Backend>
3840
+ inline BOOST_MP_CXX14_CONSTEXPR number<Backend, et_off>
3841
+ conj(const number<Backend, et_off>& arg)
3842
+ {
3843
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
3844
+ number<Backend, et_off> result;
3845
+ using default_ops::eval_conj;
3846
+ eval_conj(result.backend(), arg.backend());
3847
+ return result;
3848
+ }
3849
+
3850
+ template <class tag, class A1, class A2, class A3, class A4>
3851
+ inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3852
+ detail::function, detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >
3853
+ proj(const detail::expression<tag, A1, A2, A3, A4>& arg)
3854
+ {
3855
+ return detail::expression<
3856
+ detail::function, detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
3857
+ detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
3858
+ }
3859
+ template <class Backend>
3860
+ inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3861
+ detail::function, detail::proj_funct<Backend>, number<Backend, et_on> >
3862
+ proj(const number<Backend, et_on>& arg)
3863
+ {
3864
+ return detail::expression<
3865
+ detail::function, detail::proj_funct<Backend>, number<Backend, et_on> >(
3866
+ detail::proj_funct<Backend>(), arg);
3867
+ }
3868
+ template <class Backend>
3869
+ inline BOOST_MP_CXX14_CONSTEXPR number<Backend, et_off>
3870
+ proj(const number<Backend, et_off>& arg)
3871
+ {
3872
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
3873
+ number<Backend, et_off> result;
3874
+ using default_ops::eval_proj;
3875
+ eval_proj(result.backend(), arg.backend());
3876
+ return result;
3877
+ }
3878
+
3879
+ UNARY_OP_FUNCTOR(fabs, number_kind_floating_point)
3880
+ UNARY_OP_FUNCTOR(sqrt, number_kind_floating_point)
3881
+ UNARY_OP_FUNCTOR(floor, number_kind_floating_point)
3882
+ UNARY_OP_FUNCTOR(ceil, number_kind_floating_point)
3883
+ UNARY_OP_FUNCTOR(trunc, number_kind_floating_point)
3884
+ UNARY_OP_FUNCTOR(round, number_kind_floating_point)
3885
+ UNARY_OP_FUNCTOR(exp, number_kind_floating_point)
3886
+ UNARY_OP_FUNCTOR(exp2, number_kind_floating_point)
3887
+ UNARY_OP_FUNCTOR(log, number_kind_floating_point)
3888
+ UNARY_OP_FUNCTOR(log10, number_kind_floating_point)
3889
+ UNARY_OP_FUNCTOR(cos, number_kind_floating_point)
3890
+ UNARY_OP_FUNCTOR(sin, number_kind_floating_point)
3891
+ UNARY_OP_FUNCTOR(tan, number_kind_floating_point)
3892
+ UNARY_OP_FUNCTOR(asin, number_kind_floating_point)
3893
+ UNARY_OP_FUNCTOR(acos, number_kind_floating_point)
3894
+ UNARY_OP_FUNCTOR(atan, number_kind_floating_point)
3895
+ UNARY_OP_FUNCTOR(cosh, number_kind_floating_point)
3896
+ UNARY_OP_FUNCTOR(sinh, number_kind_floating_point)
3897
+ UNARY_OP_FUNCTOR(tanh, number_kind_floating_point)
3898
+ UNARY_OP_FUNCTOR(log2, number_kind_floating_point)
3899
+ UNARY_OP_FUNCTOR(nearbyint, number_kind_floating_point)
3900
+ UNARY_OP_FUNCTOR(rint, number_kind_floating_point)
3901
+
3902
+ HETERO_BINARY_OP_FUNCTOR(ldexp, short, number_kind_floating_point)
3903
+ //HETERO_BINARY_OP_FUNCTOR(frexp, short*, number_kind_floating_point)
3904
+ HETERO_BINARY_OP_FUNCTOR_B(ldexp, int, number_kind_floating_point)
3905
+ //HETERO_BINARY_OP_FUNCTOR_B(frexp, int*, number_kind_floating_point)
3906
+ HETERO_BINARY_OP_FUNCTOR_B(ldexp, long, number_kind_floating_point)
3907
+ //HETERO_BINARY_OP_FUNCTOR_B(frexp, long*, number_kind_floating_point)
3908
+ HETERO_BINARY_OP_FUNCTOR_B(ldexp, long long, number_kind_floating_point)
3909
+ //HETERO_BINARY_OP_FUNCTOR_B(frexp, long long*, number_kind_floating_point)
3910
+ BINARY_OP_FUNCTOR(pow, number_kind_floating_point)
3911
+ BINARY_OP_FUNCTOR(fmod, number_kind_floating_point)
3912
+ BINARY_OP_FUNCTOR(fmax, number_kind_floating_point)
3913
+ BINARY_OP_FUNCTOR(fmin, number_kind_floating_point)
3914
+ BINARY_OP_FUNCTOR(atan2, number_kind_floating_point)
3915
+ BINARY_OP_FUNCTOR(fdim, number_kind_floating_point)
3916
+ BINARY_OP_FUNCTOR(hypot, number_kind_floating_point)
3917
+ BINARY_OP_FUNCTOR(remainder, number_kind_floating_point)
3918
+
3919
+ UNARY_OP_FUNCTOR(logb, number_kind_floating_point)
3920
+ HETERO_BINARY_OP_FUNCTOR(scalbn, short, number_kind_floating_point)
3921
+ HETERO_BINARY_OP_FUNCTOR(scalbln, short, number_kind_floating_point)
3922
+ HETERO_BINARY_OP_FUNCTOR_B(scalbn, int, number_kind_floating_point)
3923
+ HETERO_BINARY_OP_FUNCTOR_B(scalbln, int, number_kind_floating_point)
3924
+ HETERO_BINARY_OP_FUNCTOR_B(scalbn, long, number_kind_floating_point)
3925
+ HETERO_BINARY_OP_FUNCTOR_B(scalbln, long, number_kind_floating_point)
3926
+ HETERO_BINARY_OP_FUNCTOR_B(scalbn, long long, number_kind_floating_point)
3927
+ HETERO_BINARY_OP_FUNCTOR_B(scalbln, long long, number_kind_floating_point)
3928
+
3929
+ //
3930
+ // Complex functions:
3931
+ //
3932
+ UNARY_OP_FUNCTOR(exp, number_kind_complex)
3933
+ UNARY_OP_FUNCTOR(log, number_kind_complex)
3934
+ UNARY_OP_FUNCTOR(log10, number_kind_complex)
3935
+ BINARY_OP_FUNCTOR(pow, number_kind_complex)
3936
+ UNARY_OP_FUNCTOR(sqrt, number_kind_complex)
3937
+ UNARY_OP_FUNCTOR(sin, number_kind_complex)
3938
+ UNARY_OP_FUNCTOR(cos, number_kind_complex)
3939
+ UNARY_OP_FUNCTOR(tan, number_kind_complex)
3940
+ UNARY_OP_FUNCTOR(asin, number_kind_complex)
3941
+ UNARY_OP_FUNCTOR(acos, number_kind_complex)
3942
+ UNARY_OP_FUNCTOR(atan, number_kind_complex)
3943
+ UNARY_OP_FUNCTOR(sinh, number_kind_complex)
3944
+ UNARY_OP_FUNCTOR(cosh, number_kind_complex)
3945
+ UNARY_OP_FUNCTOR(tanh, number_kind_complex)
3946
+ UNARY_OP_FUNCTOR(asinh, number_kind_complex)
3947
+ UNARY_OP_FUNCTOR(acosh, number_kind_complex)
3948
+ UNARY_OP_FUNCTOR(atanh, number_kind_complex)
3949
+
3950
+ //
3951
+ // Integer functions:
3952
+ //
3953
+ BINARY_OP_FUNCTOR(gcd, number_kind_integer)
3954
+ BINARY_OP_FUNCTOR(lcm, number_kind_integer)
3955
+ HETERO_BINARY_OP_FUNCTOR(pow, unsigned, number_kind_integer)
3956
+
3957
+ #undef BINARY_OP_FUNCTOR
3958
+ #undef UNARY_OP_FUNCTOR
3959
+
3960
+ //
3961
+ // ilogb:
3962
+ //
3963
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
3964
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == number_kind_floating_point, typename Backend::exponent_type>::type
3965
+ ilogb(const multiprecision::number<Backend, ExpressionTemplates>& val)
3966
+ {
3967
+ using default_ops::eval_ilogb;
3968
+ return eval_ilogb(val.backend());
3969
+ }
3970
+
3971
+ template <class tag, class A1, class A2, class A3, class A4>
3972
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == number_kind_floating_point, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type::backend_type::exponent_type>::type
3973
+ ilogb(const detail::expression<tag, A1, A2, A3, A4>& val)
3974
+ {
3975
+ using default_ops::eval_ilogb;
3976
+ typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type arg(val);
3977
+ return eval_ilogb(arg.backend());
3978
+ }
3979
+
3980
+ } //namespace multiprecision
3981
+
3982
+ namespace math {
3983
+
3984
+
3985
+ //
3986
+ // Overload of Boost.Math functions that find the wrong overload when used with number:
3987
+ //
3988
+ namespace detail {
3989
+
3990
+ template <class T>
3991
+ T sinc_pi_imp(T);
3992
+ template <class T, class Policy>
3993
+ T sinhc_pi_imp(T, const Policy&);
3994
+
3995
+ } // namespace detail
3996
+
3997
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
3998
+ inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
3999
+ {
4000
+ boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
4001
+ return detail::sinc_pi_imp(x);
4002
+ }
4003
+
4004
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
4005
+ inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
4006
+ {
4007
+ boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
4008
+ return detail::sinc_pi_imp(x);
4009
+ }
4010
+
4011
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
4012
+ inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
4013
+ {
4014
+ boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
4015
+ return detail::sinhc_pi_imp(x, boost::math::policies::policy<>());
4016
+ }
4017
+
4018
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
4019
+ inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy& pol)
4020
+ {
4021
+ boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x, pol);
4022
+ return detail::sinhc_pi_imp(x, pol);
4023
+ }
4024
+
4025
+ using boost::multiprecision::gcd;
4026
+ using boost::multiprecision::lcm;
4027
+
4028
+ #ifdef BOOST_MSVC
4029
+ #pragma warning(pop)
4030
+ #endif
4031
+ } // namespace math
4032
+
4033
+ namespace integer {
4034
+
4035
+ using boost::multiprecision::gcd;
4036
+ using boost::multiprecision::lcm;
4037
+
4038
+ } // namespace integer
4039
+
4040
+ } // namespace boost
4041
+
4042
+ //
4043
+ // This has to come last of all:
4044
+ //
4045
+ #include <boost/multiprecision/detail/no_et_ops.hpp>
4046
+ #include <boost/multiprecision/detail/et_ops.hpp>
4047
+ //
4048
+ // min/max overloads:
4049
+ //
4050
+ #include <boost/multiprecision/detail/min_max.hpp>
4051
+
4052
+ #endif