Matlab Issue with functions - matlab

So, i have been doing this work with matlab and every time i try to get the answer a new problem pops up. The one that repeats the most on the prompt is
??? Input argument "x" is undefined.
The work is about deriving with matlab, i have to derive a function with two diferent derivation methods and i have to get that table. Thanks a lot to everyone that trys to answer im very lost with this subject.
clc,clear;
h=1;
x=1.2;
derivada1=derivada_1(x,h);
derivada2=derivada_2(x,h);
for i=0:1:10
fprintf('%.10f %.10f %.10f\n',h*(10.^(-i)),derivada1,derivada2);
end
The function i have to derive is
function [ fx ] = funcion( x )
%UNTITLED2 Summary of this function goes here
% Detailed explanation goes here
fx=x.^3-3*x.^2-x+3;
end
Method1
function [ dfx1 ] = derivada_1( x,h )
%UNTITLED4 Summary of this function goes here
% Detailed explanation goes here
fx=feval(funcion,x);
fh2=feval(fx,x+h);
fh3=feval(fx,x-h);
dfx1=(fh2-fh3)/(2*h);
end
Method 2
function [ dfx2 ] = derivada_2( x,h )
%UNTITLED4 Summary of this function goes here
% Detailed explanation goes here
fx=feval(funcion,x);
fh1=feval(fx,x+2*h);
fh2=feval(fx,x+h);
fh3=feval(fx,x-h);
fh4=feval(fx,x-2*h);
dfx2=(-fh1+8*fh2-8*fh3+fh4)/(12*h);
end
Code
Table of results

You really over-complicated it using feval, it's that simple:
function [ dfx1 ] = derivada_1(x,h )
fh2=funcion(x+h);
fh3=funcion(x-h);
dfx1=(fh2-fh3)/(2*h);
end
The problem with your original code was you didn't use function handles. feval(funcion,x) evaluates funcion and passes the returned values to feval, but funcion requires input arguments. Instead it should be something like feval(#funcion,x) passing a function handle (aka function pointer in other programming languages).

Related

MatLab function, variable output

function [ muln, varargout ] = my_mul( varargin )
%MY_MUL This function is used to multiply numbers.
% My_mul function multiplies array of entered numbers, and outputs single
% solution.
% For example: my_mul(12, 2, 3, 5) gives ans = 360
if nargout >=1
disp('Error, wrong number of output arguments');
varargout{1} = 0;
return
end
if nargin <= 1
disp('Error, small number of input argumnets');
return
else
muln = 1;
for i = 1:nargin
muln = muln*varargin{i};
end
end
end
Hi, everyone, I'm just doing my assignment for uni and have a qiuck question.
How can I make this function to give an error if it is called with more than one output.(It meant to give only one) Thanks!
In your function definition, you have defined your function to allow for an unlimited number of outputs. The keyword varargout is a place-holder for a variable number of outputs.
As you have stated in your question, you only want one possible output which in your case looks to be muln. So if you simply remove varargout from your function definition, MATLAB should automatically throw an error if too many outputs are requested
function muln = my_mul(varargin)
If you ever do need to use varargout but want to place constraints on how many outputs are provided for any given scenario, you can check the number of output arguments that were requested using nargout and then throw an error with the error function.
if nargout > 4
error('my_mul:TooManyOutputs', 'Too many outputs requested');
end
My opinion is that if a return value is expected the function needs to throw. Otherwise the caller (function calling this function) will expect everything to be ok. Note that disp('Error') gives information to the developer, but it does not give the program any indication on what happens. More importantly, the information does not give any indication of where the error occurs. This can force the developer to do heavy debugging just to find the error, which is completely unnecessary.
The use of variable output arguments should only be used in case a different number of output arguments should be expected. An example is some customized plot function
function varargout = myplot(varargin)
filename = '';
idx = find(strcmp(varargin,'filename'));
if (~isempty(idx) && length(varargin)<idx+1 && ~ischar(varargin{idx+1}))
error('filename property must be followed by a directory');
elseif(~isempty(idx))
filename = varargin{idx+1};
varargin([idx,idx+1]) = [];
end
h = plot(varargin{:});
varagout{1} = h;
if (~isempty(idx))
save(filename, h);
end
varagout{2} = filename;
This function works as plot except it saves the figure to file in case a filename is specified. In case the developer needs the handle it will be returned and in case the developer wants the save directory it can be returned as well. None of these arguments are necessary though. The developer may want to use this function as a standard plot function and this means that the user may want to call myplot as myplot(x,y);which does not return a value. Further note that even if 'filename' is not specified, the function can still return 2 outputs. The second output may be an empty array of char, but two outputs for the caller will never cause a crash.
Also, note that no further error handling is required. The only unchecked crashes are in plot and save. How this is handled may be different for different users and this means that it only is reasonable to let the user catch the error and handle it (as he would have done if save or plot would have thrown).
Apart from this you may also want to have a check so that the number of output variables are within the correct range (in this case 0,1 or 2 outputs).

an error received while executing my function?

When I execute the following:
function [ x ] = addya( varargin )
x=varargin{1};
t=varargin{1};
if(nargin>1)
for i=2:nargin
t=t+varargin(i);
end;
end
x=t;
The error i am getting is:
addya(1,1) ??? Undefined function or method
'addya' for input arguments of type 'double'.
please suggest changes and errors.
Make sure this function is saved in a file called addya.m.
Moreover, as mentioned by il_raffa there's a typo - inside the loop: you should access varargin using {}.
The following code works for me when saved as addya.m:
function [ x ] = addya( varargin )
x=varargin{1}; %// Why is this needed?
t=varargin{1};
if(nargin>1)
for i=2:nargin
t=t+varargin{i};
end;
end
x=t;
Also, I would suggest to refrain from using i as a loop index due to possible complication with complex numbers.

Designing Function to Reduce Return Variables in Matlab

This is NOT a question where I need to know how to add A+B in MATLAB. This is more of a code design question.
I have few function files that return a numeric matrix and index info on the matrix. For example
function [Mat1, IdxID, IdxDate, IdxVal, IdxMarker, IdxOpen, ...] = First ()
....
.... % where IdxId = 1 ; IdxDate = 2 ; ...
end
function [Mat1, IdxUid, IdxName, IdxVal, Mat2, IdxUid2, IdxSalary2, ...] = Second ()
....
.... % where IdxUid= 1 ; IdxName= 2 ; ...
end
As you can see the code becomes clunky and when I call these functions, I have to declare an equal number of outputs to catch all the indices. The advantage is if I suddenly swap ID & Date columns, the calling functions do not change as I simply make ID=2, Date=1. I also have the advantage of renaming these variables inside the function.
Is there a better way to do this? I'm testing whether struct or cell can be used for indices. I can't use datasets or cell for returning numeric matrix. Too much time is lost in translating it into numbers. Thanks.
Yes, you can return arrays/cells/structs instead. For instance, id can be a struct with multiple variables. Your function definition could be as follows.
function [Mat, Id] = Second ()
...
end
In your function, have the following set:
Id.Name
Id.Val
Id.Salary
...
If you find that you have multiple structs with the same exact structure, you can even consider objects.
Please clarify with more details on the structure if you want a more detailed answer.

Passing output arguments between functions, code not working

I can't seem to pass a variable from one function to another. I've used functions quite extensively (but I'm still a programming newb), so I'm probably just making a dumb mistake here, but I can't for the life of me find it! This is what I'm doing.
My first function
function [ ToFparam ] = ToF_3D_Viewer( ToFparam, RGBparam, Naviparam, DICOMparam )
ToF_2_DICOM_Coords(ToFparam,Naviparam,DICOMparam);
disp(ToFparam.ROI.XYZ_DICOM); %says it's a non-existent field!
end
My second function
function [ ToFparam ] = ToF_2_DICOM_Coords( ToFparam, Naviparam, DICOMparam )
Naviparam.Endotip_2_Tracker = diag([1,-1,-1,1]);
[m,n,z]=size(ToFparam.ROI.XYZ);
ToFparam.ROI.XYZ_DICOM=reshape(inv(Naviparam.data.Endo_RefHomMat(1:3,1:3))*inv(Naviparam.Endotip_2_Tracker(1:3,1:3))*(reshape(ToFparam.ROI.XYZ,[m*n z]))')',[m n z]);
disp(ToFparam.ROI.XYZ_DICOM) %outputs correctly!
end
I also tried changing my first function to the following, but when I later try to add ToFparam.ROI.XYZ_DICOM to another matrix of the same size, which clearly outputs as a matrix in my ToF_2_DICOM_Coords function, it throws an error, saying I can't add a variable of type "structure"
function [ ToFparam ] = ToF_3D_Viewer( ToFparam, RGBparam, Naviparam, DICOMparam )
ToFparam.ROI.XYZ_DICOM = ToF_2_DICOM_Coords(ToFparam,Naviparam,DICOMparam);
disp(ToFparam.ROI.XYZ_DICOM); %says it's a non-existent field!
end
Thanks in advance
You should ask for a return value in youre function call to ToF_2_DICOM_Coords,
function [ ToFparam ] = ToF_3D_Viewer( ToFparam, RGBparam, Naviparam, DICOMparam )
Tofparam = ToF_2_DICOM_Coords(ToFparam,Naviparam,DICOMparam);
disp(ToFparam.ROI.XYZ_DICOM); %says it's a non-existent field!
end

How to write a function that does not throw a "wrong number of arguments" error

I am trying to write a minimal function that can be called with a variable number of arguments but that will not throw a wrong number of arguments error if miscalled.
Here is where I start from :
function varargout=fname(varargin)
% FNAME
% Usage: output=fname(input)
% Arguments check
if(nargin~=1 || nargout~=1)
disp('Function fname requires one input argument');
disp('and one output argument');
disp('Try `help fname`');
varargout(1:nargout)={0};
return;
end
input=varargin{1};
output=input;
varargout(1)={output};
end
However this does not work as I would like it to. Is there a way to write a function that :
never throw a "wrong number of arguments" error (so that the rest of the execution can continue)
accepts variable number of input and output arguments and checks them inside the function
(maybe more tricky) if the number of input / output arguments is not correct, does not replace the value of the provided output arguments (so that any misplaced call does not erase the previous value of the output argument)
I am open to any suggestions / other methods.
Thank you for your help.
UPDATE: thanks to #Amro for his answer, I guess what I miss here is either a call by address of reference for Matlab functions or a way to interrupt a function without returning anything and without stopping the rest of the execution.
Here is one way to implement your function:
function varargout = fname(input,varargin)
%# FNAME
%# Usage: output=fname(input)
%%# INPUT
if nargin<1
varargout(1:nargout) = {[]};
warning('Not enough input arguments.'), return
end
if ~isempty(varargin)
warning('Too many input arguments.')
end
%%# YOUR CODE: manipulate input, and compute output
output = input;
%%# OUTPUT
varargout{1} = output;
if nargout>1
warning('Too many output arguments.')
varargout(2:nargout) = {[]};
end
end
Obviously you can customize the warning messages to your liking...
Also, if you want your function to simply print the message instead of issuing warnings, replace all WARNING calls with simple DISP function calls.
Examples of function call:
fname()
fname(1)
fname(1,2)
x = fname()
x = fname(1)
x = fname(1,2)
[x,y] = fname()
[x,y] = fname(1)
[x,y] = fname(1,2)
The above calls execute as expected (showing warning messages when applicable). One caveat though, in the last three calls, if the variable y already existed in the workspace prior to the calls, it would be overwritten by the empty value y=[] in each...
If I understand your question correctly, then the answer is no. If a caller calls a function like this:
[a, b, c] = fname('foo');
then fname is required to return (at least) three outputs. There's no way to tell MATLAB that it should leave b and c alone if fname only returns one output.