12

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
psihodelia
  • 29,566
  • 35
  • 108
  • 157
  • Are you looking for a setting to flip on? If so, I don't think that there is one. You can certainly do it with a print statement however. – Frederick Aug 28 '13 at 17:11
  • I am looking for any beautiful solution, if no setting is possible then maybe a simple function will do this? – psihodelia Aug 29 '13 at 07:12
  • Octave is free software. You are free to change the source to do something different if that's what you want. This freedom is probably the biggest advantage of using free software. Can't you use that instead of writing a separate function? – carandraug Sep 16 '13 at 15:54
  • 1
    My guess is that you can change this somewhere inside 'src/pr-output.cc' (or if you're using the development version, inside 'libinterp/corefcn/pr-output.cc'). – carandraug Sep 16 '13 at 16:02
  • @carandraug: that is indeed one of the benefits of free software, you can just change the [source code](http://hg.octave.org/octave/file/tip/libinterp/corefcn/pr-output.cc#l3445) as you see fit :) – Amro Sep 19 '13 at 09:30

5 Answers5

17

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
Mohsen Nosratinia
  • 9,844
  • 1
  • 27
  • 52
  • I would recommend making a new function like `myDisplay` (overloading builtin functions is not my favorite activity). In that case it will also work on complicated inputs. Try: `x= {uint8(8);[6 7 8];'abc'}` for example. – Dennis Jaheruddin Sep 12 '13 at 12:49
  • 3
    Mohsen, if you really want to be fancy, you should test `get(0,'FormatSpacing')` to see whether MATLAB has `format compact` or `format loose`, and adjust the number of newlines your function displays. – Sam Roberts Sep 12 '13 at 20:35
  • 2
    The newly released R2013b supposedly has a new way to customize the display of objects: http://www.mathworks.com/help/matlab/ref/matlab.mixin.customdisplayclass.html – Amro Sep 12 '13 at 22:23
  • 1
    @SamRoberts Thanks for the tip. I actually thought of adding that but decided against that and just replicated the example in the question. – Mohsen Nosratinia Sep 13 '13 at 06:47
  • 2
    @Amro My understanding is that it is for user-defined classes and cannot be used for built-in classes like `double`. – Mohsen Nosratinia Sep 13 '13 at 06:48
  • @MohsenNosratinia: I think you are right, it wouldn't work here. I'm still on R2013a, so I cant play with it just yet :) – Amro Sep 13 '13 at 07:32
  • Thank you. But your method doesn't work in GNU Octave. Octave shows a warning message however: "warning: function ./display.m shadows a core library function" – psihodelia Sep 17 '13 at 11:44
8

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
Community
  • 1
  • 1
Eitan T
  • 32,660
  • 14
  • 72
  • 109
6

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
Mohsen Nosratinia
  • 9,844
  • 1
  • 27
  • 52
1

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).

Dennis Jaheruddin
  • 21,208
  • 8
  • 66
  • 122
1

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
Amro
  • 123,847
  • 25
  • 243
  • 454