복소 거듭제곱: cpow(C99)

복소 거듭제곱: cpow(C99)

실수에서 pow(x, y)가 x의 y승을 구하듯, 복소수에도 거듭제곱을 계산하는 함수가 있어요. 그것이 바로 cpow예요. 복소 지수라서 실수의 경우보다 결과가 더 다양하게 나올 수 있고, 분지 절단을 어떻게 두는지도 중요하죠.

출처: cppreference

본문

시그니처

<complex.h> 헤더에 정의돼 있어요.

형태 주석
float complex cpowf ( float complex x, float complex y ); (1) C99부터
double complex cpow ( double complex x, double complex y ); (2) C99부터
long double complex cpowl ( long double complex x, long double complex y ); (3) C99부터
#define pow(x, y) (4) C99부터, <tgmath.h>

동작 방식

복소 거듭제곱 x^y를 계산해요. 첫 번째 인자 x에 대해서는 음의 실수축을 따라 분지 절단을 둡니다.

(4)의 pow는 타입 제네릭 매크로예요. 어느 한 인자가 long double complexcpowl, double complexcpow, float complexcpowf를 호출해요. 두 인자가 모두 실수나 정수면 대응하는 실수 함수(powl, pow, powf)를 호출하고, 어느 인자가 허수 타입이면 복소 버전을 호출해요.

반환값

오류가 없다면 복소 거듭제곱 x^y를 반환해요. 오류와 특수한 경우는 cexp(y * clog(x))로 구현한 것과 똑같이 처리돼요. 다만 구현이 특수한 경우를 더 신중하게 처리하는 것은 허용됩니다.

예제

여러 가지 복소 거듭제곱을 계산해 보는 코드예요.

#include <stdio.h>
#include <complex.h>

int main(void)
{
    double complex z = cpow(1.0+2.0*I, 2);
    printf("(1+2i)^2 = %.1f%+.1fi\n", creal(z), cimag(z));

    double complex z2 = cpow(-1, 0.5);
    printf("(-1+0i)^0.5 = %.1f%+.1fi\n", creal(z2), cimag(z2));

    double complex z3 = cpow(conj(-1), 0.5); // other side of the cut
    printf("(-1-0i)^0.5 = %.1f%+.1fi\n", creal(z3), cimag(z3));

    double complex z4 = cpow(I, I); // i^i = exp(-pi/2)
    printf("i^i = %f%+fi\n", creal(z4), cimag(z4));
}

출력:

(1+2i)^2 = -3.0+4.0i
(-1+0i)^0.5 = 0.0+1.0i
(-1-0i)^0.5 = 0.0-1.0i
i^i = 0.207880+0.000000i

여기서 흥미로운 건 마지막 i^i예요. 수학적으로 i^i = e^(i·ln i) = e^(-π/2)라서 실수값인데, 이 코드에서도 허수부 0인 실수로 잘 나오죠. 또 (-1+0i)^0.5(-1-0i)^0.5는 분지 절단의 양쪽에 있어서 +i-i로 갈리는 것도 볼 수 있어요.

더 알아보기

  • cexp: 복소 지수 함수.
  • clog: 복소 자연로그(cpow가 내부적으로 의존하는 함수).
  • csqrt: 복소 제곱근.
  • pow, powf, powl: 실수 거듭제곱.