11

The Matlab documentation says that

For speed and improved robustness, you can replace complex i and j by 1i. For example, instead of using

a = i;

use

a = 1i;

The robustness part is clear, as there might be variables called i or j. However, as for speed, I have made a simple test in Matlab 2010b and I obtain results which seem to contradict the claim:

>>clear all

>> a=0; tic, for n=1:1e8, a=i; end, toc
Elapsed time is 3.056741 seconds.

>> a=0; tic, for n=1:1e8, a=1i; end, toc
Elapsed time is 3.205472 seconds.

Any ideas? Could it be a version-related issue?

After comments by @TryHard and @horchler, I have tried assigning other values to the variable a, with these results:

Increasing order of elapsed time:

"i" < "1i" < "1*i" (trend "A")

"2i" < "2*1i" < "2*i" (trend "B")

"1+1i" < "1+i" < "1+1*i" (trend "A")

"2+2i" < "2+2*1i" < "2+2*i" (trend "B")

Community
  • 1
  • 1
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147

2 Answers2

11

I think you are looking at a pathological example. Try something more complex (results shown for R2012b on OSX):

(repeated addition)

>> clear all
>> a=0; tic, for n=1:1e8, a = a + i; end, toc
Elapsed time is 2.217482 seconds. % <-- slower
>> clear all
>> a=0; tic, for n=1:1e8, a = a + 1i; end, toc
Elapsed time is 1.962985 seconds. % <-- faster

(repeated multiplication)

>> clear all
>> a=0; tic, for n=1:1e8, a = a * i; end, toc
Elapsed time is 2.239134 seconds. % <-- slower
>> clear all
>> a=0; tic, for n=1:1e8, a = a * 1i; end, toc
Elapsed time is 1.998718 seconds. % <-- faster
SheetJS
  • 22,470
  • 12
  • 65
  • 75
  • 14
    "Try something more complex..." -pun intended I hope. :-) – horchler Aug 10 '13 at 16:18
  • It may be as you say. Then, the claim "For speed and improved robustness, you can replace complex i and j by 1i. For example, instead of using a = i; use a = 1i" in the documentation is strictly wrong – Luis Mendo Aug 10 '13 at 16:29
  • 1
    For robustness, the documentation is correct (for example, if you inadvertently run `i=3`, then `a=i` will set 3 but `a=1i` will default to complex `i`), but I agree that it's not clear why they added speed considerations – SheetJS Aug 10 '13 at 18:09
6

One thing to remember is that optimizations are applied differently whether you are running from the command line or a saved M-function.

Here is a test of my own:

function testComplex()
    tic, test1(); toc
    tic, test2(); toc
    tic, test3(); toc
    tic, test4(); toc
    tic, test5(); toc
    tic, test6(); toc
end

function a = test1
    a = zeros(1e7,1);
    for n=1:1e7
        a(n) = 2 + 2i;
    end
end

function a = test2
    a = zeros(1e7,1);
    for n=1:1e7
        a(n) = 2 + 2j;
    end
end
function a = test3
    a = zeros(1e7,1);
    for n=1:1e7
        a(n) = 2 + 2*i;
    end
end

function a = test4
    a = zeros(1e7,1);
    for n=1:1e7
        a(n) = 2 + 2*j;
    end
end

function a = test5
    a = zeros(1e7,1);
    for n=1:1e7
        a(n) = complex(2,2);
    end
end

function a = test6
    a = zeros(1e7,1);
    for n=1:1e7
        a(n) = 2 + 2*sqrt(-1);
    end
end

The results on my Windows machine running R2013a:

>> testComplex
Elapsed time is 0.946414 seconds.    %// 2 + 2i
Elapsed time is 0.947957 seconds.    %// 2 + 2j
Elapsed time is 0.811044 seconds.    %// 2 + 2*i
Elapsed time is 0.685793 seconds.    %// 2 + 2*j
Elapsed time is 0.767683 seconds.    %// complex(2,2)
Elapsed time is 8.193529 seconds.    %// 2 + 2*sqrt(-1)

Note that the results fluctuate a little bit with different runs where the order of calls is shuffled. So take the timings with a grain of salt.

My conclusion: doesn't matter in terms of speed if you use 1i or 1*i.


One interesting difference is that if you also have a variable in the function scope where you also use it as the imaginary unit, MATLAB throws an error:

Error: File: testComplex.m Line: 38 Column: 5
"i" previously appeared to be used as a function or command, conflicting with its
use here as the name of a variable.
A possible cause of this error is that you forgot to initialize the variable, or you
have initialized it implicitly using load or eval.

To see the error, change the above test3 function into:

function a = test3
    a = zeros(1e7,1);
    for n=1:1e7
        a(n) = 2 + 2*i;
    end
    i = rand();        %// added this line!
end

i.e, the variable i was used as both a function and a variable in the same local scope.

Amro
  • 123,847
  • 25
  • 243
  • 454
  • 2
    I bet if you "warm up" those functions before timing them, any differences will disappear into the noise. – horchler Aug 11 '13 at 20:28
  • For me with or without warmup the results were the same: about 0.43 for the first four methods (no significant difference) then 0.58 and 1.2 respectively. Ran it several times and the last two are significantly slower than the first four. – Dennis Jaheruddin Aug 14 '13 at 09:05
  • 3
    true, the way I measured the timing is not very accurate. A better solution is to use [TIMEIT](http://www.mathworks.com/matlabcentral/fileexchange/18798-timeit-benchmarking-function) from the File Exchange, which takes care of warming up the code, running it several times, and averaging the results, all while taking into consideration the overhead of calling functions... You'll be happy to know that the next version of MATLAB (prerelease as of know) includes this function natively! – Amro Aug 14 '13 at 15:11