Multiprecision complex numbers

Contents

Multiprecision complex numbers#

Note

The functionality described in this section is available only if mp++ was configured with the MPPP_WITH_MPC option enabled (see the installation instructions).

Added in version 0.20.

#include <mp++/complex.hpp>

The complex class#

class mppp::complex#

Multiprecision complex class.

This class represents arbitrary-precision complex values as real-imaginary pairs encoded in a binary floating-point format. It acts as a wrapper around the MPC mpc_t type, pairing multiprecision significands (whose size can be set at runtime) to fixed-size exponents. In other words, the real and imaginary parts of complex values can have an arbitrary number of binary digits of precision (limited only by the available memory), but the exponent range is limited. The real and imaginary parts of a complex always have the same precision.

complex aims to behave like a floating-point C++ type whose precision is a runtime property of the class instances rather than a compile-time property of the type. Because of this, the way precision is handled in complex differs from the way it is managed in MPC. The most important difference is that in operations involving complex the precision of the result is usually determined by the precision of the operands, whereas in MPC the precision of the operation is determined by the precision of the return value (which is always passed as the first function parameter in the MPC API). For instance, in the following code,

auto c = complex{5, complex_prec_t(200)} + real{6, complex_prec_t(150)};

the first operand has a value of 5 and precision of 200 bits, while the second operand has a value of 6 and precision 150 bits. The precision of the result c will be the maximum precision among the two operands, that is, 200 bits.

The real and imaginary parts of a complex always have the same precision. The precision of a complex can be set at construction, or it can be changed later via functions such as mppp::complex::set_prec(), mppp::complex::prec_round(), etc. By default, the precision of a complex is automatically deduced upon construction following a set of heuristics aimed at ensuring that the constructed complex preserves the value used for initialisation, if possible. For instance, by default the construction of a complex from a 32 bit integer will yield a complex with a precision of 32 bits. This behaviour can be altered by specifying explicitly the desired precision value.

Most of the functionality is exposed via plain functions, with the general convention that the functions are named after the corresponding MPC functions minus the leading mpc_ prefix. For instance, the MPC call

mpc_add(rop, a, b, MPC_RNDNN);

that writes the result of a + b, rounded to nearest, into rop, becomes simply

add(rop, a, b);

where the add() function is resolved via argument-dependent lookup. Function calls with overlapping arguments are allowed, unless noted otherwise. Unless otherwise specified, the complex API always rounds to nearest (that is, the MPC_RNDNN rounding mode is used).

Various overloaded operators are provided. The arithmetic operators always return a complex result.

Member functions are provided to access directly the internal mpc_t instance (see mppp::complex::get_mpc_t() and mppp::complex::_get_mpc_t()), so that it is possible to use transparently the MPC API with complex objects.

A tutorial showcasing various features of complex is available.

complex()#

Default constructor.

The real and imaginary parts will both be initialised to positive zero, the precision will be the value returned by mppp::real_prec_min().

complex(const complex &other)#
complex(complex &&other) noexcept#

Copy and move constructors.

The copy constructor performs an exact deep copy of the input object.

After move construction, the only valid operations on other are destruction, copy/move assignment and the invocation of the is_valid() member function. After re-assignment, other can be used normally again.

Parameters:

other – the construction argument.

explicit complex(const complex &other, complex_prec_t p)#
explicit complex(complex &&other, complex_prec_t p)#

Copy/move constructors with custom precision.

These constructors will set this to the value of other with precision p. If p is smaller than the precision of other, a rounding operation will be performed, otherwise the value will be copied exactly.

After move construction, the only valid operations on other are destruction, copy/move assignment and the invocation of the is_valid() member function. After re-assignment, other can be used normally again.

Parameters:
  • other – the construction argument.

  • p – the desired precision.

Throws:

std::invalid_argument – if p is outside the range established by mppp::real_prec_min() and mppp::real_prec_max().

template<complex_interoperable T>
complex(T &&x)#
template<complex_interoperable T>
explicit complex(T &&x, complex_prec_t p)#

Generic constructors.

The generic constructors will set this to the value of x.

The variant with the p argument will set the precision of this exactly to p.

The variant without the p argument will set the precision of this according to the following heuristics:

  • if T is real, then the precision is set to the precision of x (as returned by mppp::real::get_prec()),

  • if T is real-valued, then the precision is set following the same heuristics described in the generic constructor of real,

  • if T is complex-valued, then the precision is set to the maximum between the precisions of the real and imaginary parts of x (which are deduced following the same heuristics described in the generic constructor of real).

Parameters:
  • x – the construction argument.

  • p – the desired precision.

Throws:

unspecified – any exception raised by the invoked real constructor.

template<rv_complex_interoperable T, rv_complex_interoperable U>
explicit complex(T &&x, U &&y, complex_prec_t p)#
template<rv_complex_interoperable T, rv_complex_interoperable U>
explicit complex(T &&x, U &&y)#

Generic constructors from real and imaginary parts.

These constructors will set this to \(x+\imath y\).

The variant with the p argument will set the precision of this exactly to p.

Otherwise, the precision of this will be the maximum among the deduced precisions of x and y. The precision deduction rules are the same explained in the generic constructors of real. If x and/or y are real, the deduced precision is the output of mppp::real::get_prec().

Parameters:
  • x – the real part of the value that will be used for the initialisation.

  • y – the imaginary part of the value that will be used for the initialisation.

  • p – the desired precision.

Throws:

unspecified – any exception raised by the invoked real constructor.

template<string_type T>
explicit complex(const T &s, int base, complex_prec_t p)#
template<string_type T>
explicit complex(const T &s, complex_prec_t p)#

Constructors from string, base and precision.

These constructors will initialise this from the string_type s, which is interpreted as a complex number in base base. base must be either zero (in which case the base will be automatically deduced) or a number in the \(\left[ 2,62 \right]\) range. The accepted string formats are:

  • a single floating-point number (e.g., 1.234),

  • a single floating-point number surrounded by round brackets (e.g., (1.234)),

  • a pair of floating-point numbers, surrounded by round brackets and separated by a comma (e.g., (1.234, 4.567)).

The allowed floating-point representations (for both the real and imaginary part) are described in the documentation of the constructor from string of real.

The precision of this will be set to p.

The second constructor calls the first one with a base value of 10.

Parameters:
  • s – the input string.

  • base – the base used in the string representation.

  • p – the desired precision.

Throws:
  • std::invalid_argument – if base is not zero and not in the \(\left[ 2,62 \right]\) range, or s cannot be interpreted as a complex number.

  • unspecified – any exception thrown by the constructor of real from string.

explicit complex(const char *begin, const char *end, int base, complex_prec_t p)#
explicit complex(const char *begin, const char *end, complex_prec_t p)#

Constructors from range of characters, base and precision.

The first constructor will initialise this from the content of the input half-open range, which is interpreted as the string representation of a complex value in base base.

Internally, the constructor will copy the content of the range to a local buffer, add a string terminator, and invoke the constructor from string, base and precision.

The second constructor calls the first one with a base value of 10.

Parameters:
  • begin – the start of the input range.

  • end – the end of the input range.

  • base – the base used in the string representation.

  • p – the desired precision.

Throws:

unspecified – any exception thrown by the constructor from string, or by memory allocation errors in standard containers.

explicit complex(const mpc_t c)#

Constructor from an mpc_t.

This constructor will initialise this with an exact deep copy of c.

Warning

It is the user’s responsibility to ensure that c has been correctly initialised with a precision which is:

Parameters:

c – the mpc_t that will be deep-copied.

explicit complex(mpc_t &&c)#

Move constructor from an mpc_t.

This constructor will initialise this with a shallow copy of c.

Warning

It is the user’s responsibility to ensure that c has been correctly initialised with a precision which is:

Additionally, the user must ensure that, after construction, mpc_clear() is never called on c: the resources previously owned by c are now owned by this, which will take care of releasing them when the destructor is called.

Note

Due to a compiler bug, this constructor is not available on Microsoft Visual Studio.

Parameters:

c – the mpc_t that will be moved.

~complex()#

Destructor.

The destructor will run sanity checks in debug mode.

complex &operator=(const complex &other)#
complex &operator=(complex &&other) noexcept#

Copy and move assignment operators.

Parameters:

other – the assignment argument.

Returns:

a reference to this.

template<complex_interoperable T>
complex &operator=(T &&x)#

The generic assignment operator will set this to the value of x.

The precision of this will be set according to the same heuristics described in the generic constructor.

Parameters:

x – the assignment argument.

Returns:

a reference to this.

Throws:

unspecified – any exception thrown by the generic assignment operator of real.

complex &operator=(const mpc_t c)#

Copy assignment from mpc_t.

This operator will set this to a deep copy of c.

Warning

It is the user’s responsibility to ensure that c has been correctly initialised with a precision which is:

Parameters:

c – the assignment argument.

Returns:

a reference to this.

complex &operator=(mpc_t &&c)#

Move assignment from mpc_t.

This operator will set this to a shallow copy of c.

Warning

It is the user’s responsibility to ensure that c has been correctly initialised with a precision which is:

Additionally, the user must ensure that, after the assignment, mpc_clear() is never called on c: the resources previously owned by c are now owned by this, which will take care of releasing them when the destructor is called.

Note

Due to a compiler bug, this operator is not available on Microsoft Visual Studio.

Parameters:

c – the assignment argument.

Returns:

a reference to this.

bool is_valid() const noexcept#

Check validity.

A complex becomes invalid after it is used as an argument to the move constructor, or after the extraction of the real/imaginary parts via the move overload of get_real_imag().

Returns:

true if this is valid, false otherwise.

complex &set(const complex &other)#

Set to another complex.

This member function will set this to the value of other. Contrary to the copy assignment operator, the precision of the assignment is dictated by the precision of this, rather than the precision of other. Consequently, the precision of this will not be altered by the assignment, and a rounding might occur, depending on the values and the precisions of the operands.

This function is a thin wrapper around the mpc_set() assignment function from the MPC API.

Parameters:

other – the value to which this will be set.

Returns:

a reference to this.

template<complex_interoperable T>
complex &set(const T &x)#

Generic setter.

This member function will set this to the value of x. Contrary to the generic assignment operator, the precision of the assignment is dictated by the precision of this, rather than being deduced from the type and value of x. Consequently, the precision of this will not be altered by the assignment, and a rounding might occur, depending on the operands.

Parameters:

x – the value to which this will be set.

Returns:

a reference to this.

template<string_type T>
complex &set(const T &s, int base = 10)#

Setter to string.

This member function will set this to the value represented by s, which will be interpreted as a complex number in base base (the expected string representations for a complex number are detailed in the documentation of the constructor from string). base must be either 0 (in which case the base is automatically deduced), or a value in the \(\left[ 2,62 \right]\) range. The precision of the assignment is dictated by the precision of this, and a rounding might thus occur.

If s is not a valid representation of a complex number in base base, the real and imaginary parts of this will be set to NaN and an error will be raised.

Parameters:
  • s – the string to which this will be set.

  • base – the base used in the string representation.

Returns:

a reference to this.

Throws:
  • std::invalid_argument – if s cannot be parsed as a complex value, or if the value of base is invalid.

  • unspecified – any exception thrown by memory allocation errors in standard containers.

complex &set(const char *begin, const char *end, int base = 10)#

Set to character range.

This setter will set this to the content of the input half-open range, which is interpreted as the string representation of a complex value in base base.

Internally, the setter will copy the content of the range to a local buffer, add a string terminator, and invoke the setter to string.

Parameters:
  • begin – the start of the input range.

  • end – the end of the input range.

  • base – the base used in the string representation.

Returns:

a reference to this.

Throws:

unspecified – any exception thrown by the setter to string, or by memory allocation errors in standard containers.

complex &set(const mpc_t c)#

Set to an mpc_t.

This member function will set this to the value of c. Contrary to the corresponding assignment operator, the precision of the assignment is dictated by the precision of this, rather than the precision of c. Consequently, the precision of this will not be altered by the assignment, and a rounding might occur, depending on the values and the precisions of the operands.

This function is a thin wrapper around the mpc_set() assignment function from the MPC API.

Warning

It is the user’s responsibility to ensure that c has been correctly initialised with a precision which is:

Parameters:

c – the assignment argument.

Returns:

a reference to this.

complex &set_nan()#

Set to NaN.

This member function will set both the real and imaginary parts of this to NaN.

Returns:

a reference to this.

const mpc_struct_t *get_mpc_t() const#
mpc_struct_t *_get_mpc_t()#

Getters for the internal mpc_t instance.

These member functions will return a const or mutable pointer to the internal mpc_t instance.

Warning

When using the mutable getter, it is the user’s responsibility to ensure that the internal MPC structure is kept in a state which respects the invariants of the complex class. Specifically, the precision value must be the same for the real and imaginary parts and within the bounds established by mppp::real_prec_min() and mppp::real_prec_max(), and upon destruction a complex object must contain a valid mpc_t object.

Returns:

a const or mutable pointer to the internal MPC structure.

bool zero_p() const#
bool inf_p() const#
bool number_p() const#
bool is_one() const#

Detect special values.

These member functions will return true if this is, respectively:

  • zero,

  • a complex infinity (that is, at least one component of this is an infinity),

  • a finite number (that is, both components of this are finite numbers),

  • one,

false otherwise.

Added in version 0.21: The inf_p() and number_p() functions.

Returns:

the result of the detection.

mpfr_prec_t get_prec() const#

Precision getter.

Returns:

the precision of this.

complex &set_prec(mpfr_prec_t p)#

Destructively set the precision

This member function will set the precision of this to exactly p bits. The value of the real and imaginary parts of this will be set to NaN.

Parameters:

p – the desired precision.

Returns:

a reference to this.

Throws:

std::invalid_argument – if p is outside the range established by mppp::real_prec_min() and mppp::real_prec_max().

complex &prec_round(mpfr_prec_t p)#

Set the precision maintaining the current value.

This member function will set the precision of this to exactly p bits. If p is smaller than the current precision of this, a rounding operation will be performed, otherwise the current value will be preserved exactly.

Parameters:

p – the desired precision.

Returns:

a reference to this.

Throws:

std::invalid_argument – if p is outside the range established by mppp::real_prec_min() and mppp::real_prec_max().

template<complex_convertible T>
explicit operator T() const#

Generic conversion operator.

This operator will convert this to T.

Conversion to bool returns false if this is zero, true otherwise.

Conversion to other real-valued complex_convertible types will attempt to convert the real part of this to T via the cast operator of real (unless T is real, in which case a copy of the real part of this will be returned). If the imaginary part of this is nonzero, a domain error will be raised.

Conversion to complex-valued complex_convertible types is also implemented on top of the conversion operator of real.

Returns:

this converted to T.

Throws:
  • std::domain_error – if T is a real-valued type other than bool and the imaginary part of this is not zero.

  • unspecified – any exception raised by the cast operator of real.

template<complex_convertible T>
bool get(T &rop) const#

Generic conversion function.

This member function, similarly to the conversion operator, will convert this to T, storing the result of the conversion into rop. Differently from the conversion operator, this function does not raise any exception: if the conversion is successful, the function will return true, otherwise the function will return false. If the conversion fails, rop will not be altered.

Parameters:

rop – the variable which will store the result of the conversion.

Returns:

true if the conversion succeeded, false otherwise. The conversion can fail in the ways specified in the documentation of the conversion operator.

std::string to_string(int base = 10) const#

Conversion to string.

This member function will convert this to a string representation in base base. The returned string is guaranteed to produce exactly the original value when used in one of the constructors from string of complex (provided that the original precision and base are used in the construction).

Parameters:

base – the base to be used for the string representation.

Returns:

this converted to a string.

Throws:

unspecified – any exception thrown by mppp::real::to_string().

std::size_t get_str_ndigits(int base = 10) const#

Added in version 0.25.

Note

This function is available from MPFR 4.1 onwards.

Minimum number of digits necessary for round-tripping.

This member function will return the minimum number of digits necessary to ensure that the current value of this can be recovered exactly from a string representation in the given base.

Parameters:

base – the base to be used for the string representation.

Returns:

the minimum number of digits necessary for round-tripping.

Throws:

std::invalid_argument – if base is not in the \(\left[ 2,62 \right]\) range.

std::pair<real, real> get_real_imag() const &#
std::pair<real, real> get_real_imag() &&#

Copy or move out the real and imaginary parts.

After the invocation of the second overload, the only valid operations on this are destruction, copy/move assignment and the invocation of the is_valid() member function. After re-assignment, this can be used normally again.

Returns:

a pair containing the real and imaginary parts of this, represented as real objects.

re_cref real_cref() const#
im_cref imag_cref() const#
re_ref real_ref()#
im_ref imag_ref()#

Note

These member functions are available only if at least C++17 is being used.

These member functions facilitate the creation of const or mutable reference wrappers to the real and imaginary parts of this.

See the documentation of re_cref, im_cref, re_ref and im_ref for information on how to use these classes.

Returns:

a const or mutable reference wrapper to the real or imaginary part of this.

complex &neg()#
complex &conj()#
complex &proj()#
complex &abs()#
complex &norm()#
complex &arg()#
complex &sqr()#
complex &mul_i(int s = 0)#
complex &inv()#

Note

The inv() function is available only if mp++ was configured with the MPPP_WITH_FLINT option enabled.

In-place basic aritmetic functions.

These member functions will set this to, respectively:

  • \(-z\),

  • \(\overline{z}\),

  • the projection of \(z\) into Riemann sphere,

  • \(\left| z \right|\),

  • \(\left| z \right|^2\),

  • \(\arg z\),

  • \(z^2\),

  • \(\imath z\) (if \(s\geq 0\)) or \(-\imath z\) (if \(s < 0\)),

  • \(1/z\),

where \(z\) is the current value of this.

The inv() function follows the conventions laid out in Annex G of the C99 standard when this is zero or an infinity.

Added in version 0.21: The inv() function.

Returns:

a reference to this.

Throws:

std::invalid_argument – if the conversion between FLINT and MPC types fails because of (unlikely) overflow conditions.

complex &sqrt()#
complex &rec_sqrt()#

Note

The rec_sqrt() function is available only if mp++ was configured with the MPPP_WITH_FLINT option enabled.

In-place roots.

These member functions will set this to, respectively:

  • \(\sqrt{z}\),

  • \(1 / \sqrt{z}\),

where \(z\) is the current value of this.

The rec_sqrt() function follows the conventions laid out in Annex G of the C99 standard when this is zero or an infinity.

Added in version 0.21: The rec_sqrt() function.

Returns:

a reference to this.

Throws:

std::invalid_argument – if the conversion between FLINT and MPC types fails because of (unlikely) overflow conditions.

complex &exp()#
complex &log()#
complex &log10()#

In-place logarithms and exponentials.

These member functions will set this to, respectively:

  • \(e^z\),

  • \(\log z\),

  • \(\log_{10} z\),

where \(z\) is the current value of this.

Returns:

a reference to this.

complex &sin()#
complex &cos()#
complex &tan()#
complex &asin()#
complex &acos()#
complex &atan()#

In-place (inverse) trigonometric functions.

These member functions will set this to, respectively:

  • \(\sin{z}\),

  • \(\cos{z}\),

  • \(\tan{z}\),

  • \(\arcsin{z}\),

  • \(\arccos{z}\),

  • \(\arctan{z}\),

where \(z\) is the current value of this.

Returns:

a reference to this.

complex &sinh()#
complex &cosh()#
complex &tanh()#
complex &asinh()#
complex &acosh()#
complex &atanh()#

In-place (inverse) hyperbolic functions.

These member functions will set this to, respectively:

  • \(\sinh{z}\),

  • \(\cosh{z}\),

  • \(\tanh{z}\),

  • \(\operatorname{arcsinh}{z}\),

  • \(\operatorname{arccosh}{z}\),

  • \(\operatorname{arctanh}{z}\),

where \(z\) is the current value of this.

Returns:

a reference to this.

complex &agm1()#

Added in version 0.21.

Note

This function is available only if mp++ was configured with the MPPP_WITH_FLINT option enabled.

Arithmetic-geometric mean.

This member function will set this to \(\operatorname{agm}\left( 1, z \right)\), where \(z\) is the current value of this.

Returns:

a reference to this.

Throws:

std::invalid_argument – if the conversion between FLINT and MPC types fails because of (unlikely) overflow conditions.

Types#

type mpc_t#

This is the type used by the MPC library to represent multiprecision complex numbers. It is defined as an array of size 1 of an unspecified structure (see mpc_struct_t).

using mppp::mpc_struct_t = std::remove_extent_t<mpc_t>#

The C structure used by MPC to represent arbitrary-precision complex numbers. The MPC type mpc_t is defined as an array of size 1 of this structure.

enum class mppp::complex_prec_t : mpfr_prec_t#

A strongly-typed counterpart to mpfr_prec_t, used in the constructors of complex in order to avoid ambiguities during overload resolution.

Concepts#

template<typename T>
concept mppp::cvr_complex#

This concept is satisfied if the type T, after the removal of reference and cv qualifiers, is the same as mppp::complex.

template<typename T>
concept mppp::rv_complex_interoperable#

This concept is satisfied if T, after the removal of reference and cv qualifiers, is a real-valued type that can interoperate with complex. Specifically, this concept will be true if T, after the removal of reference and cv qualifiers, is either:

template<typename T>
concept mppp::complex_interoperable#

This concept is satisfied if T, after the removal of reference and cv qualifiers, is a type that can interoperate with complex. Specifically, this concept will be true if T, after the removal of reference and cv qualifiers, is either:

template<typename T>
concept mppp::complex_convertible#

This concept is satisfied if T is a type which a complex can be converted to. Specifically, this concept will be true if T is a complex_interoperable type which is not a reference or cv qualified.

template<typename ...Args>
concept mppp::complex_set_args#

This concept is satisfied if the types in the parameter pack Args can be used as argument types in one of the mppp::complex::set() member function overloads. In other words, this concept is satisfied if the expression

c.set(x, y, z, ...);

is valid (where c is a non-const complex and x, y, z, etc. are const references to the types in Args).

template<typename T, typename U>
concept mppp::complex_eq_op_types#

This concept is satisfied if the types T and U are suitable for use in the equality/inequality operators involving complex. Specifically, the concept will be true if either:

template<typename T, typename U>
concept mppp::complex_op_types#

This concept is satisfied if the types T and U are suitable for use in the generic binary operators and functions involving complex. Specifically, the concept will be true if either:

template<typename T, typename U>
concept mppp::complex_in_place_op_types#

This concept is satisfied if the types T and U are suitable for use in the generic in-place operators involving complex. Specifically, the concept will be true if T and U satisfy complex_op_types and T, after the removal of reference, is not const.

Functions#

Components access#

std::pair<mppp::real, mppp::real> mppp::get_real_imag(const mppp::complex &c)#
std::pair<mppp::real, mppp::real> mppp::get_real_imag(mppp::complex &&c)#

Copy or move out the real and imaginary parts of a complex.

After the invocation of the second overload, the only valid operations on c are destruction, copy/move assignment and the invocation of the is_valid() member function. After re-assignment, c can be used normally again.

Parameters:

c – the input parameter.

Returns:

a pair containing the real and imaginary parts of c, represented as real objects.

class mppp::complex::re_cref#

const reference wrapper for the real part of a complex.

After construction from a complex, an instance of this class can be used to perform read-only operations on the real part of the complex number via the real API.

Here’s a typical usage pattern:

complex c{1, 2};

{
   // Place the re_cref object in a new scope
   // in order to minimise its lifetime.
   complex::re_cref re{c};

   // We can use 're' as-if it was a pointer
   // to an mppp::real.
   std::cout << "The real part of c is " << *re << '\n';
   std::cout << "Is the real part of c one? " << re->is_one() << '\n';
}

Because re_cref shares data with a complex, special care should be taken in order to avoid undefined behaviour. In particular:

  • the lifetime of a re_cref is tied to the lifetime of the complex from which it was constructed. Thus, a re_cref must always be destroyed before the destruction of the complex from which it was constructed;

  • during the lifetime of a re_cref, only const operations on the complex from which it was constructed are allowed.

The easiest way to avoid mistakes is to follow these guidelines:

  • create a re_cref object in a new scope,

  • in the new scope, don’t perform non-const operations on the complex from which the re_cref object was created,

  • exit the new scope as soon as you are finished interacting with the re_cref object.

When using at least C++17, the creation of a re_cref can also be accomplished via the mppp::complex::real_cref() and mppp::real_cref() functions (which slightly reduce the amount of typing).

explicit re_cref(const complex &c)#

Constructor.

This is the only constructor available for a re_cref object. It will create a reference to the real part of c.

Parameters:

c – the input complex.

re_cref(const re_cref&) = delete#
re_cref(re_cref&&) = delete#
re_cref &operator=(const re_cref&) = delete#
re_cref &operator=(re_cref&&) = delete#

re_cref cannot be copied or moved.

const real &operator*() const#
const real *operator->() const#

Dereference and arrow operators.

These operators allow to interact with a re_cref as-if it was a const pointer to a real object.

Returns:

a const reference/pointer to a real object.

class mppp::complex::im_cref#

const reference wrapper for the imaginary part of a complex.

The API is identical to re_cref.

class mppp::complex::re_ref#

Mutable reference wrapper for the real part of a complex.

After construction from a complex, an instance of this class can be used to perform non-const operations on the real part of the complex number via the real API.

Here’s a typical usage pattern:

complex c{1, 2};

{
   // Place the re_ref object in a new scope
   // in order to minimise its lifetime.
   complex::re_ref re{c};

   // We can use 're' as-if it was a pointer
   // to an mppp::real.
   *re += 5;
}

std::cout << "c is now: " << c << '\n'; // Will print '(6.000..., 2.000...)'.

On construction, re_ref takes ownership of the real part of a complex. On destruction, re_ref will automatically transfer its content back to the real part of the complex from which it was constructed. In order to avoid misuses, it is thus important to keep the following in mind:

  • the lifetime of a re_ref is tied to the lifetime of the complex from which it was constructed. Thus, a re_ref must always be destroyed before the destruction of the complex from which it was constructed;

  • during the lifetime of a re_ref, neither const nor mutable operations can be performed on the complex from which it was constructed. The only exception to this rule is that it is allowed to create an im_cref or an im_ref to the complex (so that it is possible to operate on both the real and imaginary parts of a complex at the same time);

  • it is the user’s responsibility to ensure that any modification to the precision of the real part is propagated to the imaginary part of the complex (so that the complex class invariant dictating that the real and imaginary parts must always have the same precision is preserved).

The easiest way to avoid mistakes is to follow these guidelines:

  • create a re_ref object in a new scope,

  • in the new scope, never reuse the complex from which the re_ref object was created. The only exception is that you can create an im_cref or an im_ref to the same complex;

  • ensure that any modification to the precision of the real part is propagated to the imaginary part;

  • exit the new scope as soon as you are finished interacting with the re_ref object.

When using at least C++17, the creation of a re_ref can also be accomplished via the mppp::complex::real_ref() and mppp::real_ref() functions (which slightly reduce the amount of typing).

explicit re_ref(complex &c)#

Constructor.

This is the only constructor available for a re_ref object. It will take ownership of the real part of a complex.

Parameters:

c – the input complex.

re_ref(const re_ref&) = delete#
re_ref(re_ref&&) = delete#
re_ref &operator=(const re_ref&) = delete#
re_ref &operator=(re_ref&&) = delete#

re_ref cannot be copied or moved.

~re_ref()#

The destructor will transfer the (possibly modified) real part back to the complex from which the re_ref object was created.

real &operator*()#
real *operator->()#

Dereference and arrow operators.

These operators allow to interact with a re_ref as-if it was a pointer to a real object.

Returns:

a reference/pointer to a real object.

class mppp::complex::im_ref#

Mutable reference wrapper for the imaginary part of a complex.

The API is identical to re_ref.

mppp::complex::re_cref mppp::real_cref(const mppp::complex &c)#
mppp::complex::im_cref mppp::imag_cref(const mppp::complex &c)#
mppp::complex::re_ref mppp::real_ref(mppp::complex &c)#
mppp::complex::im_ref mppp::imag_ref(mppp::complex &c)#

Note

These functions are available only if at least C++17 is being used.

These functions facilitate the creation of const or mutable reference wrappers to the real and imaginary parts of c.

See the documentation of re_cref, im_cref, re_ref and im_ref for information on how to use these classes.

Parameters:

c – the input parameter.

Returns:

a const or mutable reference wrapper to the real or imaginary part of c.

Precision handling#

mpfr_prec_t mppp::get_prec(const mppp::complex &c)#

Get the precision of a complex.

Parameters:

c – the input argument.

Returns:

the precision of c.

void mppp::set_prec(mppp::complex &c, mpfr_prec_t p)#
void mppp::prec_round(mppp::complex &c, mpfr_prec_t p)#

Set the precision of a complex.

The first variant will set the precision of c to exactly p bits. The value of c will be set to NaN.

The second variant will preserve the current value of c, performing a rounding operation if p is less than the current precision of c.

Parameters:
  • c – the input argument.

  • p – the desired precision.

Throws:

unspecified – any exception thrown by mppp::complex::set_prec() or mppp::complex::prec_round().

Assignment#

template<mppp::complex_set_args... Args>
mppp::complex &mppp::set(mppp::complex &c, const Args&... args)#

Generic setter.

This function will use the arguments args to set the value of the complex c, using one of the available mppp::complex::set() overloads. That is, the body of this function is equivalent to

return c.set(args...);

The input arguments must satisfy the mppp::complex_set_args concept.

Parameters:
Returns:

a reference to c.

Throws:

unspecified – any exception thrown by the invoked mppp::complex::set() overload.

mppp::complex &mppp::set_nan(mppp::complex &c)#

Set to NaN.

This function will set both the real and imaginary parts of c to NaN.

Parameters:

c – the input argument.

Returns:

a reference to c.

mppp::complex &mppp::set_rootofunity(mppp::complex &c, unsigned long n, unsigned long k)#

Set to a power of the standard primitive n-th root of unity.

This function will set c to \(e^{2\pi\imath k/n}\). The precision of c will not be altered.

Parameters:
  • c – the input argument.

  • n – the root order.

  • k – the exponent.

void mppp::swap(mppp::complex &a, mppp::complex &b) noexcept#

Swap efficiently a and b.

Parameters:
  • a – the first argument.

  • b – the second argument.

Conversion#

template<mppp::complex_convertible T>
bool mppp::get(T &rop, const mppp::complex &c)#

Generic conversion function.

This function will convert the input complex c to T, storing the result of the conversion into rop. If the conversion is successful, the function will return true, otherwise the function will return false. If the conversion fails, rop will not be altered.

Parameters:
  • rop – the variable which will store the result of the conversion.

  • c – the input argument.

Returns:

true if the conversion succeeded, false otherwise. The conversion can fail in the ways specified in the documentation of the conversion operator for complex.

std::size_t mppp::get_str_ndigits(const mppp::complex &c, int base = 10)#

Added in version 0.25.

Note

This function is available from MPFR 4.1 onwards.

Minimum number of digits necessary for round-tripping.

This member function will return the minimum number of digits necessary to ensure that the current value of c can be recovered exactly from a string representation in the given base.

Parameters:
  • c – the input value.

  • base – the base to be used for the string representation.

Returns:

the minimum number of digits necessary for round-tripping.

Throws:

std::invalid_argument – if base is not in the \(\left[ 2,62 \right]\) range.

Arithmetic#

template<mppp::cvr_complex T, mppp::cvr_complex U>
mppp::complex &mppp::add(mppp::complex &rop, T &&a, U &&b)#
template<mppp::cvr_complex T, mppp::cvr_complex U>
mppp::complex &mppp::sub(mppp::complex &rop, T &&a, U &&b)#
template<mppp::cvr_complex T, mppp::cvr_complex U>
mppp::complex &mppp::mul(mppp::complex &rop, T &&a, U &&b)#
template<mppp::cvr_complex T, mppp::cvr_complex U>
mppp::complex &mppp::div(mppp::complex &rop, T &&a, U &&b)#

Basic complex binary arithmetic.

These functions will set rop to, respectively:

  • \(a+b\),

  • \(a-b\),

  • \(a \times b\),

  • \(\frac{a}{b}\).

The precision of the result will be set to the largest precision among the operands.

Parameters:
  • rop – the return value.

  • a – the first operand.

  • b – the second operand.

Returns:

a reference to rop.

template<mppp::cvr_complex T, mppp::cvr_complex U, mppp::cvr_complex V>
mppp::complex &mppp::fma(mppp::complex &rop, T &&a, U &&b, V &&c)#

Quaternary complex multiply-add.

This function will set rop to \(a \times b + c\).

The precision of the result will be set to the largest precision among the operands.

Parameters:
  • rop – the return value.

  • a – the first operand.

  • b – the second operand.

  • c – the third operand.

Returns:

a reference to rop.

template<mppp::cvr_complex T, mppp::cvr_complex U, mppp::cvr_complex V>
mppp::complex mppp::fma(T &&a, U &&b, V &&c)#

Ternary complex multiply-add.

This function will return \(a \times b + c\).

The precision of the result will be the largest precision among the operands.

Parameters:
  • a – the first operand.

  • b – the second operand.

  • c – the third operand.

Returns:

\(a \times b + c\).

template<mppp::cvr_complex T>
mppp::complex &mppp::neg(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::conj(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::proj(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::sqr(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::mul_i(mppp::complex &rop, T &&z, int s = 0)#
template<mppp::cvr_complex T>
mppp::complex &mppp::inv(mppp::complex &rop, T &&z)#
mppp::real &mppp::abs(mppp::real &rop, const mppp::complex &z)#
mppp::real &mppp::norm(mppp::real &rop, const mppp::complex &z)#
mppp::real &mppp::arg(mppp::real &rop, const mppp::complex &z)#

Note

The inv() function is available only if mp++ was configured with the MPPP_WITH_FLINT option enabled.

Basic binary arithmetic functions.

These functions will set rop to, respectively:

  • \(-z\),

  • \(\overline{z}\),

  • the projection of \(z\) into Riemann sphere,

  • \(z^2\),

  • \(\imath z\) (if \(s\geq 0\)) or \(-\imath z\) (if \(s < 0\)),

  • \(1/z\),

  • \(\left| z \right|\),

  • \(\left| z \right|^2\),

  • \(\arg z\).

The precision of the result will be equal to the precision of z.

The inv() function follows the conventions laid out in Annex G of the C99 standard when z is zero or an infinity.

Added in version 0.21: The inv() function.

Parameters:
  • rop – the return value.

  • z – the argument.

Returns:

a reference to rop.

Throws:

std::invalid_argument – if the conversion between FLINT and MPC types fails because of (unlikely) overflow conditions.

template<mppp::cvr_complex T>
mppp::complex mppp::neg(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::conj(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::proj(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::sqr(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::mul_i(T &&z, int s = 0)#
template<mppp::cvr_complex T>
mppp::complex mppp::inv(T &&z)#
mppp::real mppp::abs(const mppp::complex &z)#
mppp::real mppp::norm(const mppp::complex &z)#
mppp::real mppp::arg(const mppp::complex &z)#

Note

The inv() function is available only if mp++ was configured with the MPPP_WITH_FLINT option enabled.

Basic unary arithmetic functions.

These functions will return, respectively:

  • \(-z\),

  • \(\overline{z}\),

  • the projection of \(z\) into Riemann sphere,

  • \(z^2\),

  • \(\imath z\) (if \(s\geq 0\)) or \(-\imath z\) (if \(s < 0\)),

  • \(1/z\),

  • \(\left| z \right|\),

  • \(\left| z \right|^2\),

  • \(\arg z\).

The precision of the result will be equal to the precision of z.

The inv() function follows the conventions laid out in Annex G of the C99 standard when z is zero or an infinity.

Added in version 0.21: The inv() function.

Parameters:

z – the argument.

Returns:

the result of the operation.

Throws:

std::invalid_argument – if the conversion between FLINT and MPC types fails because of (unlikely) overflow conditions.

template<mppp::cvr_complex T>
mppp::complex &mppp::mul_2ui(mppp::complex &rop, T &&c, unsigned long n)#
template<mppp::cvr_complex T>
mppp::complex &mppp::mul_2si(mppp::complex &rop, T &&c, long n)#
template<mppp::cvr_complex T>
mppp::complex &mppp::div_2ui(mppp::complex &rop, T &&c, unsigned long n)#
template<mppp::cvr_complex T>
mppp::complex &mppp::div_2si(mppp::complex &rop, T &&c, long n)#

Ternary complex primitives for multiplication/division by powers of 2.

These functions will set rop to, respectively:

  • \(c \times 2^n\) (mul_2 variants),

  • \(\frac{c}{2^n}\) (div_2 variants).

The precision of the result will be equal to the precision of c.

Parameters:
  • rop – the return value.

  • c – the operand.

  • n – the power of 2.

Returns:

a reference to rop.

template<mppp::cvr_complex T>
mppp::complex mppp::mul_2ui(T &&c, unsigned long n)#
template<mppp::cvr_complex T>
mppp::complex mppp::mul_2si(T &&c, long n)#
template<mppp::cvr_complex T>
mppp::complex mppp::div_2ui(T &&c, unsigned long n)#
template<mppp::cvr_complex T>
mppp::complex mppp::div_2si(T &&c, long n)#

Binary complex primitives for multiplication/division by powers of 2.

These functions will return, respectively:

  • \(c \times 2^n\) (mul_2 variants),

  • \(\frac{c}{2^n}\) (div_2 variants).

The precision of the result will be equal to the precision of c.

Parameters:
  • c – the operand.

  • n – the power of 2.

Returns:

c multiplied/divided by \(2^n\).

Comparison#

int mppp::cmpabs(const mppp::complex &a, const mppp::complex &b)#

Three-way comparison of absolute values.

This function will compare a and b, returning:

  • zero if \(\left|a\right|=\left|b\right|\),

  • a negative value if \(\left|a\right|<\left|b\right|\),

  • a positive value if \(\left|a\right|>\left|b\right|\).

If at least one NaN component is involved in the comparison, an error will be raised.

Parameters:
  • a – the first operand.

  • b – the second operand.

Returns:

an integral value expressing how the absolute values of a and b compare.

Throws:

std::domain_error – if at least one of the components of a and b is NaN.

bool mppp::zero_p(const mppp::complex &c)#
bool mppp::inf_p(const mppp::complex &c)#
bool mppp::number_p(const mppp::complex &c)#
bool mppp::is_one(const mppp::complex &c)#

Detect special values.

These functions will return true if c is, respectively:

  • zero,

  • a complex infinity (that is, at least one component of c is an infinity),

  • a finite number (that is, both components of c are finite numbers),

  • one,

false otherwise.

Added in version 0.21: The inf_p() and number_p() functions.

Parameters:

c – the input argument.

Returns:

the result of the detection.

Roots#

template<mppp::cvr_complex T>
mppp::complex &mppp::sqrt(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::rec_sqrt(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::rootn_ui(mppp::complex &rop, T &&z, unsigned long k)#

Note

The rec_sqrt() and rootn_ui() functions are available only if mp++ was configured with the MPPP_WITH_FLINT option enabled.

Binary complex roots.

These functions will set rop to, respectively:

  • \(\sqrt{z}\),

  • \(1 / \sqrt{z}\),

  • \(\sqrt[k]{z}\).

The precision of the result will be equal to the precision of z.

The rec_sqrt() function follows the conventions laid out in Annex G of the C99 standard when z is zero or an infinity.

The rootn_ui() function computes the principal k-th root of z. If k is zero, rop will be set to NaN.

Added in version 0.21: The rec_sqrt() and rootn_ui() functions.

Parameters:
  • rop – the return value.

  • z – the operand.

  • k – the degree of the root.

Returns:

a reference to rop.

Throws:

std::invalid_argument – if the conversion between FLINT and MPC types fails because of (unlikely) overflow conditions.

template<mppp::cvr_complex T>
mppp::complex mppp::sqrt(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::rec_sqrt(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::rootn_ui(T &&z, unsigned long k)#

Note

The rec_sqrt() and rootn_ui() functions are available only if mp++ was configured with the MPPP_WITH_FLINT option enabled.

Unary complex roots.

These functions will return, respectively:

  • \(\sqrt{z}\),

  • \(1 / \sqrt{z}\),

  • \(\sqrt[k]{z}\).

The precision of the result will be equal to the precision of z.

The rec_sqrt() function follows the conventions laid out in Annex G of the C99 standard when z is zero or an infinity.

The rootn_ui() function computes the principal k-th root of z. If k is zero, rop will be set to NaN.

Added in version 0.21: The rec_sqrt() and rootn_ui() functions.

Parameters:
  • z – the operand.

  • k – the degree of the root.

Returns:

the result of the operation.

Throws:

std::invalid_argument – if the conversion between FLINT and MPC types fails because of (unlikely) overflow conditions.

Exponentiation#

template<mppp::cvr_complex T, mppp::cvr_complex U>
mppp::complex &mppp::pow(mppp::complex &rop, T &&op1, U &&op2)#

Ternary exponentiation.

This function will set rop to op1 raised to the power of op2. The precision of rop will be set to the largest precision among the operands.

Parameters:
  • rop – the return value.

  • op1 – the base.

  • op2 – the exponent.

Returns:

a reference to rop.

template<typename T, mppp::complex_op_types<T> U>
mppp::complex mppp::pow(T &&op1, U &&op2)#

Binary exponentiation.

This function will compute and return op1 raised to the power of op2. The precision of the result will be set to the largest precision among the operands.

Parameters:
  • op1 – the base.

  • op2 – the exponent.

Returns:

op1 raised to the power of op2.

Trigonometry#

template<mppp::cvr_complex T>
mppp::complex &mppp::sin(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::cos(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::tan(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::asin(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::acos(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::atan(mppp::complex &rop, T &&z)#

Binary basic (inverse) trigonometric functions.

These functions will set rop to, respectively:

  • \(\sin{z}\),

  • \(\cos{z}\),

  • \(\tan{z}\),

  • \(\arcsin{z}\),

  • \(\arccos{z}\),

  • \(\arctan{z}\).

The precision of the result will be equal to the precision of z.

Parameters:
  • rop – the return value.

  • z – the argument.

Returns:

a reference to rop.

template<mppp::cvr_complex T>
mppp::complex mppp::sin(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::cos(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::tan(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::asin(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::acos(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::atan(T &&z)#

Unary basic (inverse) trigonometric functions.

These functions will return, respectively:

  • \(\sin{z}\),

  • \(\cos{z}\),

  • \(\tan{z}\),

  • \(\arcsin{z}\),

  • \(\arccos{z}\),

  • \(\arctan{z}\).

The precision of the result will be equal to the precision of z.

Parameters:

z – the argument.

Returns:

the trigonometric function of z.

template<mppp::cvr_complex T>
void mppp::sin_cos(mppp::complex &sop, mppp::complex &cop, T &&op)#

Simultaneous sine and cosine.

This function will set sop and cop respectively to the sine and cosine of op. sop and cop must be distinct objects. The precision of sop and rop will be set to the precision of op.

Parameters:
  • sop – the sine return value.

  • cop – the cosine return value.

  • op – the operand.

Throws:

std::invalid_argument – if sop and cop are the same object.

Hyperbolic functions#

template<mppp::cvr_complex T>
mppp::complex &mppp::sinh(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::cosh(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::tanh(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::asinh(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::acosh(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::atanh(mppp::complex &rop, T &&z)#

Binary basic (inverse) hyperbolic functions.

These functions will set rop to, respectively:

  • \(\sinh{z}\),

  • \(\cosh{z}\),

  • \(\tanh{z}\),

  • \(\operatorname{arcsinh}{z}\),

  • \(\operatorname{arccosh}{z}\),

  • \(\operatorname{arctanh}{z}\).

The precision of the result will be equal to the precision of z.

Parameters:
  • rop – the return value.

  • z – the argument.

Returns:

a reference to rop.

template<mppp::cvr_complex T>
mppp::complex mppp::sinh(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::cosh(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::tanh(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::asinh(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::acosh(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::atanh(T &&z)#

Unary basic (inverse) hyperbolic functions.

These functions will return, respectively:

  • \(\sinh{z}\),

  • \(\cosh{z}\),

  • \(\tanh{z}\),

  • \(\operatorname{arcsinh}{z}\),

  • \(\operatorname{arccosh}{z}\),

  • \(\operatorname{arctanh}{z}\).

The precision of the result will be equal to the precision of z.

Parameters:

z – the argument.

Returns:

the hyperbolic function of z.

Logarithms and exponentials#

template<mppp::cvr_complex T>
mppp::complex &mppp::exp(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::log(mppp::complex &rop, T &&z)#
template<mppp::cvr_complex T>
mppp::complex &mppp::log10(mppp::complex &rop, T &&z)#

Binary complex logarithms and exponentials.

These functions will set rop to, respectively:

  • \(e^z\),

  • \(\log z\),

  • \(\log_{10} z\).

The precision of the result will be equal to the precision of z.

Parameters:
  • rop – the return value.

  • z – the operand.

Returns:

a reference to rop.

template<mppp::cvr_complex T>
mppp::complex mppp::exp(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::log(T &&z)#
template<mppp::cvr_complex T>
mppp::complex mppp::log10(T &&z)#

Unary complex logarithms and exponentials.

These functions will return, respectively:

  • \(e^z\),

  • \(\log z\),

  • \(\log_{10} z\).

The precision of the result will be equal to the precision of z.

Parameters:

z – the argument.

Returns:

the result of the operation.

Arithmetic-geometric mean#

template<mppp::cvr_complex T>
mppp::complex &mppp::agm1(mppp::complex &rop, T &&x)#
template<mppp::cvr_complex T, mppp::cvr_complex U>
mppp::complex &mppp::agm(mppp::complex &rop, T &&x, U &&y)#

Added in version 0.21.

Note

These functions are available only if mp++ was configured with the MPPP_WITH_FLINT option enabled.

complex AGM functions.

These functions will set rop to, respectively:

  • \(\operatorname{agm}\left( 1, x \right)\),

  • \(\operatorname{agm}\left( x, y \right)\).

The precision of rop will be set to the largest precision among the operands.

Parameters:
  • rop – the return value.

  • x – the first operand.

  • y – the second operand.

Returns:

a reference to rop.

Throws:

std::invalid_argument – if the conversion between FLINT and MPC types fails because of (unlikely) overflow conditions.

template<mppp::cvr_complex T>
mppp::complex mppp::agm1(T &&x)#
template<typename T, mppp::complex_op_types<T> U>
mppp::complex mppp::agm(T &&x, U &&y)#

Added in version 0.21.

Note

These functions are available only if mp++ was configured with the MPPP_WITH_FLINT option enabled.

complex AGM functions.

These functions will return, respectively:

  • \(\operatorname{agm}\left( 1, x \right)\),

  • \(\operatorname{agm}\left( x, y \right)\).

The precision of the result will be equal to the highest precision among the operands.

Parameters:
  • x – the first operand.

  • y – the second operand.

Returns:

the result of the operation.

Throws:

std::invalid_argument – if the conversion between FLINT and MPC types fails because of (unlikely) overflow conditions.

Input/Output#

std::ostream &mppp::operator<<(std::ostream &os, const mppp::complex &c)#

Output stream operator.

This function will direct to the output stream os the input complex c.

Parameters:
  • os – the target stream.

  • c – the input argument.

Returns:

a reference to os.

Throws:
  • std::overflow_error – in case of (unlikely) overflow errors.

  • std::invalid_argument – if the MPFR printing primitive mpfr_asprintf() returns an error code.

  • unspecified – any exception raised by the public interface of std::ostream or by memory allocation errors.

Mathematical operators#

template<mppp::cvr_complex T>
mppp::complex mppp::operator+(T &&c)#
template<mppp::cvr_complex T>
mppp::complex mppp::operator-(T &&c)#

Identity and negation operators.

Parameters:

c – the input argument.

Returns:

\(c\) and \(-c\) respectively.

template<typename T, mppp::complex_op_types<T> U>
mppp::complex mppp::operator+(T &&a, U &&b)#
template<typename T, mppp::complex_op_types<T> U>
mppp::complex mppp::operator-(T &&a, U &&b)#
template<typename T, mppp::complex_op_types<T> U>
mppp::complex mppp::operator*(T &&a, U &&b)#
template<typename T, mppp::complex_op_types<T> U>
mppp::complex mppp::operator/(T &&a, U &&b)#

Binary arithmetic operators.

The precision of the result will be set to the largest precision among the operands.

Parameters:
  • a – the first operand.

  • b – the second operand.

Returns:

the result of the binary operation.

template<typename U, mppp::complex_in_place_op_types<U> T>
T &mppp::operator+=(T &a, U &&b)#
template<typename U, mppp::complex_in_place_op_types<U> T>
T &mppp::operator-=(T &a, U &&b)#
template<typename U, mppp::complex_in_place_op_types<U> T>
T &mppp::operator*=(T &a, U &&b)#
template<typename U, mppp::complex_in_place_op_types<U> T>
T &mppp::operator/=(T &a, U &&b)#

In-place arithmetic operators.

If a is a complex, then these operators are equivalent, respectively, to the expressions:

a = a + b;
a = a - b;
a = a * b;
a = a / b;

Otherwise, these operators are equivalent to the expressions:

a = static_cast<T>(a + b);
a = static_cast<T>(a - b);
a = static_cast<T>(a * b);
a = static_cast<T>(a / b);
Parameters:
  • a – the first operand.

  • b – the second operand.

Returns:

a reference to a.

Throws:

unspecified – any exception thrown by the generic conversion operator of complex.

mppp::complex &mppp::operator++(mppp::complex &c)#
mppp::complex &mppp::operator--(mppp::complex &c)#

Prefix increment/decrement.

Parameters:

c – the input argument.

Returns:

a reference to c after the increment/decrement.

mppp::complex mppp::operator++(mppp::complex &c, int)#
mppp::complex mppp::operator--(mppp::complex &c, int)#

Suffix increment/decrement.

Parameters:

c – the input argument.

Returns:

a copy of c before the increment/decrement.

template<typename T, mppp::complex_eq_op_types<T> U>
bool mppp::operator==(const T &a, const U &b)#
template<typename T, mppp::complex_eq_op_types<T> U>
bool mppp::operator!=(const T &a, const U &b)#

Comparison operators.

These operators will compare a and b, returning true if, respectively, \(a=b\) and \(a \neq b\), and false otherwise.

The comparisons are always exact (i.e., no rounding is involved).

These operators handle NaN in the same way specified by the IEEE floating-point standard.

Parameters:
  • a – the first operand.

  • b – the second operand.

Returns:

the result of the comparison.

User-defined literals#

template<char... Chars>
mppp::complex mppp::literals::operator""_icr128()#
template<char... Chars>
mppp::complex mppp::literals::operator""_icr256()#
template<char... Chars>
mppp::complex mppp::literals::operator""_icr512()#
template<char... Chars>
mppp::complex mppp::literals::operator""_icr1024()#

User-defined arbitrary-precision imaginary literals.

These numeric literal operator templates can be used to construct purely imaginary complex instances with, respectively, 128, 256, 512 and 1024 bits of precision. The real part of the return value will be set to zero, while the imaginary part will be set to the input floating-point literal. Literals in decimal and hexadecimal format are supported.

Throws:

std::invalid_argument – if the input sequence of characters is not a valid floating-point literal (as defined by the C++ standard).