Generalized Arithmetic Operators


Recently, in a discussion on the MATLAB newsgroup, comp.soft-sys.matlab, several MATLAB users suggested that it would be nice if MATLAB would allow you to write things like

    Y = X - mean(X)
where X is an N-by-M matrix and you want to return each column minus its mean. Currently you have to write something like
    Y = X - repmat(mean(X),[N,1])
which requires extra memory to replicate the single row of mean(X), extra time to do it and isn't as clean looking.

Generalizing this idea for N-dimensional arrays, what we want to do is compare the dimensions of the two operands and copy singleton dimensions in one to match the size of the other, without actually copying any data. Here are some examples for

    Z = X + Y
size(X) size(Y) size(Z) equivalent code
[5 3] [1 3] [5 3] Z = X + repmat(Y,[5 1])
[5 1] [1 3] [5 3] Z = repmat(X,[1 3]) + repmat(Y,[5 1])
[4 5 1 7] [4 1 6 7] [4 5 6 7] Z = repmat(X,[1 1 6 1]) + repmat(Y,[1 5 1 1])
[4 5] [4 5 6 7] [4 5 6 7] Z = repmat(X,[1 1 6 7]) + Y
[4 5] [1 1 6 7] [4 5 6 7] Z = repmat(X,[1 1 6 7]) + repmat(Y,[4 5 1 1])

Without changing the core code of MATLAB it is possible to implement this with MEX functions and operator overloading. I have written a C MEX program, genops.c, to do this. This single source file can be used to generate MEX files to overload the following built-in MATLAB functions: plus, minus, times, rdivide, ldivide, power, eq, ne, lt, gt, le and ge. Also included in the package are a function to switch this functionality on or off and a function to compile genops.c with the required compiler directives to generate all the MEX files.

To install this on your system first obtain the three files (genops.c, genops.m and makegenops.m) and create a directory on your MATLAB path called genopsfun and a directory called src inside that. Install the three files like this, putting genops.c inside the src directory:

  genopsfun (directory)
    genops.m
    makegenops.m 
    src (directory)
      genops.c

The makegenops.m program will create a directory called doubleops and a directory inside that called @double which will contain all the MEX files. By adding or removing doubleops from the path (using the genops.m function) we can switch this new functionality on or off.