| Home | Libraries | People | FAQ | More

#### mpc_complex

`#include <boost/multiprecision/mpc.hpp>`

    namespace boost{ namespace multiprecision{

    template <unsigned Digits10>
    class mpc_complex_backend;

    typedef number<mpc_complex_backend<50> >    mpc_complex_50;
    typedef number<mpc_complex_backend<100> >   mpc_complex_100;
    typedef number<mpc_complex_backend<500> >   mpc_complex_500;
    typedef number<mpc_complex_backend<1000> >  mpc_complex_1000;
    typedef number<mpc_complex_backend<0> >     mpc_complex;

    }} // namespaces

The `mpc_complex_backend` type is used in conjunction with `number`: It acts as a thin wrapper around the MPC `mpc_t` to provide an real-number type that is a drop-in replacement for `std::complex`, but with much greater precision.

Type `mpc_complex_backend` can be used at fixed precision by specifying a non-zero `Digits10` template parameter, or at variable precision by setting the template argument to zero. The typedefs mpc_complex_50, mpc_complex_100, mpc_complex_500, mpc_complex_1000 provide complex types at 50, 100, 500 and 1000 decimal digits precision respectively. The typedef mpc_complex provides a variable precision type whose precision can be controlled via the `number`s member functions.

The `mpc` backend should allow use of the same syntax as the C++ standard library complex type. When using this backend, remember to link with the flags `-lmpc -lmpfr -lgmp`.

As well as the usual conversions from arithmetic and string types, instances of `number<mpc_complex_backend<N> >` are copy constructible and assignable from:

- The GMP native types `mpf_t`, `mpz_t`, `mpq_t`.
- The MPFR native type `mpfr_t`.
- The MPC native type `mpc_t`.
- The `number` wrappers around those types: `number<mpfr_float_backend<M> >`, `number<mpf_float<M> >`, `number<gmp_int>`, `number<gmp_rational>`.

It's also possible to access the underlying `mpc_t` via the `data()` member function of `mpfr_float_backend`.

Things you should know when using this type:

- A default constructed `mpc_complex_backend` is set to zero (Note that this is not the default MPC behavior).
- All operations use round to nearest.
- No changes are made to MPC, GMP or MPFR global settings, so this type can coexist with existing MPC, MPFR or GMP code.
- The code can equally use MPIR in place of GMP - indeed that is the preferred option on Win32.
- This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware.
- Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted as a valid complex number.
- Division by zero results in a complex-infinity.
- Unlike `std::complex`, you can not use `reinterpret_cast` to treat this type as an array of the underlying floating point type.
- Unlike `std::complex`, there are no literals for imaginary values.
- When using the variable precision type `mpc_complex`, then copy construction and assignment copies the precision of the source variable. Likewise move construction and assignment.
- When constructing the variable precision type `mpc_complex` you can specify two arguments to the constructor - the first is the value to assign to the variable, the second is an unsigned integer specifying the precision in decimal places. The `assign` member function similarly has a 2-argument overload taking the value to assign and the precision. You can use this to preserve the precision of the target variable using the somewhat arcane: `a.assign(b, a.precision())`, which assigns `b` to `a` but preserves the precision of `a`.

###### MPC example:

    #include <iostream>
    #include <complex>
    #include <boost/multiprecision/mpc.hpp>

    template<class Complex>
    void complex_number_examples()
    {
        Complex z1{0, 1};
        std::cout << std::setprecision(std::numeric_limits<typename Complex::value_type>::digits10);
        std::cout << std::scientific << std::fixed;
        std::cout << "Print a complex number: " << z1 << std::endl;
        std::cout << "Square it             : " << z1*z1 << std::endl;
        std::cout << "Real part             : " << z1.real() << " = " << real(z1) << std::endl;
        std::cout << "Imaginary part        : " << z1.imag() << " = " << imag(z1) << std::endl;
        using std::abs;
        std::cout << "Absolute value        : " << abs(z1) << std::endl;
        std::cout << "Argument              : " << arg(z1) << std::endl;
        std::cout << "Norm                  : " << norm(z1) << std::endl;
        std::cout << "Complex conjugate     : " << conj(z1) << std::endl;
        std::cout << "Projection onto Riemann sphere: " <<  proj(z1) << std::endl;
        typename Complex::value_type r = 1;
        typename Complex::value_type theta = 0.8;
        using std::polar;
        std::cout << "Polar coordinates (phase = 0)    : " << polar(r) << std::endl;
        std::cout << "Polar coordinates (phase !=0)    : " << polar(r, theta) << std::endl;

        std::cout << "\nElementary special functions:\n";
        using std::exp;
        std::cout << "exp(z1) = " << exp(z1) << std::endl;
        using std::log;
        std::cout << "log(z1) = " << log(z1) << std::endl;
        using std::log10;
        std::cout << "log10(z1) = " << log10(z1) << std::endl;
        using std::pow;
        std::cout << "pow(z1, z1) = " << pow(z1, z1) << std::endl;
        using std::sqrt;
        std::cout << "Take its square root  : " << sqrt(z1) << std::endl;
        using std::sin;
        std::cout << "sin(z1) = " << sin(z1) << std::endl;
        using std::cos;
        std::cout << "cos(z1) = " << cos(z1) << std::endl;
        using std::tan;
        std::cout << "tan(z1) = " << tan(z1) << std::endl;
        using std::asin;
        std::cout << "asin(z1) = " << asin(z1) << std::endl;
        using std::acos;
        std::cout << "acos(z1) = " << acos(z1) << std::endl;
        using std::atan;
        std::cout << "atan(z1) = " << atan(z1) << std::endl;
        using std::sinh;
        std::cout << "sinh(z1) = " << sinh(z1) << std::endl;
        using std::cosh;
        std::cout << "cosh(z1) = " << cosh(z1) << std::endl;
        using std::tanh;
        std::cout << "tanh(z1) = " << tanh(z1) << std::endl;
        using std::asinh;
        std::cout << "asinh(z1) = " << asinh(z1) << std::endl;
        using std::acosh;
        std::cout << "acosh(z1) = " << acosh(z1) << std::endl;
        using std::atanh;
        std::cout << "atanh(z1) = " << atanh(z1) << std::endl;
    }

    int main()
    {
        std::cout << "First, some operations we usually perform with std::complex:\n";
        complex_number_examples<std::complex<double>>();
        std::cout << "\nNow the same operations performed using the MPC backend:\n";
        complex_number_examples<boost::multiprecision::mpc_complex_50>();

        return 0;
    }

Which produces the output (for the multiprecision type):

    Print a complex number: (0.00000000000000000000000000000000000000000000000000,1.00000000000000000000000000000000000000000000000000)
    Square it             : -1.00000000000000000000000000000000000000000000000000
    Real part             : 0.00000000000000000000000000000000000000000000000000 = 0.00000000000000000000000000000000000000000000000000
    Imaginary part        : 1.00000000000000000000000000000000000000000000000000 = 1.00000000000000000000000000000000000000000000000000
    Absolute value        : 1.00000000000000000000000000000000000000000000000000
    Argument              : 1.57079632679489661923132169163975144209858469968755
    Norm                  : 1.00000000000000000000000000000000000000000000000000
    Complex conjugate     : (0.00000000000000000000000000000000000000000000000000,-1.00000000000000000000000000000000000000000000000000)
    Projection onto Riemann sphere: (0.00000000000000000000000000000000000000000000000000,1.00000000000000000000000000000000000000000000000000)
    Polar coordinates (phase = 0)    : 1.00000000000000000000000000000000000000000000000000
    Polar coordinates (phase !=0)    : (0.69670670934716538906374002277244853473117519431538,0.71735609089952279256716781570337728075604730751255)

    Elementary special functions:
    exp(z1) = (0.54030230586813971740093660744297660373231042061792,0.84147098480789650665250232163029899962256306079837)
    log(z1) = (0.00000000000000000000000000000000000000000000000000,1.57079632679489661923132169163975144209858469968755)
    log10(z1) = (0.00000000000000000000000000000000000000000000000000,0.68218817692092067374289181271567788510506374186196)
    pow(z1, z1) = 0.20787957635076190854695561983497877003387784163177
    Take its square root  : (0.70710678118654752440084436210484903928483593768847,0.70710678118654752440084436210484903928483593768847)
    sin(z1) = (0.00000000000000000000000000000000000000000000000000,1.17520119364380145688238185059560081515571798133410)
    cos(z1) = 1.54308063481524377847790562075706168260152911236587
    tan(z1) = (0.00000000000000000000000000000000000000000000000000,0.76159415595576488811945828260479359041276859725794)
    asin(z1) = (0.00000000000000000000000000000000000000000000000000,0.88137358701954302523260932497979230902816032826163)
    acos(z1) = (1.57079632679489661923132169163975144209858469968755,-0.88137358701954302523260932497979230902816032826163)
    atan(z1) = (0.00000000000000000000000000000000000000000000000000,inf)
    sinh(z1) = (0.00000000000000000000000000000000000000000000000000,0.84147098480789650665250232163029899962256306079837)
    cosh(z1) = 0.54030230586813971740093660744297660373231042061792
    tanh(z1) = (0.00000000000000000000000000000000000000000000000000,1.55740772465490223050697480745836017308725077238152)
    asinh(z1) = (0.00000000000000000000000000000000000000000000000000,1.57079632679489661923132169163975144209858469968755)
    acosh(z1) = (0.88137358701954302523260932497979230902816032826163,1.57079632679489661923132169163975144209858469968755)
    atanh(z1) = (0.00000000000000000000000000000000000000000000000000,0.78539816339744830961566084581987572104929234984378)