Tue 20 May 2008
MATLAB (the scientific computing software) has a lot of built-in functions for doing various matrix operations quickly without using loops (for, while, etc.). When you’re computing vast amounts of data, this can save a lot of time as each loop iteration eats compute cycles.
Today I needed a function that returned only the positive elements of a matrix. I was surprised to find that MATLAB does not include this as a built-in function. A quick google search came up empty. It’s very easy to write a program to search for elements that are postive by iterating through all the elements of a matrix and forming either a mask (a matrix of 1’s and 0’s - 1’s for positives) or directly generating the matrix needed. However, this does not keep with the idea of avoiding loops.
Here is the solution I came up with. First of all, let’s do some math. If you add the absolute value of a negative number to itself, you’ll get zero.
Example: -2+|-2| = 0
For positive numbers you’ll end up with two times the number…
Example: 3+|3| = 6
Thus, an equation to get only the positive (elements) numbers, where X is any matrix of numbers is:
X + |X| / 2 = positive numbers of X
In MATLAB this is coded as:
MATLAB > (X+abs(X))./2
Now, let’s get a bit mask out of this. All we need to do is divide the matrix X by itself to get ones since anything divided by itself equals one (x/x = 1). However, this method will produce “divide by zero” warnings in MATLAB if you have zeros in your matrix. A simple fix is to use binary arithmatic instead of dividing the matrix by itself. The following will produce the mask of positive elements:
MATLAB > ((X+abs(X))./2)&1
In this case the positive values are converted to 1’s by performing a binary AND with 1 on the matrix. Now we have a nice bit mask to work with for the next step of finding the negative numbers. Taking the code from before and inverting it gives us a mask of non-positives (includes zeros). But the zeros will fall out when multiplied by the original matrix. That gives us this code of the negative elements of the matrix:
MATLAB > ~(((X+abs(X))./2)&1).*X
If a mask of negative elements is desired, simple use the binary AND operator again.
MATLAB > ~(((X+abs(X))./2)&1).*X&1
And finally if we want a mask of zeros in the matrix, we can combine both masks and invert.
MATLAB > ~((~(((X+abs(X))./2)&1).*X&1)+(((X+abs(X))./2)&1))
These pieces of code allow efficient computation of positive, negative, and zero elements as well as their corresponding bit masks.
