1

I have just started using boost::multiprecision trying to speed up some calculations previously done in Matlab. I found quite an unexpected problem, though. My calculations involve complex numbers, so I am using cpp_complex_50 type (e.g. cpp_complex_50 A, B;)

At some point I need to use boost::math::tools::bracket_and_solve_root() function, which requires that the function it works on returns real values. Here comes my problem... I cannot convert my complex multiprecision variable A.real() to any type that is real, eg. to cpp_dec_float_50 type or even double. The task should be streightforward, but I am virtually drowned in error complaints from my compiler (MSVC2015), and cannot solve it. Any hints at how to convert the data are more than welcome.

A somewhat connected question is the problem of initialization of cpp_complex_50 type variables with real values. At the moment I can only use data of type double at initialization, which means I am loosing some accuracy at the initialization stage already, e.g.:

cpp_complex_50 A = 4.0 * boost::math::constants::pi<double>(); // it works

but

cpp_complex_50 A = 4.0 * boost::math::constants::pi<cpp_dec_float_50>(); // It does NOT work

Any hints are needed. I am stuck at this, despite nice initial results.

Regards

Pawel

Pawel
  • 11
  • 1
  • Does `cpp_complex_50 A = 4*boost::math::constants::pi();` work? – user14717 Mar 09 '21 at 18:23
  • Also, does returning the real part of a complex number actually make sense in the context of your calculation? It's generally a bit odd to try to find the root of a real part of a complex function . . . – user14717 Mar 09 '21 at 18:24
  • No. It does not work. The code... 'cpp_complex_50 A = 4*boost::math::constants::pi()' does not work trigerring a lithany of error messages from the compiler. The constant pi must be double -- then it works with no problems. – Pawel Mar 09 '21 at 20:21
  • Well, it does make sense, in my opinion. You can separately display the real and the imaginary part of a complex number: ``` cpp_complex_50 A; // some initialization so that A is non-zero cout << A.real() << endl; cout << A.imag() << endl; ``` A.real() is already real and if it get displayed as a real number of specified precision there should not be problems with explicitely assigning this value to some variable of a real type (e.g. cpp_dec_float_50 or even double). Problem is that I cannot achieve this which is irritating, so say the least. – Pawel Mar 09 '21 at 20:32

2 Answers2

1

cpp_complex uses cpp_bin_float.

Live On Compiler Explorer

#include <boost/multiprecision/cpp_complex.hpp>
#include <iostream>

namespace bmp = boost::multiprecision;

int main() {
    using Complex = bmp::cpp_complex_100;
    using Real    = Complex::value_type;

    Real r = 4.0 * boost::math::constants::pi<Real>();

    Complex b(r, {});
    // or
    b = r.convert_to<Complex>();

    std::cout << b.str(100) << std::endl;
}

Prints

12.56637061435917295385057353311801153678867759750042328389977836923126562514483599451213930136846827

sehe
  • 374,641
  • 47
  • 450
  • 633
  • See also, perhaps related https://stackoverflow.com/a/31061421/85371 – sehe Mar 09 '21 at 22:43
  • Thank you. The hint that cpp_complex uses cpp_bin_float (and not cpp_dec_float like in my initial code) helped me. A code: cpp_complex_50 A = ...; // some initialization cpp_bin_float_50 B = A.real(); works without problems. – Pawel Mar 10 '21 at 10:20
  • Of course. I just worded it in more generic terms so your code is less brittle when you change details – sehe Mar 10 '21 at 13:01
0

Following valuable comment from sehe... the code

cpp_complex_50 A = 4.0 * boost::math::constants::pi<cpp_bin_float_50>();
cout << A << endl;

works, producing:

12.5663706143591729538505735331180115367886775975

Similarely,

cpp_bin_float_50 B = A.real();
cout << B << endl;

works as well, printing the same.

Pawel
  • 11
  • 1