I defined the following class
classdef TimerManager < handle
methods (Access = private)
function obj = TimerManager()
end
end
methods (Static)
function singleObj = getInstance(varargin)
varargin{1}
singleObj = TimerManager();
end
end
methods
function foo(obj)
end
end
end
I found the following code works differently w/ or w/o ;
Is this expected? or if I missed anything?
>> TimerManager.getInstance(0).foo()
ans =
0
>> TimerManager.getInstance(0).foo();
Index exceeds matrix dimensions.
Error in TimerManager.getInstance (line 13)
varargin{1}
If I use nargin in side getInstance, it is 0 if I put ; at the end.
Your error has nothing to do with the semi-colon. This has to do with the way that MATLAB handles subscripted referencing of objects (subsref).
The (Detailed) Issue
In MATLAB, you cannot "chain" subscripted referencing. For example if we create a cell array, we can't immediately index into this cell array without first assigning it to a temporary variable:
X1 = {'X1', 'X2', 'X3'}{1}
Error: Unbalanced or unexpected parenthesis or bracket.
The same applies for accessing the property or method of an object which is returned by a function. In your case, TimerManager.getInstance returns an instance which you must first assign to a temporary variable before being able to access it's foo method.
instance = TimerManager.getInstance(0);
fooResult = instance.foo();
MATLAB makes an attempt to throw an error or warning when it thinks that you're trying to "chain" these subscript references together, but if there is a scenario where an order of subscript operations is valid, then it is unable to throw the appropriate error. You are experiencing one of those cases.
The syntax that you are using is something like the following:
a.b(c).d()
This is valid if a.b is an array of structs with a field of d which is a function handle. In this case, c is an index.
When MATLAB parses this, it's going to retrieve the value of a.b, then ensure that c is a positive integer (a valid index) and is within the bounds of the array a.b. Then once that's been confirmed, MATLAB will access the d field and invoke it.
If we go back to your code for a second, we can comment out the varargin{1} line and get a more useful error message.
TimerManager.getInstance(0).foo();
Subscript indices must either be real positive integers or logicals.
Ok so that kind of makes sense, MATLAB is treating TimerManager.getInstance as a struct array and trying to index into it with the 0 which is obviously invalid and results in the error.
With respect to the actual error that you reported, note above that I said that before applying subscript referencing on the supposed struct array, MATLAB needs to first get the current value of TimerManager.getInstance. Because MATLAB thinks that this is just a struct array it's not going to pass any input arguments to it and this is resulting in varargin being empty and the error that you're seeing.
So your statement is functionally the same as:
instance = TimerManager.getInstance; % No input arguments
instance(0).foo() % Indexing error
Note that this does work if the "input" to getInstance is 1 since this is a valid index into the 1 x 1 array of TimerManager instances returned when you call Timermanager.getInstance with no inputs.
TimerManager.getInstance(1).foo();
Potential Solutions
Use a temporary variable
instance = TimerManager.getInstance(0);
fooResult = instance.foo();
Or use the method(obj) notation for invoking the method rather than the obj.method() notation.
foo(TimerManager.getInstance(0))
A Note on Octave
None of this is going to be an issue in Octave since it allows "chaining" these subscript references together without the need for a temporary variable.
Related
classdef Dog
methods
function out = bark(obj, text)
% disp(text)
out = 1;
end
function ind = end(~, ~, ~)
error("`end` forbidden")
end
end
end
d=Dog(), d(end) will error but d.bark(end) won't.
Uncommenting disp(text) instead errors as Not enough input arguments, but that's not same as forbidding end as input to bark.
d.bark(end, end) errors as Too many input arguments.
Can end be forbidden (or detected) as input to any method of d?
It looks like d.bark(end) calls d.bark first, obtaining the output array out, then calls end(out,1,1). This end is not your overloaded function, it is the version for whatever type out is, which in your case is double. So this is the built-in out. This end returns 1. Finally, it calls d.bark(1).
I think this is a strange behavior. MATLAB only does this for class methods, not for free functions. For example sqrt(end) or eps(end) give the error "The end operator must be used within an array index expression.".
I don't think there is a way around this, it is built-in MATLAB behavior, it would require changing the interpreter to override the behavior.
I hope this is the right area. I'm trying to get this code to work in MatLab.
function y=test(x)
y=-x+(B/(B-1))*(r-a)*p+(B/(B-1))*(r-a)*(b((1-(b/x)^(B-1))/r- a)+p* ((b/x)^B))/(1-(b/x)^B);
end
I then jump to the command value and type this:
B=3.0515;
b=1.18632*10^5;
a=.017;
r=.054;
p=5931617;
I then try to find the zeros of the first equation by typing this and I get errors:
solution=fzero(#test,5000000)
I'm getting the following error:
Error: File: test.m Line: 5 Column: 1 This statement is not
inside any function. (It follows the END that terminates the
definition of the function "test".)
New error
Error using fzero (line 289)
FZERO cannot continue because user supplied function_handle ==> #(x)
(test(x,B,b,a,r,p))
failed with the error below.
Subscript indices must either be real positive integers or logicals.
I would guess that this is a problem of scoping, you are defining variables (B, b, etc...) in the command line but trying to use them inside your test function where they are out of scope. You should alter your test function to take these in as parameters and then use an anonymous function so that your call to test in fsolve still only takes a single parameter:
function y=test(x, B, b, r, a, p)
y=-x+(B/(B-1))*(r-a)*p+(B/(B-1))*(r-a)*(b((1-(b/x)^(B-1))/r- a)+p* ((b/x)^B))/(1-(b/x)^B);
end
and
B=3.0515;
b=1.18632*10^5;
a=.017;
r=.054;
p=5931617;
solution=fzero(#(x)(test(x,B,b,a,r,p)),5000000)
As an aside, unless you really do mean matrix multiplication, I would suggest that you replace all your *s and /s in test with the element-wise operators .* and ./. If you are dealing with scalars, it doesn't matter now, but it makes a big difference if you later want to scale your project and need a vectorized solution.
Regarding the errors you have added to your question:
You can't put code after the end in your function file. (With the exception of local functions). Your objective function should be an .m-file containing the code for one single function.
This is because in your test function you have ...b((1-(b/x)^(B-1))... which in MATLAB means you are trying to index the variable b in which case the value of (1-(b/x)^(B-1) has to be a positive integer. I'm guess you are missing a *
Your
function y=test(x)
y=-x+(B/(B-1))*(r-a)*p+(B/(B-1))*(r-a)*(b((1-(b/x)^(B-1))/r- a)+p* ((b/x)^B))/(1-(b/x)^B);
end
cannot access variables in your workspace. You need to pass the values in somehow. You could do something like:
function y=test(x,B,b,a,r,p)
y=-x+(B/(B-1))*(r-a)*p+(B/(B-1))*(r-a)*(b((1-(b/x)^(B-1))/r- a)+p* ((b/x)^B))/(1-(b/x)^B);
end
and then you can create an implicit wrapper function:
B=3.0515;
b=1.18632*10^5;
a=.017;
r=.054;
p=5931617;
solution = fzero(#(x) test(x,B,b,a,r,p),5000000)
I haven't tested whether fzero returns sensible results, but this code shouldn't give an error.
I have used MatLab to write the following code for Horner's Algorithm
function [answer ] = Simple( a,x )
%Simple takes two arguments that are in order and returns the value of the
%polynomial p(x). Simple is called by typing Simple(a,x)
% a is a row vector
%x is the associated scalar value
n=length(a);
result=a(n);
for j=n-1:-1:1 %for loop working backwards through the vector a
result=x*result+a(j);
end
answer=result;
end
I now need to add an error check to ensure the caller uses integer values in the row vector a.
For previous integer checks I have used
if(n~=floor(n))
error(...
But this was for a single value, I am unsure how to do this check for each of the elements in a.
You've got (at least) two options.
1) Use any:
if (any(n ~= floor(n)))
error('Bummer. At least one wasn''t an integer.')
end
Or even more succinctly...
assert(all(n == floor(n)), 'Bummer. At least one wasn''t an integer.')
2) Use the much more capable validateattributes:
validateattributes(n, {'double'}, {'integer'})
This function can check for more than a dozen other things, too.
Same math will work, but is now checking each element. Try this:
if any(n~=floor(n))
error(...
I'm using MATLAB to access a postgresql database. I'm running into problems trying to access a column of type boolean[]:
x;#% x is a <1x1 org.postgresql.jdbc4.Jdbc4Array>
When accessing real[] values, I can take the following approach:
double(x.getArray());
Unfortunately, with a boolean[] this leads to the following error message:
Undefined function 'toDouble' for input arguments of type 'logical'.
So I figured converting to logical first may work:
logical(x.getArray());
Except this doesn't work either.
Error using logical
Conversion to logical from java.lang.Boolean[][] is not possible.
The problem may arise because java.lang.Boolean doesn't derive from java.lang.Number, however the MATLAB docs on conversion of java return types make it seem like this shouldn't be a problem.
Am I doing something wrong here? How do I get from the fetch result to a logical array usable in MATLAB? If all else fails, I can rebuild the tables with arrays of numeric types instead of boolean[], but it seems like this should be possible without going that far.
I suspect that this is due to the difference in Java between Boolean (an object) and boolean, a primitive. Matlab conversions are really set up to handle primitives, not necessarily their associated object wrappers.
I think that this conversion requires a loop, as follows:
%Setup test
b = java.lang.Boolean.FALSE;
array = java.lang.reflect.Array.newInstance(b.getClass(), [5 6]);
for ix1=1:length(array);
for ix2 = 1:(length(array(1)));
array(ix1, ix2)=b;
end;
end;
%Now `array` is an initialize 2D Java array of type Boolean.
%To convert to a Matlab logical array
matArray = false(length(array), length(array(1))); %Initialize
for ix1=1:size(matArray, 1);
for ix2 = 1:size(matArray, 2);
matArray(ix1, ix2)=(array(ix1, ix2).booleanValue());
%The `booleanValue()` method converts from `Boolean` class to `boolean` primitive
end;
end;
Suppose I have a column matrix pols containing vectors of [theta, rho, z].
Which means, if I have 9 such vectors, it will be a 9x3 matrix.
It is quite handy to have them arranged as such, because I can just feed any one of them to functions like pol2cart:
cart3 = pol2cart(pols(3,:));
and for a certain vector, I can find its components via the indices 1, 2, 3:
rho5 = pols(5,2);
But sometimes the matrix is actually within another wider matrix, and could be in the middle instead of the beginning, such that the above might become:
rho5 = pols(5,6);
In order to make the code more readable in case someone else has to maintain it, is there anyway to refer to an index via a unique name? Like
rho5 = pols(5).rho;
where it could be defined earlier that .rho maps to the column which has the value of rho.
I've ventured into converting matrices to cells then to array using mat2cell and cell2struct but it doesn't seem practical. Or, I could make an array of structs, but then I lose the ability to do pol2cart(pols), and instead must do
pol2cart(pols.theta, pols.rho, pols.z);
So to repeat the question: can I map the indices to unique names?
For the default MATLAB data types, no, you can't really do that. You could, however, create your own new data type (i.e. class object) to store your data. Within the class definition you would overload the subsref method to define how subscripted referencing (i.e. using (), {}, or .) behaves for your new object. This could get rather tricky with regards to dealing with arrays of objects, but it is possible.
Note that you would also have to create overloaded methods for all the existing functions you want to use on your new data type. Specifically, you would have to create a pol2cart method for your object that could internally call the built-in pol2cart function with the appropriate pieces of data from your object passed as arguments.
...And this brings me to a simpler solution for your current situation. Instead of making a whole new type of class object, you could create a structure array (or scalar structure of arrays) to store your data and simply create a new overloaded pol2cart function specifically for struct data types that will simplify the calling syntax.
I discuss more details of overloading functions for built-in data types in two other answers here and here. In short, you would create a folder called #struct and place it in a folder on your MATLAB path. In this #struct folder you would then put this overloaded function:
function varargout = pol2cart(polarCoordinates)
[varargout{1:nargout}] = pol2cart(polarCoordinates.theta, ...
polarCoordinates.rho, ...
polarCoordinates.z);
end
Note that this is a stream-lined version of the function, without error checks on the input, etc. Now, let's make some sample data:
pols = rand(9, 3); %# A 2-D array of data
polStruct = struct('theta', pols(:, 1), ... %# Convert it to a scalar
'rho', pols(:, 2), ... %# structure of arrays
'z', pols(:, 3));
And you could access the rho value of the fifth row as follows:
rho5 = pols(5,2);
rho5 = polStruct.rho(5);
If you wanted to convert from polar to cartesian coordinates, here's how you would do it for each data type:
[X,Y,Z] = pol2cart(pols(:,1), pols(:,2), pols(:,3)); %# Calls the built-in one
[X2,Y2,Z2] = pol2cart(polStruct); %# Calls the overloaded one
And you can check that they each give identical results as follows:
>> isequal([X Y Z],[X2 Y2 Z2])
ans =
1 %# True!
OK, the formal answer is probably "no" as given by woodchips above. However, if you really want to do something like that, you might be able to use a semi-hack. Specifically, you can define a class and overload an operator to achieve (almost) what you want. Unfortunately, I see that Matlab doesn't allow overloading ., so you have to use some other operator. (see edit below)
Just to give you the idea, here is a class that returns the i-th row of a matrix M by M^i.
classdef Test
properties
M;
end
methods
function this = Test(M)
this.M = M;
end
function res = mpower(this, i)
res = this.M(i, :);
end
end
end
And it can be run like this:
>> tmp = Test([1 2; 3 4]);
>> tmp^1
ans =
1 2
>> tmp^2
ans =
3 4
Use at your own risk! :)
Edit:
I was wrong above. As mentioned in gnovice's answer you can actually define the . operator for a custom class using method subsref.
No. You cannot do so. As simple as that.