Force imaginary part of complex answer to be postive (efficiently)
2 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Sanders A.
el 22 de Abr. de 2022
Comentada: Walter Roberson
el 25 de Abr. de 2022
I am using fsolve to find the complex roots over a very large parameter space (which it is doing quite well). However, I would like the system to only return the positive pair for neatness sake. Which of these would be more efficient to run (yes, I know this is needless optimization, but I have some time while the code runs and thought I would ask)?
if imag(result) < 0
result = result - 2i*imag(result); % option 1
% or
result = real(result) - 1i*imag(result); % option 2
% or
result = complex(real(result), -imag(result)); % option 3
% or ...?
end
If someone who is knowledgeable could explain why each case is faster/slower, that would be really neat to learn!
Thanks!
0 comentarios
Respuesta aceptada
Walter Roberson
el 23 de Abr. de 2022
format long g
S = 10000;
result = complex(randn(S,1), randn(S,1));
N = 100;
t1 = zeros(N,1); t2 = zeros(N,1); t3 = zeros(N,1); t4 = zeros(N,1);
for K = 1 : N; start = tic; newresult = result - 2i*imag(result); t = toc(start); t1(K) = t; end
for K = 1 : N; start = tic; newresult = real(result) - 1i*imag(result); t = toc(start); t2(K) = t; end
for K = 1 : N; start = tic; newresult = complex(real(result), -imag(result)); t = toc(start); t3(K) = t; end
for K = 1 : N; start = tic; newresult = complex(real(result), abs(imag(result))); t = toc(start); t4(K) = t; end
subset = [t1, t2, t3, t4];
subset = subset(11:end,:);
mean(subset, 1)
plot(subset)
legend({'option 1', 'option 2', 'option 3', 'unconditional'})
We can see that using your option 3, complex() is notably faster than your first two options.
The 4th option I put in, also using complex() but also using abs(), is an option that does not require the if first. If you were doing a bunch of these, your three options should all properly be timed inside a loop that did an "if" -- that or should be written in terms of logical masks. But my 4th option using complex() and abs() is just slightly slower than your unconditional complex() ... except the timing for your unconditional complex does not include the tests for negative complex part, so it is rather likely that using the 4th option I show here, and no if, would be faster than testing which entries to convert.
2 comentarios
Walter Roberson
el 25 de Abr. de 2022
The cost of doing the test does indeed add up.
In the below, I used three approaches:
- logical indexing
- for loop with individual tests
- unconditional
The first plot shows the logical indexing together with the unconditional approach. The second plot shows the for loop approach.
You can see that the logical indexing approach is significantly faster than any of the for loop approaches. And you can see that unconditional is the fastest approach.
Also I added an approach using conj(); you can see that it is slower than my unconditional abs() approach, but it is faster than any of the other approaches.
format long g
S = 10000;
result = complex(randn(S,1), rand(S,1));
which = rand(S,1) < 0.1;
result(which) = conj(result(which));
N = 100;
t1 = zeros(N,1); t2 = zeros(N,1); t3 = zeros(N,1); t4 = zeros(N,1);
t1L = zeros(N,1); t2L = zeros(N,1); t3L = zeros(N,1); t4L = zeros(N,1);
t5 = zeros(N,1);
for K = 1 : N; start = tic; newresult = option1(result); t = toc(start); t1(K) = t; end
for K = 1 : N; start = tic; newresult = option2(result); t = toc(start); t2(K) = t; end
for K = 1 : N; start = tic; newresult = option3(result); t = toc(start); t3(K) = t; end
for K = 1 : N; start = tic; newresult = option4(result); t = toc(start); t4(K) = t; end
for K = 1 : N; start = tic; newresult = option1L(result); t = toc(start); t1L(K) = t; end
for K = 1 : N; start = tic; newresult = option2L(result); t = toc(start); t2L(K) = t; end
for K = 1 : N; start = tic; newresult = option3L(result); t = toc(start); t3L(K) = t; end
for K = 1 : N; start = tic; newresult = option4L(result); t = toc(start); t4L(K) = t; end
for K = 1 : N; start = tic; newresult = option5(result); t = toc(start); t5(K) = t; end
subset = [t1, t2, t3, t4, t1L, t2L, t3L, t4L, t5];
subset = subset(11:end,:);
mean(subset, 1).'
subplot(2,1,1)
plot(subset(:,[1:4, end]))
legend({'option 1 mask', 'option 2 mask', 'option 3 mask', 'conj mask', 'unconditional'});
subplot(2,1,2)
plot(subset(:,5:8))
legend({'option 1 loop', 'option 2 loop', 'option 3 loop', 'conj loop'})
function newresult = option1(result)
newresult = result;
mask = imag(result) < 0;
newresult(mask) = result(mask) - 2i*imag(result(mask));
end
function newresult = option2(result)
newresult = result;
mask = imag(result) < 0;
newresult(mask) = real(result(mask)) - 1i*imag(result(mask));
end
function newresult = option3(result)
newresult = result;
mask = imag(result) < 0;
newresult(mask) = complex(real(result(mask)), -imag(result(mask)));
end
function newresult = option4(result)
newresult = result;
mask = imag(result) < 0;
newresult(mask) = conj(result(mask));
end
function newresult = option1L(result)
newresult = result;
for mask = 1 : numel(result)
if imag(result(mask))
newresult(mask) = result(mask) - 2i*imag(result(mask));
end
end
end
function newresult = option2L(result)
newresult = result;
for mask = 1 : numel(result)
if imag(result(mask))
newresult(mask) = real(result(mask)) - 1i*imag(result(mask));
end
end
end
function newresult = option3L(result)
newresult = result;
for mask = 1 : numel(result)
if imag(result(mask))
newresult(mask) = complex(real(result(mask)), -imag(result(mask)));
end
end
end
function newresult = option4L(result)
newresult = result;
for mask = 1 : numel(result)
if imag(result(mask))
newresult(mask) = conj(result(mask));
end
end
end
function newresult = option5(result)
newresult = complex(real(result), abs(imag(result)));
end
Más respuestas (0)
Ver también
Categorías
Más información sobre Verification, Validation, and Test en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!