Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MATLAB: Is it possible to overload operators on native constructs (cells, structs, etc)?

I'm using cells to manage data in some stuff I'm working on. I'd like to be able to do things like:

A = cellfun( @(X)( randn( 5,5 ) ), cell( 5,1 ), 'UniformOutput', 0 );
B = cellfun( @(X)( randn( 5,5 ) ), cell( 5,1 ), 'UniformOutput', 0 );
%#
%# Each of the following would fail if cell member dimensions
%# don't match up
%#
%# matrix sums for each cell entry
%# C = A + B;
C = cellfun( @(X,Y)( X + Y ), A, B, 'UniformOutput', 0 );
%#
%# direct/hadamard product
%# D = A .* B;
D = cellfun( @(X,Y)( X .* Y ), A, B, 'UniformOutput', 0 );
%#
%# matrix-matrix products (not across all entries)
%# E = A * B;
E = cellfun( @(X,Y)( X * Y ), A, B, 'UniformOutput', 0 );

However, I don't want the extremely verbose syntax to do it. It seems a bit overboard to create a new class for this when all I want to do is provide a definition for math operators on cells.

The question: Is a class the only way to go about it?

If I write a class to do this, it certainly makes it easier to write the code. The biggest negatives I see are related to optimizations, though there's a few other things that bug me about it..

Any optimizations going on behind the scenes (eg, when Jacket compiles something to run on a GPU) would potentially have a harder time determining what optimizations to make. As an example, suppose I have two cells (A,B) containing a number of matrices of appropriate dimension. If I write code to produce a new cell:

Z = c1*A + c2*B

... with scalars {c1,c2}, I can write it in such a way that Jacket (or whatever) will easily determine that it should do the calculations as:

Z{kk} = c1*A{kk} + c2*B{kk}

or perhaps an even better optimization than that. Otherwise. it may end up with something slower and/or less memory efficient, eg:

temp1 = cellfun( @(X)( c1*X ), A );
temp2 = cellfun( @(X)( c2*X ), B );
Z     = cellfun( @plus, temp1, temp2 );

Assuming MATLAB or Jacket are unable to optimize it, this would end up using too much memory.

like image 947
Brian Vandenberg Avatar asked Mar 19 '11 22:03

Brian Vandenberg


1 Answers

It is in fact possible to create new operators or overload existing ones for built-in data types in MATLAB. I describe one example of this in my answer to another SO question about modifying the default overflow behavior of integer types.

First, you may want to look at what methods currently exist for cell arrays. You can do this using the function METHODS, and here's what I get in MATLAB R2010b:

>> methods cell

Methods for class cell:

aa2nt            issorted         regexptranslate  strfind          
accumarray       newdepfun        reshape          strjust          
cell2struct      nt2aa            rna2dna          strmatch         
ctranspose       nwalign          seq2regexp       strtok           
display          permute          setdiff          transpose        
dna2rna          regexp           setxor           union            
intersect        regexpi          sort             unique           
ismember         regexprep        strcat           

The arithmetic operator methods would show up in the above list as their function equivalents, like plus for the + operator or times for the .* operator. Only the transpose method (.' operator) is defined for cell arrays. You would have to create the rest yourself, defining how a given operator will behave for cell arrays arguments.

You can do this by first making a new folder called @cell and placing it in an existing folder on your MATLAB path. You would then place your new methods in the @cell folder. For example, a very simple implementation of a plus method for cell arrays (without any input-checking, error-checking, etc.) would be this:

function C = plus(A,B)
  C = cellfun(@plus,A,B,'UniformOutput',false);  %# Apply plus cell-wise
end

In the above code, you would probably first want to check that the operands A and B are cell arrays of the same size. However, you could create whatever unique functionality you want, such as allowing B to be a scalar value which would get added to every cell of A. It's totally up to you to define how the + operator will behave for cell arrays.

This would then allow you to write your code in a much more compact way, as in this example:

>> A = {[1 2 3] [4 5] 6};  %# One 3-element cell array
>> B = {5 [4 5] 2};        %# Another 3-element cell array
>> C = A+B;                %# Use the new plus operator
>> C{:}                    %# Display the cell contents

ans =

     6     7     8

ans =

     8    10

ans =

     8

I can't really speak to the behind-the-scenes optimizations and how this might affect them. I know that the documentation "Techniques for Improving Performance" specifically mentions this about overloading built-in functions:

Overloading MATLAB built-in functions on any of the standard MATLAB data classes can negatively affect performance. For example, if you overload the plus function to handle any of the integer classes differently, you may hinder certain optimizations in the MATLAB built-in function code for plus, and thus may slow down any programs that make use of this overload.

However, in your case you aren't overloading existing functions for a class. You're simply creating new ones that didn't exist for that class, so it's hard to say what effect this may ultimately have on performance.

like image 139
gnovice Avatar answered Sep 29 '22 08:09

gnovice