Tue 20 May 2008
Non-recursive MATLAB Code for Finding Positive/Negative/Zero Matrix Elements and Their Bit Masks
Posted by BJ Sintay under Science, Software, Tech-talk
No Comments
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.
This past week I reconnected with an old floppy disk game Space Quest 1 (VGA edition) by Sierra. Luckily I have backups of my floppies now, because the disks no longer work. If you’re holding on to old floppies, you may be surprised to discover that the data is no longer there! Anyways, I played the game through in about 3 hours the other night and really enjoyed it. Space Quest 1 is an old Sierra RPG in which you are a janitor given the job of saving the universe. The game is a ton of fun and was one of my favorite computer games when I was younger. What’s funny is this game has to run on DosBOX, an emulator of DOS. It’s hard to imagine we already need emulators for those games in a Windows environment.