Undefined argument when declaring function in Octave - function

I get undefined variable/argument when trying to define my own random generator function.
Code:
function result = myrand(n, t, p, d)
a = 200 * t + p
big_rand = a * n
result = big_rand / 10**d
return;
endfunction
mrand = myrand(5379, 0, 91, 4)
error:
>> myrand
error: 't' undefined near line 2 column 15
error: called from
myrand at line 2 column 7

You can't start a script with a function keyword.
https://www.gnu.org/software/octave/doc/v4.0.1/Script-Files.html
This works:
disp("Running...")
function result = myrand(n, t, p, d)
a = 200 * t + p
big_rand = a * n
result = big_rand / 10**d
return;
endfunction
mrand = myrand(5379, 0, 91, 4)
You should get:
warning: function 'myrand' defined within script file 'myrand.m'
Running ...
a = 91
big_rand = 489489
result = 48.949
mrand = 48.949

Related

My code in octave seemed has a problem with the code error

I was trying to run the program but the window says
error: 'a' undefined near line 2, column 10
error: called from
false_position at line 2 column 6
here's my code
function y = false_position(f, a, b, error)
if ~(f(a) < 0)
disp("f(a) must be less than 0")
elseif ~(f(b) > 0)
disp("f(b) must be greater than zero")
else
c = 100000;
while abs(f(c)) > error
%Formula for the x-intercept
c = -f(b) * (b - a) / (f(b) - f(a)) + b;
if f(c) < 0
a = c;
else
b = c;
endif
disp(f(c))
endwhile
x = ["The root is approximately located at ", num2str(c)];
disp(x)
y = c;
endif
endfunction
every time i ran the code, it says like that and i am not really a pro with using the octave. I was kinda hoping someone will help me with this error.
Any answers will do

Call arguments in a function in MATLAB

I tried to run this function in MATLAB:
function llik = log_likelihood(p)
global d;
N = length(d);
tau = fzero(#(t) (t - (t^2 * p + 1 - p) / (2 * (t * p + 1 - p))), [0,1]);
loglik = 0;
for i = 1 : N
loglik = loglik + log(isnan(d(i)) * (1 - p * (1 - tau) + ~isnan(d(i))* p * (1 - tau)));
end
llik = loglik / N;
end
Here, p is a scalar. MATLAB gives me an error warning saying
Error using fzero>localFirstFcnEval
FZERO cannot continue because user-supplied function_handle ==>
#(t)(t-(t^2*p+1-p)/(2*(t*p+1-p))) failed with the error below.
Unrecognized function or variable 'p'.
I am confused since p should be the argument of the function. How can it be unrecongized? Thank you for your help!
Everything seems okay with my Matlab if i assign the value d inside the function, where do you define the variable d, if it's a global variable, it must be define as:
global d;
This is my result:

Implementing Euler's Method in GNU Octave

I am reading "Numerical Methods for Engineers" by Chapra and Canale. In it, they've provided pseudocode for the implementation of Euler's method (for solving ordinary differential equations). Here is the pseucode:
Pseucode for implementing Euler's method
I tried implementing this code in GNU Octave, but depending on the input values, I am getting one of two errors:
The program doesn't give any output at all. I have to press 'Ctrl + C' in order to break execution.
The program gives this message:
error: 'ynew' undefined near line 5 column 21
error: called from
Integrator at line 5 column 9
main at line 18 column 7
I would be very grateful if you could get this program to work for me. I am actually an amateur in GNU Octave. Thank you.
Edit 1: Here is my code. For main.m:
%prompt user
y = input('Initial value of y:');
xi = input('Initial value of x:');
xf = input('Final value of x:');
dx = input('Step size:');
xout = input('Output interval:');
x = xi;
m = 0;
xpm = x;
ypm = y;
while(1)
xend = x + xout;
if xend > xf
xend = xf;
h = dx;
Integrator(x,y,h,xend);
m = m + 1;
xpm = x;
ypm = y;
if x >= xf
break;
endif
endif
end
For Integrator.m:
function Integrator(x,y,h,xend)
while(1)
if xend - x < h
h = xend - x;
Euler(x,y,h,ynew);
y = ynew;
if x >= xend
break;
endif
endif
end
endfunction
For Euler.m:
function Euler(x,y,h,ynew)
Derivs(x,y,dydx);
ynew = y + dydx * h;
x = x + h;
endfunction
For Derivs.m:
function Derivs(x,y,dydx)
dydx = -2 * x^3 + 12 * x^2 - 20 * x + 8.5;
endfunction
Edit 2: I shoud mention that the differential equation which Chapra and Canale have given as an example is:
y'(x) = -2 * x^3 + 12 * x^2 - 20 * x + 8.5
That is why the 'Derivs.m' script shows dydx to be this particular polynomial.
Here is my final code. It has four different M-files:
main.m
%prompt the user
y = input('Initial value of y:');
x = input('Initial value of x:');
xf = input('Final value of x:');
dx = input('Step size:');
xout = dx;
%boring calculations
m = 1;
xp = [x];
yp = [y];
while x < xf
[x,y] = Integrator(x,y,dx,min(xf, x+xout));
m = m+1;
xp(m) = x;
yp(m) = y;
end
%plot the final result
plot(xp,yp);
title('Solution using Euler Method');
ylabel('Dependent variable (y)');
xlabel('Independent variable (x)');
grid on;
Integrator.m
%This function takes in 4 inputs (x,y,h,xend) and returns 2 outputs [x,y]
function [x,y] = Integrator(x,y,h,xend)
while x < xend
h = min(h, xend-x);
[x,y] = Euler(x,y,h);
end
endfunction
Euler.m
%This function takes in 3 inputs (x,y,h) and returns 2 outputs [x,ynew]
function [x,ynew] = Euler(x,y,h)
dydx = Derivs(x,y);
ynew = y + dydx * h;
x = x + h;
endfunction
Derivs.m
%This function takes in 2 inputs (x,y) and returns 1 output [dydx]
function [dydx] = Derivs(x,y)
dydx = -2 * x^3 + 12 * x^2 - 20 * x + 8.5;
endfunction
Your functions should look like
function [x, y] = Integrator(x,y,h,xend)
while x < xend
h = min(h, xend-x)
[x,y] = Euler(x,y,h);
end%while
end%function
as an example. Depending on what you want to do with the result, your main loop might need to collect all the results from the single steps. One variant for that is
m = 1;
xp = [x];
yp = [y];
while x < xf
[x,y] = Integrator(x,y,dx,min(xf, x+xout));
m = m+1;
xp(m) = x;
yp(m) = y;
end%while

Octave call a function as a variable of another function

I wrote a bisection method in Octave but it can't consume another function..
My bisection method code is like:
function[x,b] = bisection(f,a,b)
t = 10e-8
while abs(b-a) > t;
c = (a+b)/2;
if f(a) * f(b) <= 0
a = a;
b = c;
else
b = b;
a = c
endif
endwhile
x = (a+b)/2
endfunction
And I already have a file f1.m:
function y = f1(x)
y = x^2 - 4;
endfunction
But when I call [x,v] = bisection[f1,0,5], I get:
>> [t,v] = bisection(f1,0,5)
error: 'x' undefined near line 2 column 5
error: called from
f1 at line 2 column 3
error: evaluating argument list element number 1
what you want is to pass a pointer to f1 to your function bisection so the right call would be
[t,v] = bisection(#f1,0,5)
which outputs:
t = 1.0000e-07
a = 0.62500
a = 0.93750
a = 1.0938
a = 1.1719
a = 1.2109
a = 1.2305
a = 1.2402
a = 1.2451
a = 1.2476
a = 1.2488
a = 1.2494
a = 1.2497
a = 1.2498
a = 1.2499
a = 1.2500
a = 1.2500
a = 1.2500
a = 1.2500
a = 1.2500
a = 1.2500
a = 1.2500
a = 1.2500
a = 1.2500
a = 1.2500
x = 1.2500
t = 1.2500
v = 1.2500
Andy has given you the answer on how to fix this. I would just like to add why you get that error and what it means. Consider the following octave session:
octave:1> function Out = g1(x); Out = x+5; end
octave:2> function Out = g2(); Out = 10;end
octave:3>
octave:3> g2
ans = 10
octave:4> g1
error: 'x' undefined near line 1 column 29
error: called from
g1 at line 1 column 27
I.e., when you write g1 or g2 here, this is an actual function call. The call to g2 succeeds because g2 does not take any arguments; the syntax g2 is essentially equivalent to g2(). However, the call to g1 fails, because g1 expects an argument, and we didn't provide one.
Compare with:
octave:4> a = #g1;
octave:5> b = #g2;
octave:6> a
a = #g1
octave:7> a(1)
ans = 6
octave:8> b
b = #g2
octave:9> b()
ans = 10
where you have created handles to these functions, which you can capture into variables, and pass them as arguments into functions. These handles could then be called as a(5) or b() inside the function that received them as arguments, and it would be like calling the original g1 and g2 functions.
When you called bisection(f1,0,5), you essentially called bisection(f1(),0,5), i.e. you asked octave to evaluate the function f1 without passing any arguments, and use the result as the first input argument to the bisection function. Since function f1 is defined to take an input argument and you didn't supply any, octave complains that when it tries to evaluate y = x^2 - 4; as per the definition of f1, x was not passed as an input argument and was therefore undefined.
Therefore, to pass a "function" as an arbitrary argument that can be called inside your bisection function, you need to pass a function handle instead, which can be created using the #f1 syntax. Read up on "anonymous functions" on the octave (or matlab) documentation.

Vectorization of function contains the numerical computation of definite integral in octave

I'm trying to fit my data using a formula containing a numerical calculation of definite integrals with infinite limits of integration. For fitting I use octave function leasqr that requires vectorization model function. The following code generates error, that occurs when calling a numerical integration.
nonconformant arguments (op1 is 1x387, op2 is 10x2)
function [fGsAb] = GsAbs (x, p)
Hw = 3108.0 ;
fGsAb = Hw ./ (2.4 .* p(1) .*p(2)) .^2 .* (exp ( - (Hw - p(1) .* x) .^2 ...
./ (2.4 .* p(1) .*p(2)) .^2 ) - exp ( - (Hw + p(1) .* x) .^2 ...
./ (2.4 .* p(1) .*p(2)) .^2 )) ;
endfunction
function [GsDisp] = gauss_disp(x, p)
[GsDisp1, err] = quadgk ( #(z) GsAbs(z, p) ./(z-x), - inf, x - 0.000001 );
[GsDisp2, err] = quadgk ( #(z) GsAbs(z, p) ./(z-x), x + 0.000001 , inf );
GsDisp = GsDisp1 +GsDisp2;
endfunction
h = [200:15:6000];
pin =[1 250];
dd = gauss_disp (h, pin);
If I'm using loop:
for i = 1 : length (h)
dd (i) = gauss_disp (h (i), pin)
endfor
I have no errors, but I cannot use this construction in leasqr. How can I get around this restriction?
Thank you in advance!
Change your gauss_disp.m file from this:
function [GsDisp] = gauss_disp(x, p)
[GsDisp1, err] = quadgk ( #(z) GsAbs(z, p) ./(z-x), - inf, x - 0.000001 );
[GsDisp2, err] = quadgk ( #(z) GsAbs(z, p) ./(z-x), x + 0.000001 , inf );
GsDisp = GsDisp1 +GsDisp2;
endfunction
to this:
function [GsDisp] = gauss_disp(x, p)
GsDisp = arrayfun(#(z) gauss_disp_elementwise(z, p), x)
endfunction
function GsDisp = gauss_disp_elementwise(x, p)
[GsDisp1, err] = quadgk ( #(z) GsAbs(z, p) ./(z-x), - inf, x - 0.000001 );
[GsDisp2, err] = quadgk ( #(z) GsAbs(z, p) ./(z-x), x + 0.000001 , inf );
GsDisp = GsDisp1 +GsDisp2;
endfunction
I.e. make your original function into a helper subfunction that only deals with scalar values, and then use that with arrayfun to get outputs for the entire range of x. This way you can use this in your leasqr function, e.g.:
y = leasqr(h, dd, pin, #gauss_disp);
PS: the arrayfun syntax is just for convenience. you could have easily used a for loop similar to what you used in your question instead.