Incorrect plotting of ramp sequence in Matlab - matlab

I am trying to plot a discrete ramp sequence using Matlab, within the interval [-10, 10].
This is my code:
function Ramp()
rampseq(-10, 10);
end
function rampseq (n1, n2)
n = (n1:1:n2);
stem (n, pw(n));
end
function y = pw(n)
if (n < 0)
y = 0;
return;
else
y = n;
return;
end
end
I define the behavior of the sequence in the pw(n) function (short form for 'piecewise'). Note that if n < 0, the output should be 0 or else if n >= 0, the output should be n itself. However, the plot turns out to be:
This isn't the ramp sequence as the Y-values are not 0 when n < 0, contrary to the behavior defined in the pw(n) function. Where am I going wrong? Is the if statement being skipped for some reason? The Command Window does not show any error.

You are passing the whole vector n into the pw() function. However, the pw() function then compares n to 0, which is a scalar.
You could adjust your pw() function to operate on vector inputs like this:
function y = pw(n)
y = n;
y(n < 0) = 0;
end

Related

Matlab: Plotting the conditions output of symbolic solve

I have a loop where I symbolically solve for intervals. Each iteration of the loop gives exactly one interval, for example:
v=[x+1,-x+4];
v = v > 0;
sol=solve(v,x,'ReturnConditions',true);
cond = sol.conditions;
ezplot(cond)
Would I be able to plot the 1x1 symbolic array " cond = -1 < x & x < 4 " at a y value of my choosing? When I use ezplot it always plots at y=1.
Maybe by multiplying the cond by the y value you wish to use. In that case the title must be changed to match the original condition, cond by casting it as a string. In the example below I plotted the condition/region at a height of y = 2. To implement this in the for-loop I'd probably make a y a vector a retrieve one value/cell upon each iteration.
syms x
v = [x+1,-x+4];
v = v > 0;
sol = solve(v,x,'ReturnConditions',true);
cond = sol.conditions;
y = 2;
ezplot(y*cond);
ylim([0 y*1.2]);
title(string(cond));

Plotting the Impulsefunction

so I'm new to Matlab and had to draw the Impulsefunction with y(n) is only 1 if n == 3, else 0. The following code works:
n = -5:5;
f = n; % allocate f
for i = 1 : length(n)
f(i) = dd1(n(i)-3);
end
stem(n, f);
function y = dd1(n)
y = 0;
if n == 0
y = 1;
end
end
But I feel like it's to complicated, so I tried the following:
n = -5:5
stem(n, fo)
function y = fo(n)
y = 0
if n == 3
y=1
end
end
This returns
Not enough input arguments.
Error in alternative>fo (line 5)
if n == 3
Error in alternative (line 2)
stem(n, fo)
I feel like I'm missing something trivial here.
if is no vector-wise operation but expects a single boolean (or at least a scalar that it can cast to a boolean).
But you can do this vector-wise:
lg = n == 3;
This produces a logical (MATLAB's name for boolean) array (because n is an array and not a vector), which is true where n is equal (==) to three. So you don't need a function, because you can make use of MATLAB's ability to work with vectors and arrays implicitly.
(for your code it would be f = (n-3) == 3)
A last hint: if you have a state-space system (ss-object), you can use the function step to get the step-response as a plot.

Output 1, 0.5, or 0 depending if a matrix elements are prime, 1, or neither

I am sending a matrix to my function modifikuj, where I want to replace the elements of the matrix with:
1 if element is a prime number
0 if element is a composite number
0.5 if element is 1
I dont understand why it is not working. I just started with MATLAB, and I created this function:
function B = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
prost=1;
if (A(i,j) == 1)
A(i,j) = 0.5;
else
for k = 2:(A(i,j))
if(mod(A(i,j),k) == 0)
prost=0;
end
end
if(prost==1)
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
With
A = [1,2;3,4];
D = modifikuj(A);
D should be:
D=[0.5, 1; 1 0];
In MATLAB you'll find you can often avoid loops, and there's plenty of built in functions to ease your path. Unless this is a coding exercise where you have to use a prescribed method, I'd do the following one-liner to get your desired result:
D = isprime( A ) + 0.5*( A == 1 );
This relies on two simple tests:
isprime( A ) % 1 if prime, 0 if not prime
A == 1 % 1 if == 1, 0 otherwise
Multiplying the 2nd test by 0.5 gives your desired condition for when the value is 1, since it will also return 0 for the isprime test.
You are not returning anything from the function. The return value is supposed to be 'B' according to your code but this is not set. Change it to A.
You are looping k until A(i,j) which is always divisible by itself, loop to A(i,j)-1
With the code below I get [0.5,1;1,0].
function A = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
prost=1;
if (A(i,j) == 1)
A(i,j) = 0.5;
else
for k = 2:(A(i,j)-1)
if(mod(A(i,j),k) == 0)
prost=0;
end
end
if(prost==1)
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
In addition to #EuanSmith's answer. You can also use the in built matlab function in order to determine if a number is prime or not.
The following code will give you the desired output:
A = [1,2;3,4];
A(A==1) = 0.5; %replace 1 number with 0.5
A(isprime(A)) = 1; %replace prime number with 1
A(~ismember(A,[0.5,1])) = 0; %replace composite number with 0
I've made the assumption that the matrice contains only integer.
If you only want to learn, you can also preserve the for loop with some improvement since the function mod can take more than 1 divisor as input:
function A = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
k = A(i,j);
if (k == 1)
A(i,j) = 0.5;
else
if all(mod(k,2:k-1)) %check each modulo at the same time.
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
And you can still improve the prime detection:
2 is the only even number to test.
number bigger than A(i,j)/2 are useless
so instead of all(mod(k,2:k-1)) you can use all(mod(k,[2,3:2:k/2]))
Note also that the function isprime is a way more efficient primality test since it use the probabilistic Miller-Rabin algorithme.

Implementing a filter in Matlab

I am trying to implement the following filter on a discrete signal x:
I'm supposed to write a MATLAB function that takes a length-M (> N) vector x and a scalar N as input. The output should be a length-M vector y.
I should then test the filter with M = 50, x[n]=cos(n*pi/5)+dirac[n-30]-dirac[n-35] and N = 4, 8, 12.
Here is my try, which returns Inf with the given input and N:
function y = filt( x, N )
% filter function
if(~isvector(x))
error('Input must be a vector')
end
y = zeros(1,length(x));
temp = zeros(1,length(x));
n=1;
for v = x(:)
temp(n) = v(n);
if(n <= N-1)
y(n) = max(x);
n = n+1;
elseif(n >= N-1)
y(n) = max(temp);
end
end
end
I also tried using the built-in filter function but I can't get it to work.
Code for using the filter:
p = zeros(1,50);
for i=0:50
p(i+1)= cos(i*pi/5)+dirac(i-30)-dirac(i-35)
end
y = filt(p,4)
Thanks in advance.
That's because dirac(0) gives you Inf. This will happen in two places in your signal, where n=30 and n=35. I'm assuming you want the unit impulse instead. As such, create a signal where at n = 31 and n = 36, the output is 1, then add this with your cosine signal. This is because MATLAB starts indexing at 1 and not 0, and so dirac[0] would mean that the first point of your signal is non-zero, so translating this over by 30: dirac[n-30] would mean that the 31st point is non-zero. Similar case for dirac[n-35], so the 36th point is non-zero:
p = zeros(1,50);
p(31) = 1; p(36) = 1;
p = p + cos((0:49)*pi/5);
y = filt(p,4);
I also have some reservations with your code. It doesn't do what you think it's doing. Specifically, I'm looking at this section:
n=1;
for v = x(:)
temp(n) = v(n);
if(n <= N-1)
y(n) = max(x);
n = n+1;
elseif(n >= N-1)
y(n) = max(temp);
end
end
Doing v = x(:) would produce a column vector, and using a loop with a column vector will have unintentional results. Specifically, this loop will only execute once, with v being the entire signal. You also aren't checking the conditions properly for each window. You are doing max(x), which applies the maximum to the entire signal, and not the window.
If I can suggest a rewrite, this is what you should be doing instead:
function y = filt( x, N )
% filter function
if(~isvector(x))
error('Input must be a vector')
end
y = zeros(1,length(x));
%///// CHANGE
for n = 1 : numel(x)
if (n <= N)
y(n) = max(x(1:n));
else
y(n) = max(x(n:-1:n-N+1));
end
end
end
Take note that the if statement is n <= N. This is because in MATLAB, we start indexing at 1, but the notation in your equation starts indexing at 0. Therefore, instead of checking for n <= N-1, it must now be n <= N.

Plotting own function in scilab

Hey i have an issuse with plotting my own function in scilab.
I want to plot the following function
function f = test(n)
if n < 0 then
f(n) = 0;
elseif n <= 1 & n >= 0 then
f(n) = sin((%pi * n)/2);
else
f(n) = 1;
end
endfunction
followed by the the console command
x = [-2:0.1:2];
plot(x, test(x));
i loaded the function and get the following error
!--error 21
Invalid Index.
at line 7 of function lala called by :
plot(x, test(x))
Can you please tell me how i can fix this
So i now did it with a for loop. I don't think it is the best solution but i can't get the other ones running atm...
function f = test(n)
f = zeros(size(n));
t = length(n);
for i = 1:t
if n(i) < 0 then
f(i) = 0;
elseif n(i) <= 1 & n(i) >= 0
f(i) = sin((%pi * n(i)/2));
elseif n(i) > 1 then
f(i) = 1;
end
end
endfunction
I guess i need to find a source about this issue and get used with the features and perks matlab/scilab have to over :)
Thanks for the help tho
The original sin is
function f = test(n)
(...)
f(n) = (...)
(...)
endfunction
f is supposed to be the result of the function. Therefore, f(n) is not "the value that the function test takes on argument n", but "the n-th element of f". Scilab then handles this however it can; on your test case, it tries to access a non-integer index, which results in an error. Your loop solution solves the problem.
Replacing all three f(n) by f in your first formulation makes it into something that works... as long as the argument is a scalar (not an array).
If you want test to be able to accept vector arguments without making a loop, the problem is that n < 0 is a vector of the same size as n. My solution would use logical arrays for indexing each of the three conditions:
function f = test(n)
f = zeros(size(n));
negative = (n<0);//parentheses are optional, but I like them for readability
greater_than_1 = (n>1);
others = ~negative & ~greater_than_1;
f(isnegative)=0;
f(greater_than_1)=1;
f(others) = sin(%pi/2*n(others));
endfunction