Complex numbers
Enoki provides a vectorizable type for complex number arithmetic analogous to
std::complex<T>. To use it, include the following header file:
#include <enoki/complex.h>
Usage
The following example shows how to define and perform basic arithmetic using
enoki::Complex vectorized over 4-wide packets.
/* Declare underlying packet type, could just be 'float' for scalar arithmetic */
using FloatP = Packet<float, 4>;
/* Define complex number type */
using ComplexP = Complex<FloatP>;
const ComplexP I(0.f, 1.f);
const ComplexP z(0.2f, 0.3f);
/* Two different ways of computing the tangent function */
ComplexP t0 = (exp(I * z) - exp(-I * z)) / (I * (exp(I * z) + exp(-I * z)));
ComplexP t1 = tan(z);
std::cout << "t0 = " << t0 << std::endl << std::endl;
std::cout << "t1 = " << t1 << std::endl;
/* Prints
t0 = [0.184863 + 0.302229i,
0.184863 + 0.302229i,
0.184863 + 0.302229i,
0.184863 + 0.302229i]
t1 = [0.184863 + 0.302229i,
0.184863 + 0.302229i,
0.184863 + 0.302229i,
0.184863 + 0.302229i]
*/
Reference
-
template<typename
Type>
class Complex : StaticArrayImpl<Type, 2>
The class enoki::Complex is a 2D Enoki array whose components
are of type Type. Various arithmetic operators (e.g. multiplication)
and transcendental functions are overloaded so that they provide the
correct behavior for complex-valued inputs.
-
Complex(Type real, Type imag)
Creates a enoki::Complex instance from the given real and
imaginary inputs.
-
Complex(Type f)
Creates a real-valued enoki::Complex instance from f.
This constructor effectively changes the broadcasting behavior of
non-complex inputs—for instance, the snippet
auto value_a = zero<Array<float, 2>>();
auto value_c = zero<Complex<float>>();
value_a += 1.f; value_c += 1.f;
std::cout << "value_a = "<< value_a << ", value_c = " << value_c << std::endl;
prints value_a = [1, 1], value_c = 1 + 0i, which is the desired
behavior for complex numbers. For standard Enoki arrays, the number
1.f is broadcast to both components.
Elementary operations
-
template<typename
T>
T real(Complex<T> z)
Extracts the real part of z.
-
template<typename
T>
T imag(Complex<T> z)
Extracts the imaginary part of z.
-
template<typename
T>
Complex<T> arg(Complex<T> z)
Evaluates the complex argument of z.
-
template<typename
T>
Complex<T> abs(Complex<T> z)
Compute the absolute value of z.
-
template<typename
T>
Complex<T> sqrt(Complex<T> z)
Compute the square root of z.
-
template<typename
T>
Complex<T> conj(Complex<T> z)
Evaluates the complex conjugate of z.
-
template<typename
T>
Complex<T> rcp(Complex<T> z)
Evaluates the complex reciprocal of z.
Arithmetic operators
Only a few arithmetic operators need to be overridden to support complex
arithmetic. The rest are automatically provided by Enoki’s existing operators
and broadcasting rules.
-
template<typename
T>
Complex<T> operator*(Complex<T> z0, Complex<T> z1)
Evaluates the complex product of z1 and z2.
-
template<typename
T>
Complex<T> operator/(Complex<T> z0, Complex<T> z1)
Evaluates the complex division of z1 and z2.
Stream operators
-
std::ostream &
operator<<(std::ostream &os, const Complex<T> &z)
Sends the complex number z to the stream os using the format
1 + 2i.
Exponential, logarithm, and power function
-
template<typename
T>
Complex<T> exp(Complex<T> z)
Evaluates the complex exponential of z.
-
template<typename
T>
Complex<T> log(Complex<T> z)
Evaluates the complex logarithm of z.
-
template<typename
T>
Complex<T> pow(Complex<T> z0, Complex<T> z1)
Evaluates the complex power of z0 raised to the z1.
Trigonometric functions
-
template<typename
T>
Complex<T> sin(Complex<T> z)
Evaluates the complex sine function for z.
-
template<typename
T>
Complex<T> cos(Complex<T> z)
Evaluates the complex cosine function for z.
-
template<typename
T>
Complex<T> tan(Complex<T> z)
Evaluates the complex tangent function for z.
-
template<typename
T>
std::pair<Complex<T>, Complex<T>> sincos(Complex<T> z)
Jointly evaluates the complex sine and cosine function for z.
-
template<typename
T>
Complex<T> asin(Complex<T> z)
Evaluates the complex arc sine function for z.
-
template<typename
T>
Complex<T> acos(Complex<T> z)
Evaluates the complex arc cosine function for z.
-
template<typename
T>
Complex<T> atan(Complex<T> z)
Evaluates the complex arc tangent function for z.
Hyperbolic functions
-
template<typename
T>
Complex<T> sinh(Complex<T> z)
Evaluates the complex hyperbolic sine function for z.
-
template<typename
T>
Complex<T> cosh(Complex<T> z)
Evaluates the complex hyperbolic cosine function for z.
-
template<typename
T>
Complex<T> tanh(Complex<T> z)
Evaluates the complex hyperbolic tangent function for z.
-
template<typename
T>
std::pair<Complex<T>, Complex<T>> sincosh(Complex<T> z)
Jointly evaluates the complex hyperbolic sine and cosine function for z.
-
template<typename
T>
Complex<T> asinh(Complex<T> z)
Evaluates the complex hyperbolic arc sine function for z.
-
template<typename
T>
Complex<T> acosh(Complex<T> z)
Evaluates the complex hyperbolic arc cosine function for z.
-
template<typename
T>
Complex<T> atanh(Complex<T> z)
Evaluates the complex hyperbolic arc tangent function for z.
Miscellaneous functions
-
std::pair<T, T>
sincos_arg_diff(const Complex<T> &z1, const Complex<T> &z2)
Efficiently evaluates sin(arg(z1) - arg(z2)) and cos(arg(z1) - arg(z2)).
-
template<typename
T>
Complex<T> sqrtz(T x)
Compute the complex square root of a real-valued argument x (which may
be negative). This is considerably more efficient than the general complex
square root above.