tangent tangent correlation calculation in matrix form MATLAB












1















Consider the following calculation of the tangent tangent correlation which is performed in a for loop



v1=rand(25,1);
v2=rand(25,1);
n=25;
nSteps=10;
mean_theta = zeros(nSteps,1);
for j=1:nSteps
theta=;
for i=1:(n-j)
d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
n1 = norm([v1(i) v2(i)]);
n2 = norm([v1(i+j) v2(i+j)]);
theta = [theta acosd(d/n1/n2)];

end
mean_theta(j)=mean(theta);
end
plot(mean_theta)


How can matlab matrix calculations be utilized to make this performance better?










share|improve this question























  • Do you have the Econometrics toolbox? If so you can have a look at autocorr, which calculates the auto correlation. You should be able to adapt it to calculate the tangent tangent correlation instead. When I say adapt, I mean create a new similar function, not changing the existing one.

    – Nicky Mattsson
    Nov 26 '18 at 13:28








  • 1





    For starters, growing arrays, like you do with theta is very, very, very bad for MATLAB performance. Just preallocate it to the correct size (that's known in this case, although variable per iteration) and you'll save a lot of time already.

    – Adriaan
    Nov 26 '18 at 13:28











  • @NickyMattsson, I'd like to stick with what matlab has to offer without the toolboxes.

    – jarhead
    Nov 26 '18 at 13:54











  • @Adriaan, if you can post an answer with specifying how my example is bad for matlab and how you propose to write it differently, it would be great and will also benefit others.

    – jarhead
    Nov 26 '18 at 13:55






  • 1





    @jarhead see this question. I'm not going to write an answer, as preallocating is too evident imo, as it should always be done. No value there.

    – Adriaan
    Nov 26 '18 at 15:20


















1















Consider the following calculation of the tangent tangent correlation which is performed in a for loop



v1=rand(25,1);
v2=rand(25,1);
n=25;
nSteps=10;
mean_theta = zeros(nSteps,1);
for j=1:nSteps
theta=;
for i=1:(n-j)
d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
n1 = norm([v1(i) v2(i)]);
n2 = norm([v1(i+j) v2(i+j)]);
theta = [theta acosd(d/n1/n2)];

end
mean_theta(j)=mean(theta);
end
plot(mean_theta)


How can matlab matrix calculations be utilized to make this performance better?










share|improve this question























  • Do you have the Econometrics toolbox? If so you can have a look at autocorr, which calculates the auto correlation. You should be able to adapt it to calculate the tangent tangent correlation instead. When I say adapt, I mean create a new similar function, not changing the existing one.

    – Nicky Mattsson
    Nov 26 '18 at 13:28








  • 1





    For starters, growing arrays, like you do with theta is very, very, very bad for MATLAB performance. Just preallocate it to the correct size (that's known in this case, although variable per iteration) and you'll save a lot of time already.

    – Adriaan
    Nov 26 '18 at 13:28











  • @NickyMattsson, I'd like to stick with what matlab has to offer without the toolboxes.

    – jarhead
    Nov 26 '18 at 13:54











  • @Adriaan, if you can post an answer with specifying how my example is bad for matlab and how you propose to write it differently, it would be great and will also benefit others.

    – jarhead
    Nov 26 '18 at 13:55






  • 1





    @jarhead see this question. I'm not going to write an answer, as preallocating is too evident imo, as it should always be done. No value there.

    – Adriaan
    Nov 26 '18 at 15:20
















1












1








1








Consider the following calculation of the tangent tangent correlation which is performed in a for loop



v1=rand(25,1);
v2=rand(25,1);
n=25;
nSteps=10;
mean_theta = zeros(nSteps,1);
for j=1:nSteps
theta=;
for i=1:(n-j)
d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
n1 = norm([v1(i) v2(i)]);
n2 = norm([v1(i+j) v2(i+j)]);
theta = [theta acosd(d/n1/n2)];

end
mean_theta(j)=mean(theta);
end
plot(mean_theta)


How can matlab matrix calculations be utilized to make this performance better?










share|improve this question














Consider the following calculation of the tangent tangent correlation which is performed in a for loop



v1=rand(25,1);
v2=rand(25,1);
n=25;
nSteps=10;
mean_theta = zeros(nSteps,1);
for j=1:nSteps
theta=;
for i=1:(n-j)
d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
n1 = norm([v1(i) v2(i)]);
n2 = norm([v1(i+j) v2(i+j)]);
theta = [theta acosd(d/n1/n2)];

end
mean_theta(j)=mean(theta);
end
plot(mean_theta)


How can matlab matrix calculations be utilized to make this performance better?







matlab matrix-multiplication






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 26 '18 at 13:06









jarheadjarhead

68641436




68641436













  • Do you have the Econometrics toolbox? If so you can have a look at autocorr, which calculates the auto correlation. You should be able to adapt it to calculate the tangent tangent correlation instead. When I say adapt, I mean create a new similar function, not changing the existing one.

    – Nicky Mattsson
    Nov 26 '18 at 13:28








  • 1





    For starters, growing arrays, like you do with theta is very, very, very bad for MATLAB performance. Just preallocate it to the correct size (that's known in this case, although variable per iteration) and you'll save a lot of time already.

    – Adriaan
    Nov 26 '18 at 13:28











  • @NickyMattsson, I'd like to stick with what matlab has to offer without the toolboxes.

    – jarhead
    Nov 26 '18 at 13:54











  • @Adriaan, if you can post an answer with specifying how my example is bad for matlab and how you propose to write it differently, it would be great and will also benefit others.

    – jarhead
    Nov 26 '18 at 13:55






  • 1





    @jarhead see this question. I'm not going to write an answer, as preallocating is too evident imo, as it should always be done. No value there.

    – Adriaan
    Nov 26 '18 at 15:20





















  • Do you have the Econometrics toolbox? If so you can have a look at autocorr, which calculates the auto correlation. You should be able to adapt it to calculate the tangent tangent correlation instead. When I say adapt, I mean create a new similar function, not changing the existing one.

    – Nicky Mattsson
    Nov 26 '18 at 13:28








  • 1





    For starters, growing arrays, like you do with theta is very, very, very bad for MATLAB performance. Just preallocate it to the correct size (that's known in this case, although variable per iteration) and you'll save a lot of time already.

    – Adriaan
    Nov 26 '18 at 13:28











  • @NickyMattsson, I'd like to stick with what matlab has to offer without the toolboxes.

    – jarhead
    Nov 26 '18 at 13:54











  • @Adriaan, if you can post an answer with specifying how my example is bad for matlab and how you propose to write it differently, it would be great and will also benefit others.

    – jarhead
    Nov 26 '18 at 13:55






  • 1





    @jarhead see this question. I'm not going to write an answer, as preallocating is too evident imo, as it should always be done. No value there.

    – Adriaan
    Nov 26 '18 at 15:20



















Do you have the Econometrics toolbox? If so you can have a look at autocorr, which calculates the auto correlation. You should be able to adapt it to calculate the tangent tangent correlation instead. When I say adapt, I mean create a new similar function, not changing the existing one.

– Nicky Mattsson
Nov 26 '18 at 13:28







Do you have the Econometrics toolbox? If so you can have a look at autocorr, which calculates the auto correlation. You should be able to adapt it to calculate the tangent tangent correlation instead. When I say adapt, I mean create a new similar function, not changing the existing one.

– Nicky Mattsson
Nov 26 '18 at 13:28






1




1





For starters, growing arrays, like you do with theta is very, very, very bad for MATLAB performance. Just preallocate it to the correct size (that's known in this case, although variable per iteration) and you'll save a lot of time already.

– Adriaan
Nov 26 '18 at 13:28





For starters, growing arrays, like you do with theta is very, very, very bad for MATLAB performance. Just preallocate it to the correct size (that's known in this case, although variable per iteration) and you'll save a lot of time already.

– Adriaan
Nov 26 '18 at 13:28













@NickyMattsson, I'd like to stick with what matlab has to offer without the toolboxes.

– jarhead
Nov 26 '18 at 13:54





@NickyMattsson, I'd like to stick with what matlab has to offer without the toolboxes.

– jarhead
Nov 26 '18 at 13:54













@Adriaan, if you can post an answer with specifying how my example is bad for matlab and how you propose to write it differently, it would be great and will also benefit others.

– jarhead
Nov 26 '18 at 13:55





@Adriaan, if you can post an answer with specifying how my example is bad for matlab and how you propose to write it differently, it would be great and will also benefit others.

– jarhead
Nov 26 '18 at 13:55




1




1





@jarhead see this question. I'm not going to write an answer, as preallocating is too evident imo, as it should always be done. No value there.

– Adriaan
Nov 26 '18 at 15:20







@jarhead see this question. I'm not going to write an answer, as preallocating is too evident imo, as it should always be done. No value there.

– Adriaan
Nov 26 '18 at 15:20














2 Answers
2






active

oldest

votes


















1














Here is a full vectorized solution:



i = 1:n-1;
j = (1:nSteps).';
ij= min(i+j,n);
a = cat(3, v1(i).', v2(i).');
b = cat(3, v1(ij), v2(ij));

d = sum(a .* b, 3);
n1 = sum(a .^ 2, 3);
n2 = sum(b .^ 2, 3);
theta = acosd(d./sqrt(n1.*n2));
idx = (1:nSteps).' <= (n-1:-1:1);

mean_theta = sum(theta .* idx ,2) ./ sum(idx,2);


Result of Octave timings for my method,method4 from the answer provided by @CrisLuengo and the original method (n=250):



Full vectorized    : 0.000864983 seconds
Method4(Vectorize) : 0.002774 seconds
Original(loop) : 0.340693 seconds





share|improve this answer































    2














    There are several things you can do to speed up your code. First, always preallocate. This converts:



    theta = ;
    for i = 1:(n-j)
    %...
    theta = [theta acosd(d/n1/n2)];
    end


    into:



    theta = zeros(1,n-j);
    for i = 1:(n-j)
    %...
    theta(i) = acosd(d/n1/n2);
    end


    Next, move the normalization out of the loops. There is no need to normalize over and over again, just normalize the input:



    v = [v1,v2];
    v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
    %...
    theta(i) = acosd(dot(v(i,:),v(i+j,:)));


    This does change the output very slightly, within numerical precision, because the different order of operations leads to different floating-point rounding error.



    Finally, you can remove the inner loop by vectorizing that computation:



    i = 1:(n-j);
    theta = acosd(dot(v(i,:),v(i+j,:),2));


    Timings (n=25):




    • Original: 0.0019 s

    • Preallocate: 0.0013 s

    • Normalize once: 0.0011 s

    • Vectorize: 1.4176e-04 s


    Timings (n=250):




    • Original: 0.0185 s

    • Preallocate: 0.0146 s

    • Normalize once: 0.0118 s

    • Vectorize: 2.5694e-04 s


    Note how the vectorized code is the only one whose timing doesn't grow linearly with n.



    Timing code:



    function so
    n = 25;
    v1 = rand(n,1);
    v2 = rand(n,1);
    nSteps = 10;
    mean_theta1 = method1(v1,v2,nSteps);
    mean_theta2 = method2(v1,v2,nSteps);
    fprintf('diff method1 vs method2: %gn',max(abs(mean_theta1(:)-mean_theta2(:))));
    mean_theta3 = method3(v1,v2,nSteps);
    fprintf('diff method1 vs method3: %gn',max(abs(mean_theta1(:)-mean_theta3(:))));
    mean_theta4 = method4(v1,v2,nSteps);
    fprintf('diff method1 vs method4: %gn',max(abs(mean_theta1(:)-mean_theta4(:))));

    timeit(@()method1(v1,v2,nSteps))
    timeit(@()method2(v1,v2,nSteps))
    timeit(@()method3(v1,v2,nSteps))
    timeit(@()method4(v1,v2,nSteps))

    function mean_theta = method1(v1,v2,nSteps)
    n = numel(v1);
    mean_theta = zeros(nSteps,1);
    for j = 1:nSteps
    theta=;
    for i=1:(n-j)
    d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
    n1 = norm([v1(i) v2(i)]);
    n2 = norm([v1(i+j) v2(i+j)]);
    theta = [theta acosd(d/n1/n2)];
    end
    mean_theta(j) = mean(theta);
    end

    function mean_theta = method2(v1,v2,nSteps)
    n = numel(v1);
    mean_theta = zeros(nSteps,1);
    for j = 1:nSteps
    theta = zeros(1,n-j);
    for i = 1:(n-j)
    d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
    n1 = norm([v1(i) v2(i)]);
    n2 = norm([v1(i+j) v2(i+j)]);
    theta(i) = acosd(d/n1/n2);
    end
    mean_theta(j) = mean(theta);
    end

    function mean_theta = method3(v1,v2,nSteps)
    v = [v1,v2];
    v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
    n = numel(v1);
    mean_theta = zeros(nSteps,1);
    for j = 1:nSteps
    theta = zeros(1,n-j);
    for i = 1:(n-j)
    theta(i) = acosd(dot(v(i,:),v(i+j,:)));
    end
    mean_theta(j) = mean(theta);
    end

    function mean_theta = method4(v1,v2,nSteps)
    v = [v1,v2];
    v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
    n = numel(v1);
    mean_theta = zeros(nSteps,1);
    for j = 1:nSteps
    i = 1:(n-j);
    theta = acosd(dot(v(i,:),v(i+j,:),2));
    mean_theta(j) = mean(theta);
    end





    share|improve this answer
























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53481790%2ftangent-tangent-correlation-calculation-in-matrix-form-matlab%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      1














      Here is a full vectorized solution:



      i = 1:n-1;
      j = (1:nSteps).';
      ij= min(i+j,n);
      a = cat(3, v1(i).', v2(i).');
      b = cat(3, v1(ij), v2(ij));

      d = sum(a .* b, 3);
      n1 = sum(a .^ 2, 3);
      n2 = sum(b .^ 2, 3);
      theta = acosd(d./sqrt(n1.*n2));
      idx = (1:nSteps).' <= (n-1:-1:1);

      mean_theta = sum(theta .* idx ,2) ./ sum(idx,2);


      Result of Octave timings for my method,method4 from the answer provided by @CrisLuengo and the original method (n=250):



      Full vectorized    : 0.000864983 seconds
      Method4(Vectorize) : 0.002774 seconds
      Original(loop) : 0.340693 seconds





      share|improve this answer




























        1














        Here is a full vectorized solution:



        i = 1:n-1;
        j = (1:nSteps).';
        ij= min(i+j,n);
        a = cat(3, v1(i).', v2(i).');
        b = cat(3, v1(ij), v2(ij));

        d = sum(a .* b, 3);
        n1 = sum(a .^ 2, 3);
        n2 = sum(b .^ 2, 3);
        theta = acosd(d./sqrt(n1.*n2));
        idx = (1:nSteps).' <= (n-1:-1:1);

        mean_theta = sum(theta .* idx ,2) ./ sum(idx,2);


        Result of Octave timings for my method,method4 from the answer provided by @CrisLuengo and the original method (n=250):



        Full vectorized    : 0.000864983 seconds
        Method4(Vectorize) : 0.002774 seconds
        Original(loop) : 0.340693 seconds





        share|improve this answer


























          1












          1








          1







          Here is a full vectorized solution:



          i = 1:n-1;
          j = (1:nSteps).';
          ij= min(i+j,n);
          a = cat(3, v1(i).', v2(i).');
          b = cat(3, v1(ij), v2(ij));

          d = sum(a .* b, 3);
          n1 = sum(a .^ 2, 3);
          n2 = sum(b .^ 2, 3);
          theta = acosd(d./sqrt(n1.*n2));
          idx = (1:nSteps).' <= (n-1:-1:1);

          mean_theta = sum(theta .* idx ,2) ./ sum(idx,2);


          Result of Octave timings for my method,method4 from the answer provided by @CrisLuengo and the original method (n=250):



          Full vectorized    : 0.000864983 seconds
          Method4(Vectorize) : 0.002774 seconds
          Original(loop) : 0.340693 seconds





          share|improve this answer













          Here is a full vectorized solution:



          i = 1:n-1;
          j = (1:nSteps).';
          ij= min(i+j,n);
          a = cat(3, v1(i).', v2(i).');
          b = cat(3, v1(ij), v2(ij));

          d = sum(a .* b, 3);
          n1 = sum(a .^ 2, 3);
          n2 = sum(b .^ 2, 3);
          theta = acosd(d./sqrt(n1.*n2));
          idx = (1:nSteps).' <= (n-1:-1:1);

          mean_theta = sum(theta .* idx ,2) ./ sum(idx,2);


          Result of Octave timings for my method,method4 from the answer provided by @CrisLuengo and the original method (n=250):



          Full vectorized    : 0.000864983 seconds
          Method4(Vectorize) : 0.002774 seconds
          Original(loop) : 0.340693 seconds






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 26 '18 at 19:12









          rahnema1rahnema1

          10.7k2923




          10.7k2923

























              2














              There are several things you can do to speed up your code. First, always preallocate. This converts:



              theta = ;
              for i = 1:(n-j)
              %...
              theta = [theta acosd(d/n1/n2)];
              end


              into:



              theta = zeros(1,n-j);
              for i = 1:(n-j)
              %...
              theta(i) = acosd(d/n1/n2);
              end


              Next, move the normalization out of the loops. There is no need to normalize over and over again, just normalize the input:



              v = [v1,v2];
              v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
              %...
              theta(i) = acosd(dot(v(i,:),v(i+j,:)));


              This does change the output very slightly, within numerical precision, because the different order of operations leads to different floating-point rounding error.



              Finally, you can remove the inner loop by vectorizing that computation:



              i = 1:(n-j);
              theta = acosd(dot(v(i,:),v(i+j,:),2));


              Timings (n=25):




              • Original: 0.0019 s

              • Preallocate: 0.0013 s

              • Normalize once: 0.0011 s

              • Vectorize: 1.4176e-04 s


              Timings (n=250):




              • Original: 0.0185 s

              • Preallocate: 0.0146 s

              • Normalize once: 0.0118 s

              • Vectorize: 2.5694e-04 s


              Note how the vectorized code is the only one whose timing doesn't grow linearly with n.



              Timing code:



              function so
              n = 25;
              v1 = rand(n,1);
              v2 = rand(n,1);
              nSteps = 10;
              mean_theta1 = method1(v1,v2,nSteps);
              mean_theta2 = method2(v1,v2,nSteps);
              fprintf('diff method1 vs method2: %gn',max(abs(mean_theta1(:)-mean_theta2(:))));
              mean_theta3 = method3(v1,v2,nSteps);
              fprintf('diff method1 vs method3: %gn',max(abs(mean_theta1(:)-mean_theta3(:))));
              mean_theta4 = method4(v1,v2,nSteps);
              fprintf('diff method1 vs method4: %gn',max(abs(mean_theta1(:)-mean_theta4(:))));

              timeit(@()method1(v1,v2,nSteps))
              timeit(@()method2(v1,v2,nSteps))
              timeit(@()method3(v1,v2,nSteps))
              timeit(@()method4(v1,v2,nSteps))

              function mean_theta = method1(v1,v2,nSteps)
              n = numel(v1);
              mean_theta = zeros(nSteps,1);
              for j = 1:nSteps
              theta=;
              for i=1:(n-j)
              d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
              n1 = norm([v1(i) v2(i)]);
              n2 = norm([v1(i+j) v2(i+j)]);
              theta = [theta acosd(d/n1/n2)];
              end
              mean_theta(j) = mean(theta);
              end

              function mean_theta = method2(v1,v2,nSteps)
              n = numel(v1);
              mean_theta = zeros(nSteps,1);
              for j = 1:nSteps
              theta = zeros(1,n-j);
              for i = 1:(n-j)
              d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
              n1 = norm([v1(i) v2(i)]);
              n2 = norm([v1(i+j) v2(i+j)]);
              theta(i) = acosd(d/n1/n2);
              end
              mean_theta(j) = mean(theta);
              end

              function mean_theta = method3(v1,v2,nSteps)
              v = [v1,v2];
              v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
              n = numel(v1);
              mean_theta = zeros(nSteps,1);
              for j = 1:nSteps
              theta = zeros(1,n-j);
              for i = 1:(n-j)
              theta(i) = acosd(dot(v(i,:),v(i+j,:)));
              end
              mean_theta(j) = mean(theta);
              end

              function mean_theta = method4(v1,v2,nSteps)
              v = [v1,v2];
              v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
              n = numel(v1);
              mean_theta = zeros(nSteps,1);
              for j = 1:nSteps
              i = 1:(n-j);
              theta = acosd(dot(v(i,:),v(i+j,:),2));
              mean_theta(j) = mean(theta);
              end





              share|improve this answer




























                2














                There are several things you can do to speed up your code. First, always preallocate. This converts:



                theta = ;
                for i = 1:(n-j)
                %...
                theta = [theta acosd(d/n1/n2)];
                end


                into:



                theta = zeros(1,n-j);
                for i = 1:(n-j)
                %...
                theta(i) = acosd(d/n1/n2);
                end


                Next, move the normalization out of the loops. There is no need to normalize over and over again, just normalize the input:



                v = [v1,v2];
                v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
                %...
                theta(i) = acosd(dot(v(i,:),v(i+j,:)));


                This does change the output very slightly, within numerical precision, because the different order of operations leads to different floating-point rounding error.



                Finally, you can remove the inner loop by vectorizing that computation:



                i = 1:(n-j);
                theta = acosd(dot(v(i,:),v(i+j,:),2));


                Timings (n=25):




                • Original: 0.0019 s

                • Preallocate: 0.0013 s

                • Normalize once: 0.0011 s

                • Vectorize: 1.4176e-04 s


                Timings (n=250):




                • Original: 0.0185 s

                • Preallocate: 0.0146 s

                • Normalize once: 0.0118 s

                • Vectorize: 2.5694e-04 s


                Note how the vectorized code is the only one whose timing doesn't grow linearly with n.



                Timing code:



                function so
                n = 25;
                v1 = rand(n,1);
                v2 = rand(n,1);
                nSteps = 10;
                mean_theta1 = method1(v1,v2,nSteps);
                mean_theta2 = method2(v1,v2,nSteps);
                fprintf('diff method1 vs method2: %gn',max(abs(mean_theta1(:)-mean_theta2(:))));
                mean_theta3 = method3(v1,v2,nSteps);
                fprintf('diff method1 vs method3: %gn',max(abs(mean_theta1(:)-mean_theta3(:))));
                mean_theta4 = method4(v1,v2,nSteps);
                fprintf('diff method1 vs method4: %gn',max(abs(mean_theta1(:)-mean_theta4(:))));

                timeit(@()method1(v1,v2,nSteps))
                timeit(@()method2(v1,v2,nSteps))
                timeit(@()method3(v1,v2,nSteps))
                timeit(@()method4(v1,v2,nSteps))

                function mean_theta = method1(v1,v2,nSteps)
                n = numel(v1);
                mean_theta = zeros(nSteps,1);
                for j = 1:nSteps
                theta=;
                for i=1:(n-j)
                d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
                n1 = norm([v1(i) v2(i)]);
                n2 = norm([v1(i+j) v2(i+j)]);
                theta = [theta acosd(d/n1/n2)];
                end
                mean_theta(j) = mean(theta);
                end

                function mean_theta = method2(v1,v2,nSteps)
                n = numel(v1);
                mean_theta = zeros(nSteps,1);
                for j = 1:nSteps
                theta = zeros(1,n-j);
                for i = 1:(n-j)
                d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
                n1 = norm([v1(i) v2(i)]);
                n2 = norm([v1(i+j) v2(i+j)]);
                theta(i) = acosd(d/n1/n2);
                end
                mean_theta(j) = mean(theta);
                end

                function mean_theta = method3(v1,v2,nSteps)
                v = [v1,v2];
                v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
                n = numel(v1);
                mean_theta = zeros(nSteps,1);
                for j = 1:nSteps
                theta = zeros(1,n-j);
                for i = 1:(n-j)
                theta(i) = acosd(dot(v(i,:),v(i+j,:)));
                end
                mean_theta(j) = mean(theta);
                end

                function mean_theta = method4(v1,v2,nSteps)
                v = [v1,v2];
                v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
                n = numel(v1);
                mean_theta = zeros(nSteps,1);
                for j = 1:nSteps
                i = 1:(n-j);
                theta = acosd(dot(v(i,:),v(i+j,:),2));
                mean_theta(j) = mean(theta);
                end





                share|improve this answer


























                  2












                  2








                  2







                  There are several things you can do to speed up your code. First, always preallocate. This converts:



                  theta = ;
                  for i = 1:(n-j)
                  %...
                  theta = [theta acosd(d/n1/n2)];
                  end


                  into:



                  theta = zeros(1,n-j);
                  for i = 1:(n-j)
                  %...
                  theta(i) = acosd(d/n1/n2);
                  end


                  Next, move the normalization out of the loops. There is no need to normalize over and over again, just normalize the input:



                  v = [v1,v2];
                  v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
                  %...
                  theta(i) = acosd(dot(v(i,:),v(i+j,:)));


                  This does change the output very slightly, within numerical precision, because the different order of operations leads to different floating-point rounding error.



                  Finally, you can remove the inner loop by vectorizing that computation:



                  i = 1:(n-j);
                  theta = acosd(dot(v(i,:),v(i+j,:),2));


                  Timings (n=25):




                  • Original: 0.0019 s

                  • Preallocate: 0.0013 s

                  • Normalize once: 0.0011 s

                  • Vectorize: 1.4176e-04 s


                  Timings (n=250):




                  • Original: 0.0185 s

                  • Preallocate: 0.0146 s

                  • Normalize once: 0.0118 s

                  • Vectorize: 2.5694e-04 s


                  Note how the vectorized code is the only one whose timing doesn't grow linearly with n.



                  Timing code:



                  function so
                  n = 25;
                  v1 = rand(n,1);
                  v2 = rand(n,1);
                  nSteps = 10;
                  mean_theta1 = method1(v1,v2,nSteps);
                  mean_theta2 = method2(v1,v2,nSteps);
                  fprintf('diff method1 vs method2: %gn',max(abs(mean_theta1(:)-mean_theta2(:))));
                  mean_theta3 = method3(v1,v2,nSteps);
                  fprintf('diff method1 vs method3: %gn',max(abs(mean_theta1(:)-mean_theta3(:))));
                  mean_theta4 = method4(v1,v2,nSteps);
                  fprintf('diff method1 vs method4: %gn',max(abs(mean_theta1(:)-mean_theta4(:))));

                  timeit(@()method1(v1,v2,nSteps))
                  timeit(@()method2(v1,v2,nSteps))
                  timeit(@()method3(v1,v2,nSteps))
                  timeit(@()method4(v1,v2,nSteps))

                  function mean_theta = method1(v1,v2,nSteps)
                  n = numel(v1);
                  mean_theta = zeros(nSteps,1);
                  for j = 1:nSteps
                  theta=;
                  for i=1:(n-j)
                  d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
                  n1 = norm([v1(i) v2(i)]);
                  n2 = norm([v1(i+j) v2(i+j)]);
                  theta = [theta acosd(d/n1/n2)];
                  end
                  mean_theta(j) = mean(theta);
                  end

                  function mean_theta = method2(v1,v2,nSteps)
                  n = numel(v1);
                  mean_theta = zeros(nSteps,1);
                  for j = 1:nSteps
                  theta = zeros(1,n-j);
                  for i = 1:(n-j)
                  d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
                  n1 = norm([v1(i) v2(i)]);
                  n2 = norm([v1(i+j) v2(i+j)]);
                  theta(i) = acosd(d/n1/n2);
                  end
                  mean_theta(j) = mean(theta);
                  end

                  function mean_theta = method3(v1,v2,nSteps)
                  v = [v1,v2];
                  v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
                  n = numel(v1);
                  mean_theta = zeros(nSteps,1);
                  for j = 1:nSteps
                  theta = zeros(1,n-j);
                  for i = 1:(n-j)
                  theta(i) = acosd(dot(v(i,:),v(i+j,:)));
                  end
                  mean_theta(j) = mean(theta);
                  end

                  function mean_theta = method4(v1,v2,nSteps)
                  v = [v1,v2];
                  v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
                  n = numel(v1);
                  mean_theta = zeros(nSteps,1);
                  for j = 1:nSteps
                  i = 1:(n-j);
                  theta = acosd(dot(v(i,:),v(i+j,:),2));
                  mean_theta(j) = mean(theta);
                  end





                  share|improve this answer













                  There are several things you can do to speed up your code. First, always preallocate. This converts:



                  theta = ;
                  for i = 1:(n-j)
                  %...
                  theta = [theta acosd(d/n1/n2)];
                  end


                  into:



                  theta = zeros(1,n-j);
                  for i = 1:(n-j)
                  %...
                  theta(i) = acosd(d/n1/n2);
                  end


                  Next, move the normalization out of the loops. There is no need to normalize over and over again, just normalize the input:



                  v = [v1,v2];
                  v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
                  %...
                  theta(i) = acosd(dot(v(i,:),v(i+j,:)));


                  This does change the output very slightly, within numerical precision, because the different order of operations leads to different floating-point rounding error.



                  Finally, you can remove the inner loop by vectorizing that computation:



                  i = 1:(n-j);
                  theta = acosd(dot(v(i,:),v(i+j,:),2));


                  Timings (n=25):




                  • Original: 0.0019 s

                  • Preallocate: 0.0013 s

                  • Normalize once: 0.0011 s

                  • Vectorize: 1.4176e-04 s


                  Timings (n=250):




                  • Original: 0.0185 s

                  • Preallocate: 0.0146 s

                  • Normalize once: 0.0118 s

                  • Vectorize: 2.5694e-04 s


                  Note how the vectorized code is the only one whose timing doesn't grow linearly with n.



                  Timing code:



                  function so
                  n = 25;
                  v1 = rand(n,1);
                  v2 = rand(n,1);
                  nSteps = 10;
                  mean_theta1 = method1(v1,v2,nSteps);
                  mean_theta2 = method2(v1,v2,nSteps);
                  fprintf('diff method1 vs method2: %gn',max(abs(mean_theta1(:)-mean_theta2(:))));
                  mean_theta3 = method3(v1,v2,nSteps);
                  fprintf('diff method1 vs method3: %gn',max(abs(mean_theta1(:)-mean_theta3(:))));
                  mean_theta4 = method4(v1,v2,nSteps);
                  fprintf('diff method1 vs method4: %gn',max(abs(mean_theta1(:)-mean_theta4(:))));

                  timeit(@()method1(v1,v2,nSteps))
                  timeit(@()method2(v1,v2,nSteps))
                  timeit(@()method3(v1,v2,nSteps))
                  timeit(@()method4(v1,v2,nSteps))

                  function mean_theta = method1(v1,v2,nSteps)
                  n = numel(v1);
                  mean_theta = zeros(nSteps,1);
                  for j = 1:nSteps
                  theta=;
                  for i=1:(n-j)
                  d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
                  n1 = norm([v1(i) v2(i)]);
                  n2 = norm([v1(i+j) v2(i+j)]);
                  theta = [theta acosd(d/n1/n2)];
                  end
                  mean_theta(j) = mean(theta);
                  end

                  function mean_theta = method2(v1,v2,nSteps)
                  n = numel(v1);
                  mean_theta = zeros(nSteps,1);
                  for j = 1:nSteps
                  theta = zeros(1,n-j);
                  for i = 1:(n-j)
                  d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
                  n1 = norm([v1(i) v2(i)]);
                  n2 = norm([v1(i+j) v2(i+j)]);
                  theta(i) = acosd(d/n1/n2);
                  end
                  mean_theta(j) = mean(theta);
                  end

                  function mean_theta = method3(v1,v2,nSteps)
                  v = [v1,v2];
                  v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
                  n = numel(v1);
                  mean_theta = zeros(nSteps,1);
                  for j = 1:nSteps
                  theta = zeros(1,n-j);
                  for i = 1:(n-j)
                  theta(i) = acosd(dot(v(i,:),v(i+j,:)));
                  end
                  mean_theta(j) = mean(theta);
                  end

                  function mean_theta = method4(v1,v2,nSteps)
                  v = [v1,v2];
                  v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
                  n = numel(v1);
                  mean_theta = zeros(nSteps,1);
                  for j = 1:nSteps
                  i = 1:(n-j);
                  theta = acosd(dot(v(i,:),v(i+j,:),2));
                  mean_theta(j) = mean(theta);
                  end






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 26 '18 at 16:32









                  Cris LuengoCris Luengo

                  22.5k52253




                  22.5k52253






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53481790%2ftangent-tangent-correlation-calculation-in-matrix-form-matlab%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Wiesbaden

                      Marschland

                      Dieringhausen