How to output matrix dimensions together with its content? - matlab

Is it possible to make GNU Octave to output matrix dimensions together with its content? For example, it should produce smth. like this:
octave:1> X = [1 2; 3 4]
X [2x2] =
1 2
3 4
octave:2> X(1,:)
ans [1x2] =
1 2

In MATLAB, create display.m in a folder called #double somewhere in your path with this content:
function display(v)
name = inputname(1);
if isempty(name)
name = 'ans';
end
s = num2cell(size(v));
fprintf('\n%s [%d%s] =\n\n', name, s{1}, sprintf('x%d', s{2:end}));
builtin('disp', v);
end
This way you override the display method for class double, and get exactly what you have described. However, this will not work for other classes like int8, logical or cell. You have to override the method for all classes you are interested in. Example:
>> A=ones(2,2,2)
A [2x2x2] =
(:,:,1) =
1 1
1 1
(:,:,2) =
1 1
1 1

While Mohsen's answer does the job indeed, I felt that a separate m-file is somewhat an overkill for this purpose (especially if you don't want to clutter your directory with additional m-files). I suggest using a local anonymous function one-liner instead (let's name it dispf), so here are its evolution phases :)
The basic anonymous function I came up with is:
dispf = #(x)fprintf('%s =\n\n%s\n', inputname(1), disp(x));
which is essentially equivalent to the output in the command window after entering statements (that do not end with a semicolon, of course). Well, almost... because if inputname returns an empty string, it doesn't print 'ans' (and it should). But this can be corrected:
dispf = #(x)fprintf('%s=\n\n%s\n', ...
regexprep([inputname(1), ' '], '^ $', 'ans '), ...
disp(x));
This is basically using regexprep to match an empty string and replace it with 'ans'. Finally, we append the dimensions after the variable name:
dispf = #(x)fprintf('%s%s =\n\n%s\n', ...
regexprep([inputname(1), ' '], '^ $', 'ans '), ...
strrep(mat2str(size(x)), ' ', 'x'), ...
disp(x));
Now you can plug this one-liner is into any script without the need for an additional m-file!
Example
Just a proof that it's working:
dispf = #(x)fprintf('%s%s =\n\n%s\n', ...
regexprep([inputname(1), ' '], '^ $', 'ans '), ...
strrep(mat2str(size(x)), ' ', 'x'), ...
disp(x));
A = [1 2; 3 4];
dispf(A)
dispf(A(1, :))
The result is as expected:
A [2x2] =
1 2
3 4
ans [1x2] =
1 2

I don't know if it works in Octave, but in MATLAB you can use format debug command and get the dimensions of the array and a bit more:
>> format debug
>> X = [1 2; 3 4]
X =
Structure address = 7d19498
m = 2
n = 2
pr = 373bafa0
pi = 0
1 2
3 4

Here is another way to do it. The advantage of this method is that it can deal with more complicated inputs than the mentioned alternatives.
function show(s)
t = regexp(s,'=');
if any(t)
evalin('caller',['disp(size(' s(t+1:end) ')),' s])
else
evalin('caller',['disp(size(' s ')),' s])
end
To use it, save the function and try this:
show x = rand(3)
show('y = {uint8(8);[6 7 8]}')
Note that it can take the convenient command syntax for simple inputs and that you need the function form with the command in string form for complicated inputs (containing semicolons or apostrophes).

Here is another one. You could either use it to overload #double/display as others have explained, or name it something else and use it as your own custom display function:
function display(x)
% determine whether format is loose or compect
loose = strcmp(get(0,'FormatSpacing'), 'loose');
% print name or ans
name = inputname(1);
if isempty(name), name = 'ans'; end
if loose, disp(' '); end
disp([name ' =']);
if loose, disp(' '); end
% print size
sz = size(x);
if length(sz) == 2
fprintf(' %s: %d-by-%d\n', class(x), sz(1), sz(2));
elseif length(sz) == 3
fprintf(' %s: %d-by-%d-by-%d\n', class(x), sz(1), sz(2), sz(3));
else
fprintf(' %s: %d-D\n', class(x), numel(sz));
end
if loose, disp(' '); end
% print array
disp(x);
end
Note that I changed the format of the output a little bit from what you had:
>> format compact;
>> x = magic(5);
>> display(x)
x =
double: 5-by-5
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9

Related

Return property directly when class is called (Matlab)

I have a class called foo with only property M,
classdef foo
properties
M
end
methods
function obj = foo(arg1)
M=arg1;
end
end
end
and I create the object:
F=foo(1)
In C++ it is possible, that when I call F, that I directly get the value of one chosen variable. In my case I would like to get F.M when I just write F. For example this would allow to write
size(F)
instead of writing
size(F.M)
or defining a method size for my class. Is there a way in MATLAB to achieve this?
Edit: In other words, whenever I write F, I want that MATLAB reads it as F.M.
Edit: I will clarify what I want to acchieve.
My class represents a matrix whose values are multivariate infinite sequences with compact support. Thus I have to do a lot of bookkeeping not to mix up all the indices. Things I want to do with my matrix:
Matrix multiplication.
Convolution.
Upsampling, downsampling.
Everything else which is possible in a vector/matrix space.
I thought this is easier to acchieve when I encapsulate all the meta-data (this are the indices of the 0^th entries of the sequence) together with the data.
Because my class is actually a matrix, most operations work on that class in the same way as on ordinary matrices. Therefore I do not want to code it all over again (Because of code-maintenance, less bugs, code-readability).
In C++ I could do it that way. It seems, my approach to that problem is the wrong one in MATLAB.
You have to overload the function size as I mentioned in my comment.
classdef foo
properties
M
end
methods
function obj = foo(arg)
obj.M = arg;
end
function varargout = size(obj, varargin)
if nargin == 1
varargout = size(obj.M);
elseif nargin == 2 && nargout == 1
varargout = size(obj.M, varargin{1})
else
error('Wrong number of input or output arguments.')
end
end
function ret = mtimes(varargin)
try
ret = varargin{1}.M * varargin{2};
catch
ret = varargin{1} * varargin{2}.M;
end
end
end
end
Console Output:
>> F=foo(0:3);
>> size(F)
ans =
1 4
>> size(F, 2)
ans =
4
>> F*(4:7).'
ans =
38
>> (4:7).'*F
ans =
0 4 8 12
0 5 10 15
0 6 12 18
0 7 14 21
I could continue but preparing the console output for StackOverflow is horrible...

Why does this MD5 Matlab implementation break down for certain message sizes?

The following is an M-file for generating an MD5 digest on a file of ASCII values. I have a string of HEX values and am converting it to ASCII, then writing these values to a file which I pass to the md5 function. I am using two different online MD5 calculators to validate the script's solution. Here is one of them.
The method by which I am converting from HEX string to ACSII is by pairing two hex values and then converting the pairs to ASCII chars which are then written to the file. I know this is being done correctly because I can pass either the HEX string to the above mentioned online calculators or upload their equivalent ASCII representation and they produce the same (valid) result even though the MATLAB script gives the wrong digest.
For some reason, whether the digest is computed correctly or not depends on the number of ASCII values being read from the file. I've tried to understand if there is any pattern to this behavior but I cannot find any. It produces a valid digest for messages with 200,300-to-322, 500,996,998,1008,1010,1050,1070,1076 HEX characters which are first converted to the ASCII file. But not for 1000,1002,1004,1006,1078,1100 HEX characters. In short, I see no method to this madness... any help would be much appreciated.
% md5 Compute MD5 hash function for files
%
% d = md5(FileName)
%
% md5() computes the MD5 hash function of
% the file specified in the string FileName
% and returns it as a 64-character array d.
% The MD5 message-digest algorithm is specified
% in RFC 1321.
% The code below is for instructional and illustrational
% purposes only. It is very clear, but very slow.
% (C) Stefan Stoll, ETH Zurich, 2006
function Digest = md5(FileName)
% Guard against old Matlab versions
MatlabVersion = version;
if MatlabVersion(1)<'7'
error('md5() requires Matlab 7.0 or later!');
end
% Run autotest if no parameters are given
if (nargin==0)
md5autotest;
return;
end
% Read in entire file into uint32 vector
[Message,nBits] = readmessagefromfile(FileName);
%--------------------------------------------------
% Append a bit-1 to the last bit read from file
BytesInLastInt = mod(nBits,32)/8;
if BytesInLastInt
Message(end) = bitset(Message(end),BytesInLastInt*8+8);
else
Message = [Message; uint32(128)];
end
% Append zeros
nZeros = 16 - mod(numel(Message)+2,16);
Message = [Message; zeros(nZeros,1,'uint32')];
% Append bit length of original message as uint64, lower significant uint32 first
Lower32 = uint32(nBits);
Upper32 = uint32(bitshift(uint64(nBits),-32));
Message = [Message; Lower32; Upper32];
%--------------------------------------------------
% 64-element transformation array
T = uint32(fix(4294967296*abs(sin(1:64))));
% 64-element array of number of bits for circular left shift
S = repmat([7 12 17 22; 5 9 14 20; 4 11 16 23; 6 10 15 21].',4,1);
S = S(:).';
% 64-element array of indices into X
idxX = [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...
1 6 11 0 5 10 15 4 9 14 3 8 13 2 7 12 ...
5 8 11 14 1 4 7 10 13 0 3 6 9 12 15 2 ...
0 7 14 5 12 3 10 1 8 15 6 13 4 11 2 9] + 1;
% Initial state of buffer (consisting of A, B, C and D)
A = uint32(hex2dec('67452301'));
B = uint32(hex2dec('efcdab89'));
C = uint32(hex2dec('98badcfe'));
D = uint32(hex2dec('10325476'));
%--------------------------------------------------
Message = reshape(Message,16,[]);
% Loop over message blocks each 16 uint32 long
for iBlock = 1:size(Message,2)
% Extract next block
X = Message(:,iBlock);
% Store current buffer state
AA = A;
BB = B;
CC = C;
DD = D;
% Transform buffer using message block X and the
% parameters from S, T and idxX
k = 0;
for iRound = 1:4
for q = 1:4
A = Fun(iRound,A,B,C,D,X(idxX(k+1)),S(k+1),T(k+1));
D = Fun(iRound,D,A,B,C,X(idxX(k+2)),S(k+2),T(k+2));
C = Fun(iRound,C,D,A,B,X(idxX(k+3)),S(k+3),T(k+3));
B = Fun(iRound,B,C,D,A,X(idxX(k+4)),S(k+4),T(k+4));
k = k + 4;
end
end
% Add old buffer state
A = bitadd32(A,AA);
B = bitadd32(B,BB);
C = bitadd32(C,CC);
D = bitadd32(D,DD);
end
%--------------------------------------------------
% Combine uint32 from buffer to form message digest
Str = lower(dec2hex([A;B;C;D]));
Str = Str(:,[7 8 5 6 3 4 1 2]).';
Digest = Str(:).';
%==================================================
function y = Fun(iRound,a,b,c,d,x,s,t)
switch iRound
case 1
q = bitor(bitand(b,c),bitand(bitcmp(b),d));
case 2
q = bitor(bitand(b,d),bitand(c,bitcmp(d)));
case 3
q = bitxor(bitxor(b,c),d);
case 4
q = bitxor(c,bitor(b,bitcmp(d)));
end
y = bitadd32(b,rotateleft32(bitadd32(a,q,x,t),s));
%--------------------------------------------
function y = rotateleft32(x,s)
y = bitor(bitshift(x,s),bitshift(x,s-32));
%--------------------------------------------
function sum = bitadd32(varargin)
sum = varargin{1};
for k = 2:nargin
add = varargin{k};
carry = bitand(sum,add);
sum = bitxor(sum,add);
for q = 1:32
shift = bitshift(carry,1);
carry = bitand(shift,sum);
sum = bitxor(shift,sum);
end
end
function [Message,nBits] = readmessagefromfile(FileName)
[hFile,ErrMsg] = fopen(FileName,'r');
error(ErrMsg);
%Message = fread(hFile,inf,'bit32=>uint32');
Message = fread(hFile,inf,'ubit32=>uint32');
%Message = fread(hFile);
fclose(hFile);
d = dir(FileName);
nBits = d.bytes*8;
%============================================
function md5autotest
disp('Running md5 autotest...');
Messages{1} = '';
Messages{2} = 'a';
Messages{3} = 'abc';
Messages{4} = 'message digest';
Messages{5} = 'abcdefghijklmnopqrstuvwxyz';
Messages{6} = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
Messages{7} = char(128:255);
CorrectDigests{1} = 'd41d8cd98f00b204e9800998ecf8427e';
CorrectDigests{2} = '0cc175b9c0f1b6a831c399e269772661';
CorrectDigests{3} = '900150983cd24fb0d6963f7d28e17f72';
CorrectDigests{4} = 'f96b697d7cb7938d525a2f31aaf161d0';
CorrectDigests{5} = 'c3fcd3d76192e4007dfb496cca67e13b';
CorrectDigests{6} = 'd174ab98d277d9f5a5611c2c9f419d9f';
CorrectDigests{7} = '16f404156c0500ac48efa2d3abc5fbcf';
TmpFile = tempname;
for k=1:numel(Messages)
[h,ErrMsg] = fopen(TmpFile,'w');
error(ErrMsg);
fwrite(h,Messages{k},'char');
fclose(h);
Digest = md5(TmpFile);
fprintf('%d: %s\n',k,Digest);
if ~strcmp(Digest,CorrectDigests{k})
error('md5 autotest failed on the following string: %s',Messages{k});
end
end
delete(TmpFile);
disp('md5 autotest passed!');
This is quite old, but I looked through the code and I think that you are not handling the message length properly. I also found some issues with way that certain maths were done in MatLAB differently - for instance bitshifting was not used as I had expected, and also integer maths of uint32 variables not always handled the way you'd expect. You need to handle modular math and truncating math manually/explicitly or read the help documents a little more closely regarding those topics. Also, check the character base in your options, char128:255 might not be translating correctly, try using the command to create the message and then paste it into a different interface. Even in matlab if you process that variable even once it will get messed up bad, it comes out as ???????????yadda yadda. If you were using decimal maths you might have introduced an epsilon error as well, but check out the actual length...

Modify script from another script

I have a script that is run inside a loop (some constants are modified at each iteration). Is there a way to comment out a line of the script without modifying the .m file?
UPDATE:
Following the answer from Floris and Matthew Simoneau, I made a function trying to do the same thing (and it works). The skipLineParameter is a string referencing to a base workspace variable that has a value of 0 (don't skipline) or 1 (skipline) :
function skipline(skipLineParameter, parameter, default)
try
a = evalin('base', skipLineParameter);
if ~a
assignin('base', parameter, default);
end
catch
assignin('base', parameter, default);
end
end
This is a possible approach - using a condition that is set in the main program to decide whether to execute a particular line in the script.
If your main program is
for ii = 1:9
skipLine3 = (mod(ii,3)==0);
runSub
end
And runSub.m looks like this:
A = 1;
B = 2;
% modified lines to trap condition where 'skipLine3' doesn't exist:
if ~exist('skipLine3', 'var') skipMe = false; else skipMe = skipLine3; end
if ~skipMe, B=B*2; end
fprintf(1, "for iteration %d B is %d\n", ii, B)
Then the output will be:
for iteration 1 B is 4
for iteration 2 B is 4
for iteration 3 B is 2
for iteration 4 B is 4
for iteration 5 B is 4
for iteration 6 B is 2
for iteration 7 B is 4
for iteration 8 B is 4
for iteration 9 B is 2
As you can see - the skipLine3 parameter, which is set in the main loop (every third iteration), affects whether line 3 (B=B*2) is executed in the script.
I think what you're looking for is a function. Here's how to turn runSub into a function:
function runSub(ii,skip)
A = 1;
B = 2;
if ~skip, B=B*2; end
fprintf(1, 'for iteration %d B is %d\n', ii, B);
You can access it in the loop like this:
for ii = 1:9
skipLine3 = (mod(ii,3)==0);
runSub(ii,skipLine3)
end

Matlab function return value

I have one program that has function and the problem, return value, it has too many output.
Like exempley: y = text the answer comes up
Error in text (line 2)
if nargin == 0
Output argument "array" (and maybe others) not assigned during call to "
C:\Users\name\Documents\MATLAB\text.m>text".
The program text.m reads a txt file that contains a couple of names and numbers like
exemple:
John doughlas 15986
Filip duch 357852
and so on. The program convert them to 15986 Doughlas John and so on.
function array = text(~)
if nargin == 0
dirr = '.';
end
answer = dir(dirr);
k=1;
while k <= length(answer)
if answer(k).isdir
answer(k)=[];
else
filename{k}=answer(k).name;
k=k+1;
end
end
chose=menu( 'choose file',filename);
namn = char(filename(chose));
fid = fopen(namn, 'r');
R = textscan(fid,'%s %s %s');
x=-1;
k=0;
while x <= 24
x = k + 1;
All = [R{3}{x},' ',R{1}{x},' ',R{2}{x}];
disp(All)
k = k + 1;
end
fclose(fid);
Is there anyway to fix the problem without starting over from scratch?
Grateful for all the answers!
You specify the function output argument in the definition, but you don't assign anything to it in the function body.
For example, in
function y = student(j)
your output is y. So you have to assign something to y.
Read more about functions in MATLAB.
Here is a working example.
The first part is to create a function called 'functionA' in a filename 'functionA.m'. Then put the following code inside:
function result = functionA(N,alpha)
result = 5;
return
end
The second part is to create another Matlab file(i.e. upto you to name it) or you can use the Matlab command window even. Then run the following code:
getresult = functionA(100,10);
getresult
After running you get the following answer:
ans =
5

Any trim functions in matlab?

If I have an input like [1 2 3; 4.0 c] and I want it to output it like 1234.0c in matlab. What function can I use ? I am looking for something like trim in php.
Any idea ?
Thanks
You can use this to remove any number of spaces from inside of a string:
>> a = char(' he llo wor ld ');
>> a(isspace(a)) = [] %replaces all of the space with nothing
a =
helloworld
You can use isstrprop function with approppriate categories. For your case,
>> str = '1 2 3; 4.0 c';
>> str(isstrprop(str, 'alphanum') | str == '.')
ans =
1234.0c
You can use functions like isletter, isnumeric, etc. if you like.
Besides, you can create your own function in one line as follows
>> myTrim = #(x)(x(isstrprop(x, 'alphanum') | x == '.'));
>> myTrim(str)
ans =
1234.0c
Note that you ask [1 2 3; 4.0 c] as an input which is not a proper syntax for MATLAB. I assumed you wanted to ask for a string. In addition, trim actually implies removing leading and trailing white space from a string and there is strtrim for this in MATLAB.
It is not a valid MATLAB argument.
But if you have something like
a = ['1', '2' ,'3'; '4', '.','c'];
you can use
a(:)'
to get
142.3c
or
a = a';
a(:)'
to get
123.4c