A new version of Collections was added to project The Inbox:
http://source.squeak.org/inbox/Collections-cbc.769.mcz ==================== Summary ==================== Name: Collections-cbc.769 Author: cbc Time: 27 November 2017, 1:21:09.685285 pm UUID: 59c54629-954c-504d-87a9-cb745d5e9188 Ancestors: Collections-nice.768 Updated Matrix comment to be consistent by itself (instead of only in comparison to Array2D, which isn't in the system). Added ...ifAbsent: pairs to the ...ifInvalid: calls, to be more standard, but left the ...ifInvalid: in place (useful if you want to present the matrix is not fixed size). Added some nicer named methods like #atRow:column: to be more specific about what is called, but left old #at:at: to not inconvenience previous users. =============== Diff against Collections-nice.768 =============== Item was changed: Collection subclass: #Matrix instanceVariableNames: 'nrows ncols contents' classVariableNames: '' poolDictionaries: '' category: 'Collections-Unordered'! + !Matrix commentStamp: 'cbc 11/27/2017 13:10' prior: 0! + I represent a two-dimensional array. - !Matrix commentStamp: '<historical>' prior: 0! - I represent a two-dimensional array, rather like Array2D. - There are three main differences between me and Array2D: - (1) Array2D inherits from ArrayedCollection, but isn't one. A lot of things that should work - do not work in consequence of this. - (2) Array2D uses "at: column at: row" index order, which means that nothing you write using - it is likely to work either. I use the almost universal "at: row at: column" order, so it is - much easier to adapt code from other languages without going doolally. - (3) Array2D lets you specify the class of the underlying collection, I don't. + I use an underlying Array to hold the elements, but present a row by column access to the array. In particular, I use the almost universal "at: row at: column" order, so it is much easier to adapt code from other languages without going doolally. + Structure: nrows : a non-negative integer saying how many rows there are. ncols : a non-negative integer saying how many columns there are. contents : an Array holding the elements in row-major order. That is, for a 2x3 array + the contents are (11 12 13 21 22 23). + (show in graphical form: + 11 21 + 12 22 + 13 23 + ) - the contents are (11 12 13 21 22 23). Array2D uses column major order. + Another reason (besides speed) for always insisting on an Array is that letting it be something - You can specify the class of 'contents' when you create a new Array2D, - but Matrix always gives you an Array. - - There is a reason for this. In strongly typed languages like Haskell and Clean, - 'unboxed arrays' save you both space AND time. But in Squeak, while - WordArray and FloatArray and so on do save space, it costs time to use them. - A LOT of time. I've measured aFloatArray sum running nearly twice as slow as - anArray sum. The reason is that whenever you fetch an element from an Array, - that's all that happens, but when you fetch an element from aFloatArray, a whole - new Float gets allocated to hold the value. This takes time and churns memory. - So the paradox is that if you want fast numerical stuff, DON'T use unboxed arrays!! - - Another reason for always insisting on an Array is that letting it be something else would make things like #, and #,, rather more complicated. Always using Array is the simplest thing that could possibly work, and it works rather well. - I was trying to patch Array2D to make more things work, but just couldn't get my head - around the subscript order. That's why I made Matrix. - Element-wise matrix arithmetic works; you can freely mix matrices and numbers but don't try to mix matrices and arrays (yet). Matrix multiplication, using the symbol +* (derived from APL's +.x), works between (Matrix or Array) +* (Matrix or Array). Don't try to use a number as an argument of +*. Matrix * Number and Number * Matrix work fine, so you don't need +* with numbers. Still to come: oodles of stuff. Gaussian elimination maybe, other stuff probably not. + + original author: roak! - ! Item was changed: ----- Method: Matrix>>at:at: (in category 'accessing') ----- at: row at: column + ^self atRow: row column: column! - ^contents at: (self indexForRow: row andColumn: column)! Item was added: + ----- Method: Matrix>>at:at:ifAbsent: (in category 'accessing') ----- + at: r at: c ifAbsent: absentBlock + ^self atRow: r column: c ifAbsent: absentBlock! Item was changed: ----- Method: Matrix>>at:at:ifInvalid: (in category 'accessing') ----- at: r at: c ifInvalid: v "If r,c is a valid index for this matrix, answer the corresponding element. Otherwise, answer v." + ^self atRow: r column: c ifAbsent: [v] + "Note: the ..ifInvalid: option is useful is pretending the matrix isn't a fixed size."! - - (r between: 1 and: nrows) ifFalse: [^v]. - (c between: 1 and: ncols) ifFalse: [^v]. - ^contents at: (r-1)*ncols + c - ! Item was changed: ----- Method: Matrix>>at:at:put: (in category 'accessing') ----- at: row at: column put: value + ^self atRow: row column: column put: value! - ^contents at: (self indexForRow: row andColumn: column) put: value! Item was added: + ----- Method: Matrix>>atRow:column: (in category 'accessing') ----- + atRow: row column: column + ^contents at: (self indexForRow: row andColumn: column)! Item was added: + ----- Method: Matrix>>atRow:column:ifAbsent: (in category 'accessing') ----- + atRow: r column: c ifAbsent: absentBlock + "If r,c is a valid index for this matrix, answer the corresponding element. + Otherwise, answer absentBlock value." + + (r between: 1 and: nrows) ifFalse: [^absentBlock value]. + (c between: 1 and: ncols) ifFalse: [^absentBlock value]. + ^contents at: (r-1)*ncols + c + ! Item was added: + ----- Method: Matrix>>atRow:column:put: (in category 'accessing') ----- + atRow: row column: column put: value + ^contents at: (self indexForRow: row andColumn: column) put: value! |
Free forum by Nabble | Edit this page |