
#include <complex>
#include <cstdio>

#ifdef WITH_NS_STD
using namespace std;
#endif

#ifdef WITH_EXP_OVERLOAD

std::complex<long double>
exp(const std::complex<long double>& __x)
{
    long double __i = __x.imag();
    if (isinf(__x.real()))
    {
        if (__x.real() < (long double)0)
        {
            if (!isfinite(__i))
                __i = (long double)1;
        }
        else if (__i == 0 || !isfinite(__i))
        {
            if (isinf(__i))
                __i = (long double)NAN;
            return std::complex<long double>(__x.real(), __i);
        }
    }
    else if (isnan(__x.real()) && __x.imag() == 0)
        return __x;
    long double __e = exp(__x.real());
    return std::complex<long double>(__e * cos(__i), __e * sin(__i));
}
#endif

int main()
{
    const std::complex<long double> a = std::complex<long double>(2, 3);
    const std::complex<long double> b = std::complex<long double>(2, 0);
    std::complex<long double> x = std::complex<long double>(-5, 12);

    std::complex<long double> c = pow(a, b);

	printf("c = pow(a,b) = %.20Le + i*%.20Le\n", c.real(), c.imag());
	printf("x            = %.20Le + i*%.20Le\n\n", x.real(), x.imag());
	printf("err = c - x  = %.20Le + i*%.20Le\n\n", (c-x).real(), (c-x).imag());

    std::complex<long double> bw = b*log(a);

    std::complex<long double> d = exp(b*log(a));
    std::complex<long double> dx1 =
    	std::complex<long double>(exp(bw.real()) * cos(bw.imag()),
    		                      exp(bw.real()) * sin(bw.imag()));

	printf("d = exp(b*log(a)) = %.20Le + i*%.20Le\n", d.real(), d.imag());
	printf("dx1               = %.20Le + i*%.20Le\n", dx1.real(), dx1.imag());
	printf("err = d - x       = %.20Le + i*%.20Le\n", (d-x).real(), (d-x).imag());
	printf("err = dx1 - x     = %.20Le + i*%.20Le\n", (dx1-x).real(), (dx1-x).imag());

}
