99 lines
6.0 KiB
Plaintext
99 lines
6.0 KiB
Plaintext
[/
|
|
Copyright 2011 - 2020 John Maddock.
|
|
Copyright 2013 - 2019 Paul A. Bristow.
|
|
Copyright 2013 Christopher Kormanyos.
|
|
|
|
Distributed under the Boost Software License, Version 1.0.
|
|
(See accompanying file LICENSE_1_0.txt or copy at
|
|
http://www.boost.org/LICENSE_1_0.txt).
|
|
]
|
|
|
|
[section:cpp_complex cpp_complex]
|
|
|
|
`#include <boost/multiprecision/cpp_complex.hpp>`
|
|
|
|
namespace boost{ namespace multiprecision{
|
|
|
|
template <unsigned Digits, backends::digit_base_type DigitBase = backends::digit_base_10, class Allocator = void, class Exponent = int, Exponent MinExponent = 0, Exponent MaxExponent = 0>
|
|
using cpp_complex_backend = complex_adaptor<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> >;
|
|
|
|
template <unsigned Digits, backends::digit_base_type DigitBase = digit_base_10, class Allocator = void, class Exponent = int, Exponent MinExponent = 0, Exponent MaxExponent = 0, expression_template_option ExpressionTemplates = et_off>
|
|
using cpp_complex = number<complex_adaptor<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> >, ExpressionTemplates>;
|
|
|
|
typedef cpp_complex<50> cpp_complex_50;
|
|
typedef cpp_complex<100> cpp_complex_100;
|
|
|
|
typedef cpp_complex<24, backends::digit_base_2, void, std::int16_t, -126, 127> cpp_complex_single;
|
|
typedef cpp_complex<53, backends::digit_base_2, void, std::int16_t, -1022, 1023> cpp_complex_double;
|
|
typedef cpp_complex<64, backends::digit_base_2, void, std::int16_t, -16382, 16383> cpp_complex_extended;
|
|
typedef cpp_complex<113, backends::digit_base_2, void, std::int16_t, -16382, 16383> cpp_complex_quad;
|
|
typedef cpp_complex<237, backends::digit_base_2, void, std::int32_t, -262142, 262143> cpp_complex_oct;
|
|
|
|
|
|
}} // namespaces
|
|
|
|
The `cpp_complex_backend` back-end is used in conjunction with `number`: It acts as an entirely C++ (header only and dependency free)
|
|
complex number type that is a drop-in replacement for `std::complex`, but with much greater precision.
|
|
|
|
The template alias `cpp_complex` avoids the need to use class `number` directly.
|
|
|
|
Type `cpp_complex` can be used at fixed precision by specifying a non-zero `Digits` template parameter.
|
|
The typedefs `cpp_complex_50` and `cpp_complex_100` provide complex number types at 50 and 100 decimal digits precision
|
|
respectively.
|
|
|
|
Optionally, you can specify whether the precision is specified in decimal digits or binary bits - for example
|
|
to declare a `cpp_complex` with exactly the same precision as `std::complex<double>` one would use
|
|
`cpp_complex<53, digit_base_2>`. The typedefs `cpp_complex_single`, `cpp_complex_double`,
|
|
`cpp_complex_quad`, `cpp_complex_oct` and `cpp_complex_double_extended` provide
|
|
software analogues of the IEEE single, double, quad and octuple float data types, plus the Intel-extended-double type respectively.
|
|
Note that while these types are functionally equivalent to the native IEEE types, but they do not have the same size
|
|
or bit-layout as true IEEE compatible types.
|
|
|
|
Normally `cpp_complex` allocates no memory: all of the space required for its digits are allocated
|
|
directly within the class. As a result care should be taken not to use the class with too high a digit count
|
|
as stack space requirements can grow out of control. If that represents a problem then providing an allocator
|
|
as a template parameter causes `cpp_complex` to dynamically allocate the memory it needs: this
|
|
significantly reduces the size of `cpp_complex` and increases the viable upper limit on the number of digits
|
|
at the expense of performance. However, please bear in mind that arithmetic operations rapidly become ['very] expensive
|
|
as the digit count grows: the current implementation really isn't optimized or designed for large digit counts.
|
|
Note that since the actual type of the objects allocated
|
|
is completely opaque, the suggestion would be to use an allocator with `char` `value_type`, for example:
|
|
`cpp_complex<1000, digit_base_10, std::allocator<char> >`.
|
|
|
|
The next template parameters determine the type and range of the exponent: parameter `Exponent` can be
|
|
any signed integer type, but note that `MinExponent` and `MaxExponent` can not go right up to the limits
|
|
of the `Exponent` type as there has to be a little extra headroom for internal calculations. You will
|
|
get a compile time error if this is the case. In addition if MinExponent or MaxExponent are zero, then
|
|
the library will choose suitable values that are as large as possible given the constraints of the type
|
|
and need for extra headroom for internal calculations.
|
|
|
|
Finally, as with class `number`, the final template parameter determines whether expression templates are turn
|
|
on or not. Since by default this type allocates no memory, expression template support is off by default.
|
|
However, you should probably turn it on if you specify an allocator.
|
|
|
|
There is full standard library support available for this type, comparable with what `std::complex` provides.
|
|
|
|
Things you should know when using this type:
|
|
|
|
* Default constructed `cpp_complex`s have a value of zero.
|
|
* The radix of this type is 2, even when the precision is specified as decimal digits.
|
|
* The type supports both infinities and NaNs. An infinity is generated whenever the result would overflow,
|
|
and a NaN is generated for any mathematically undefined operation.
|
|
* There is no `std::numeric_limits` specialisation for this type: this is the same behaviour as `std::complex`. If you need
|
|
`std::numeric_limits` support you need to look at `std::numeric_limits<my_complex_number_type::value_type>`.
|
|
* Any `number` instantiated on this type, is convertible to any other `number` instantiated on this type -
|
|
for example you can convert from `number<cpp_complex<50> >` to `number<cpp_bin_float<SomeOtherValue> >`.
|
|
Narrowing conversions round to nearest and are `explicit`.
|
|
* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
|
|
as a valid complex number.
|
|
|
|
[h5 example:]
|
|
|
|
[cpp_complex_eg]
|
|
|
|
Which produces the output (for the multiprecision type):
|
|
|
|
[cpp_complex_out]
|
|
|
|
[endsect] [/section:complex Complex Number Types]
|