Wait, but what's e^N?

CJam, 22 - 15 = 7


Try it online here

Takes input in the form of a b where a is the real component and b is the complex.

For ex. 2i is

0 2



80386 Assembly (41 bytes - 15 = 26)

8B 4C 24 04 8B 54 24 08 D9 EA DC 09 D9 C0 D9 FC DC E9 D9 C9 D9 F0 D9 E8 DE C1 D9 FD DD 02 D9 FB D8 CA DD 19 D8 C9 DD 1A C3

Floating point math in assembly is a pain..

This is a function (cdecl calling convention) that calculates e^(a+bi) via the relation e^(a+bi)=e^a cos b + e^a sin b * i. (It accepts two double * parameters, a and b in that order, and outputs the real part into the a pointer, and the imaginary part into the b pointer).

The function prototype in C would be:

void __attribute__((cdecl)) exp_complex(double *a, double *b);

About half (20, to be exact) of the 41 bytes were spent calculating e^a; another 8 were spent getting the function arguments into registers.

The above bytecode was written by hand, from the following assembly (NASM-style, commented):

; get pointers into ecx, edx
mov ecx, [esp+4] ; 8B 4C 24 04
mov edx, [esp+8] ; 8B 54 24 08

; log(2,e)
fldl2e           ; D9 EA
; a log(2,e)
fmul qword [ecx] ; DC 09
; duplicate
fld st0          ; D9 C0
; get integer part
frndint          ; D9 FC
; get fractional part
fsub st1, st0    ; DC E9
; put fractional part on top
fxch st1         ; D9 C9
; 2^(fract(a log(2,e))) - 1
f2xm1            ; D9 F0
; 2^(fract(a log(2,e)))
fld1             ; D9 E8
faddp st1        ; DE C1
; 2^(fract(a log(2,e))) * 2^(int(a log(2,e)))
; = e^a
fscale           ; D9 FD

; push b
fld qword [edx]  ; DD 02
; sin and cos
fsincos          ; D9 FB
; e^a cos b
fmul st2         ; D8 CA
; output as real part
fstp qword [ecx] ; DD 19
; e^a sin b
fmul st1         ; D8 C9
; output as imaginary part
fstp qword [edx] ; DD 1A

; exit
ret              ; C3

To try this in C (gcc, linux, intel processor):

#include <stdio.h>
#include <string.h>
#include <sys/mman.h>

int main(){
    // bytecode from earlier
    char code[] = {
        0x8B, 0x4C, 0x24, 0x04, 0x8B, 0x54, 0x24, 0x08,
        0xD9, 0xEA, 0xDC, 0x09, 0xD9, 0xC0, 0xD9, 0xFC,
        0xDC, 0xE9, 0xD9, 0xC9, 0xD9, 0xF0, 0xD9, 0xE8,
        0xDE, 0xC1, 0xD9, 0xFD, 0xDD, 0x02, 0xD9, 0xFB,
        0xD8, 0xCA, 0xDD, 0x19, 0xD8, 0xC9, 0xDD, 0x1A,
    // allocate executable memory to a function pointer called 'exp_complex'
    void __attribute__( (__cdecl__) ) (*exp_complex)(double *,double *) = mmap(0,sizeof code,PROT_WRITE|PROT_EXEC,MAP_ANON|MAP_PRIVATE,-1,0);
    memcpy(exp_complex, code, sizeof code);

    // test inputs
    double a = 42.24, b = -2.7182818;

    printf("%.07g + %.07g i\n", a, b);

    // call bytecode as a c function
    exp_complex(&a, &b);

    printf("%.07g + %.07g i\n", a, b);

    // release allocated memory
    munmap(exp_complex, sizeof code);

    return 0;

Mathematica, 23 20 bytes - 15 = 5


This is an anonymous function taking two arguments (real and imaginary component). You should supply floats unless you want exact result (with square roots and exponentials). So you can use this like


Note that I is Mathematica's imaginary unit, but I'm not actually using any complex arithmetic. Also note, that Mathematica will actually print the result using a (double-struck) lowercase i as required. See the screenshot in belisarius's comment.