Numeric Collections App
Last published: March 18, 2002 by 'tgriggs'
Defines 5 Classes
Extends 10 Classes
NumericCollectionsApp adds the four basic numeric methods (+, -, *, /) to collections as well as some other methods that come as a natural follow on.
For years now, I have seen too many instances of ST programmers writing loops which mulitply the elements of one collection by the other. Or decrementing all the values by a single value. Or summing. Etc.
Basic Numeric Protocol
Collections can be sent any of the four basic math messages. And you can make collections be the arguments too. Some examples:
#(1 2 3 4) + #(5 6 7 8) --> #(6 8 10 12)
(Bag with: 2 with: 2 with: 6) / -2 --> Bag (-3 -1 -1)
0.0d * (Set with: 4 with: 5 with: 6) -> Set (0.0d)
#(10 20 30 40) * (4 @ -2) --> (Array with: 40@-20 with: 80@-40 120@-60 with: 160@-80)
Furthermore, when the reciever is an SequenceableInstance, it is possible to use the C style math/assignment operators, so that the receiver is modified, rather than a new instance created.
#(1 2 3 4) /= 5 --> #((1/5) (2/5) (3/5) (4/5))
More Numeric Protocols
Once you've done those four, it is possible and logical to write some others. Some of the more popular ones are sum, min, and max. The min and max will work on anything that understands min: or max: (such as Times and Dates). Browse the method protocols 'numeric operations', 'statistic operations', 'shewart controls', and 'fitting' in Collection and SequenceableCollection. An example is plotting a collection of x and y values in a given box on the screen. Sooner or later, you have to compute the actual pixel points from the x and y values. Using the collection stuff, it might look something like this:
(xVals - xVals min / xVals range) @ (1 - (yVals - yVals min / yVals range)) * box extent + box origin
which is much more concise than the loops and vars one might expect otherwise.
One of the things that we found ourselves doing a lot of is wanting to enumerate over every nth element of a sequence. This is particularly applicable in image processing where colors are usually stored as repeating RGB values. For example, we may want to compute the standard deviation or average of the red content of an image. ReindexedCollections, are collection wrappers which change the indexing scheme. They actually abstract and genericize the concept of reverseDo:. We don't send that message any more, we just send something like:
(sequence by: -1) do: [:each | ...work, work, work...]
The median for the red channel of an 32bit image would be:
(Image fromUser bitsInstVar from: 4 by: 4) median
This package also adds rudimentary support for native FloatArrays. These use a C library to apply the basic numeric protocols to recievers which are known to be all floats. The speed up approaches 18X as the size of the arrays gets larger. See the class side of FloatArrayMathLib for documentation on building the dll for different platforms (it's pretty easy).