How to use .* in MATLAB multiplication? - arrays

I am trying to visualize the probability distribution function of Rayleigh distribution by implementing it myself in MATLAB, instead of using the inbuilt raylpdf function.
PDF of Rayleigh distribution :
This is my attempt:
function pdf = rayleigh_pdf(x)
exp_term = -1*power(x,2)/(2*std(x))
pdf = (x*exp(exp_term))/std(x)
end
But when I try to run it I get an error:
x = linspace(-10,10,100);
plot(x,rayleigh_pdf(x))
Error:
Error using *
Incorrect dimensions for matrix multiplication. Check that the number of columns in the first matrix matches the number of rows in the second matrix. To perform elementwise
multiplication, use '.*'.
I am not sure why I am getting this error. Where should I use .*? And why is it required?

The dot-before-operator allows one to do element-wise operations instead of the default matrix operations. If you write your code without dots, chances are high that you'll either run into dimension errors (because you're trying to do matrix multiplication with non-matching dimensions for instance), or get very weird results due to automated broadcasting, making you end up with matrices in sizes you hadn't anticipated.
function pdf = rayleigh_pdf(x)
exp_term = -x.^2./(2.*std(x).^2);
pdf = (x.*exp(exp_term))./(std(x).^2)
end
Two small things: sigma-squared usually denotes variance, i.e. standard deviation squared. So either use std(x).^2 or var(x).
Instead of writing the very verbose power(x,2) operation, you can simply use .^ to obtain the element wise power.
Note that some of the dots are superfluous, such as when you're sure that you are dealing with integers (also known as 1 -by- 1 matrices in MATLAB). You can thus write the following, which is equivalent:
function pdf = rayleigh_pdf(x)
exp_term = -x.^2/(2*std(x)^2);
pdf = (x.*exp(exp_term))/(std(x)^2)
end
i.e. dots are only required when working on arrays, x and exp_term here, and not on scalars like 2 or std(x).

Related

Using norm function in matlab on a subvector of a 3D vector

I've a vector called x that is a 3D vector.
In my code I need to compute the norm of x(1,1,:) (the vector composed by x(1,1,1), x(1,1,2),...). If I try to use the norm(x(1,i,:)) command, Matlab returns me the error "Input must be 2-D". What can I do?
MATLAB’s norm is a “special” function, it doesn’t work like many other functions such as sum and mean.
However, vecnorm does behave like those functions. It computes the norm along the first non-singleton dimension, or you can specify along which dimension to compute the norm:
vecnorm(x(1,1,:))
vecnorm(x,2,3) % computes 2-norm for all vectors along 3rd dimension.
Note that this function was introduced in R2017b. For older versions you can emulate the behavior using sqrt(sum(x.^2,3)).

Is there a way to perform 2D convolutions with strides using Accelerate library in Swift?

I am trying to perform a specific downsampling process. It is described by the following pseudocode.
//Let V be an input image with dimension of M by N (row by column)
//Let U be the destination image of size floor((M+1)/2) by floor((N+1)/2)
//The floor function is to emphasize the rounding for the even dimensions
//U and V are part of a wrapper class of Pixel_FFFF vImageBuffer
for i in 0 ..< U.size.rows {
for j in 0 ..< U.size.columns {
U[i,j] = V[(i * 2), (j * 2)]
}
}
The process basically takes pixel values on every other locations spanning on both dimensions. The resulting image will be approximately half of the original image.
On a one-time call, the process is relatively fast running by itself. However, it becomes a bottleneck when the code is called numerous times inside a bigger algorithm. Therefore, I am trying to optimize it. Since I use Accelerate in my app, I would like to be able to adapt this process in a similar spirit.
Attempts
First, this process can be easily done by a 2D convolution using the 1x1 kernel [1] with a stride [2,2]. Hence, I considered the function vImageConvolve_ARGBFFFF. However, I couldn't find a way to specify the stride. This function would be the best solution, since it takes care of the image Pixel_FFFF structure.
Second, I notice that this is merely transferring data from one array to another array. So, I thought vDSP_vgathr function is a good solution for this. However, I hit a wall, since the resulting vector of vectorizing a vImageBuffer would be the interleaving bits structure A,R,G,B,A,R,G,B,..., which each term is 4 bytes. vDSP_vgathr function transfers every 4 bytes to the destination array using a specified indexing vector. I could use a linear indexing formula to make such vector. But, considering both even and odd dimensions, generating the indexing vector would be as inefficient as the original solution. It would require loops.
Also, neither of the vDSP 2D convolution functions fit the solution.
Is there any other functions in Accelerate that I might have overlooked? I saw that there's a stride option in the vDSP 1D convolution functions. Maybe, does someone know an efficient way to translate 2D convolution process with strides to 1D convolution process?

Trying to modify a matrix of unknown size in matlab with certain restrictions

Basically no for/while loops or if statements. Therefore I assume the colon operator is suppose to be used.
I'm new to Matlab and have basically used for loops in one way or another to accomplish virtually everything and can't find any online resources to help so a quick answer is greatly appreciated.
Essentially the goal is to create and return a new matrix based off an inputted matrix. The new matrix contains only the even indexed elements of the original so a 4x4 matrix would return a 2x2 and a 5x5 would also return a 2x2 because anything in the 5th row or column couldn't have both an even column and row.
My code:
function [A] = myFunction(M)
[x y] = size(M);
for a = 2:2:x
for b = 2:2:y
A(a/2, b/2) = M(a,b);
end
end
end
Which works but I am trying to understand how to do it without the for loops and using the colon operator so I can do that in other applications as well where it makes sense.
very simple
A = M(2:2:end, 2:2:end);
Read about matrix indexing for more information and details.

Failed to plot graph of two arrays in Octave

I have created two arrays in octave using a for loop and I want to create a graph using the data of the two arrays. But it showed an error " invalid value for array property "xdata"" and displayed an empty graph.
for i=1:16
x=1+(10^6)*2
h{i}=1/(10.^i)
fdd1{i}=(sin(1+h{i})-sin(1))/h{i}
error_f1{i}=fdd1{i}-cos(1)
endfor
**fplot(loglog(h,error_f1));**
Am I making mistakes in plotting the graph? May I know how to solve this problem?
Yes, you are doing all the possible mistakes in that snippet.
your variables h and error_f are cell arrays. The function loglog takes numeric arrays. I believe your specific error comes from there. You can convert them with cell2mat as in loglog (cell2mat (h), cell2mat (error_f1)) but I would argue that would still be incorrect since you should have never created a cell array in the first place (see point 4).
your data has non-positive values which you can't plot with logarithmic scale.
the fplot function takes a function handle as argument. Why are you passing a figure handle (the output of loglog) to it?
Octave is a language designed around vectorized operations. It's syntax has a strong emphasis and you will suffer if you don't. You should not have a for loop for this. Just remove your indexing and make your multiplication and division element-wise. This also fixes problem 1 since you will end up with a numeric array
r = 1:16;
x = 1 + (10^6)*2;
h = 1 ./ (10.^r);
fdd1 = (sin (1+h) - sin (1)) ./ h;
error_f1 = fdd1 - cos(1);
Rule of thumb in Octave: if you ever see a for loop, chances are you are doing it wrong.

Slow array operations

I'm a quite new MatLab programmer, so this might be an easy one.. :)
I'm trying to generate a script, that will be able to read any number of XYZ-files, in any order, into a array, and arrange them in the array according to the X and Y coordinates given in the file..
My attempt is to use Load to get the files into a array, and after that, read through the array and, as explained, use the X and Y coordinate as the locations in a new array..
I've tried presetting the array size, and also I'm subtracting a value from both X and Y to minimize the size of the array (fullArray)
%# Script for extraction of XYZ-data from DSM/DTM xyz files
%# Define folders and filter
DSMfolder='/share/CFDwork/site/OFSites/MABH/DSM/*.xyz';
DTMfolder='/share/CFDwork/site/OFSites/MABH/DTM/*.xyz';
%# Define minimumvalues, to reduce arrays.. Please leave some slack, for the
%# reduction-algorithm..
borderX=100000;
borderY=210000;
%% Expected array-size
expSizeX=20000;
expSizeY=20000;
%# Program starts.. Please do not edit below this line!
files=ls(DSMfolder);
clear fullArray
fullArray=zeros(expSizeX,expSizeY);
minX=999999999;
minY=999999999;
maxX=0;
maxY=0;
disp('Reading DSM files');
[thisFile,remaining]=strtok(files);
while (~isempty(thisFile))
disp(['Reading: ' thisFile]);
clear fromFile;
fromFile=load(thisFile);
for k=1:size(fromFile,1)
tic
fullArray(fromFile(k,1)-borderX,fromFile(k,2)-borderY)=fromFile(k,3);
disp([k size(fromFile,1)]);
if (fromFile(k,1)<minX)
minX=fromFile(k,1);
end
if (fromFile(k,2)<minY)
minY=fromFile(k,2);
end
if (fromFile(k,1)>maxX)
maxX=fromFile(k,1);
end
if (fromFile(k,2)>maxY)
maxY=fromFile(k,2);
end
toc
end
[thisFile,remaining]=strtok(remaining);
end
As can be seen, I've added a tic-toc, and the time was 3.36secs for one operation!
Any suggestion on, why this is so slow, and how to improve the speed.. I need to order 2x6,000,000 lines, and I can't be bothered to wait 466 days.. :D
Best regards
Mark
Have you considered using a sparse matrix?
A sparse matrix in matlab is defined by a list of values and their location in the matrix -
incidentally this matches your input file perfectly.
While this representation is generally meant for matrices which are truly sparse, (i.e. most of their values are zeros), it appears that in your case it would be much faster to load the matrix using the sparse function even if it is not truly sparse.
Since your data is organised in such a way (location of every data point) my guess is it is sparse anyway.
The function to create a sparse matrix takes the location as columns so instead of a for loop your code will look something like this (this segment replaces the whole for loop):
minX = min(fromFile(:,1);
maxX = max(fromFile(:,1);
minY = min(fromFile(:,2);
minY = max(fromFile(:,2);
S = sparse(fromFile(:,1) - borderX, fromFile(:,2) - borderY, fromFile(:,3));
Note that the other change I've made is calculating minimum / maximum values directly from the matrix - this is much faster than going over a for loop, as operating on vectors and matrices unleashes the true power of matlab :)
You can perform all sorts of operations on the sparse matrix, but if you want to convert it to a regular matrix you can use the matlab full function.
More information here and there.

Resources