• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PolyMathOrg / DataFrame / 13409391746

19 Feb 2025 09:30AM UTC coverage: 94.756%. Remained the same
13409391746

push

github

web-flow
Enable Pharo 12 and 13 for the CI

13571 of 14322 relevant lines covered (94.76%)

4.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

20.8
/src/DataFrame/Array2D.class.st
1
"
2
I represent a mathematical matrix or a two-dimensional array. I provide methods for creating matrices, operating on them arithmetically and algebraically. 
3

4
Structure:
5
 - numberOfRows : a non-negative integer saying how many rows there are.
6
 - numberOfColumns : a non-negative integer saying how many columns there are.
7
 - 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).  
8

9

10
Element-wise matrix arithmetic works; you can freely mix matrices and numbers but
11
don't try to mix matrices and arrays (yet).
12
Matrix multiplication, using the symbol +* (derived from APL's +.x), works between
13
(Matrix or Array) +* (Matrix or Array).  Don't try to use a number as an argument of +*.
14
Matrix * Number and Number * Matrix work fine, so you don't need +* with numbers.
15

16
"
17
Class {
18
        #name : 'Array2D',
19
        #superclass : 'Collection',
20
        #instVars : [
21
                'contents',
22
                'numberOfColumns',
23
                'numberOfRows'
24
        ],
25
        #category : 'DataFrame-Math',
26
        #package : 'DataFrame',
27
        #tag : 'Math'
28
}
29

30
{ #category : 'special instance creation' }
31
Array2D class >> columnVector: aCollection [
×
32
        "Create a matrix of one column having aCollection as contents"
×
33

×
34
        ^ self rows: aCollection size columns: 1 contents: aCollection asArray shallowCopy
×
35
]
×
36

37
{ #category : 'special instance creation' }
38
Array2D class >> diagonal: aCollection [
×
39
        |r i|
×
40
        r := self zeros: aCollection size.
×
41
        i := 0.
×
42
        aCollection do: [:each | i := i+1. r at: i at: i put: each].
×
43
        ^r
×
44
]
×
45

46
{ #category : 'special instance creation' }
47
Array2D class >> identity: n [
×
48
        | r |
×
49
        r := self zeros: n.
×
50
        1 to: n do: [ :i | r at: i at: i put: 1 ].
×
51
        ^ r
×
52
]
×
53

54
{ #category : 'instance creation' }
55
Array2D class >> new: dimension [
×
56
        "Answer a dimension*dimension matrix."
×
57
        ^ self rows: dimension columns: dimension
×
58
]
×
59

60
{ #category : 'instance creation' }
61
Array2D class >> new: dimemsion element: element [
×
62
        "Answer a dimemsion*dimemsion matrix with all elements set to element."
×
63

×
64
        ^ self rows: dimemsion columns: dimemsion element: element
×
65
]
×
66

67
{ #category : 'instance creation' }
68
Array2D class >> new: dimension tabulate: aTwoArgumentBlock [
×
69
        "Answer a dimension*dimension matrix where it at: i at: j is aBlock value: i value: j."
×
70
        ^ self rows: dimension columns: dimension tabulate: aTwoArgumentBlock
×
71
]
×
72

73
{ #category : 'special instance creation' }
74
Array2D class >> ones: dimension [
×
75
        "Create a squared matrix of dimension full of 1"
×
76
        ^ self new: dimension element: 1
×
77
]
×
78

79
{ #category : 'special instance creation' }
80
Array2D class >> rowVector: aCollection [
×
81
        "Create a matrix of one row having aCollection as contents"
×
82

×
83
        ^self rows: 1 columns: aCollection size contents: aCollection asArray shallowCopy
×
84
]
×
85

86
{ #category : 'instance creation' }
87
Array2D class >> rows: rowNumber columns: columnNumber [
5✔
88
        "Create a Matrix of rowNUmber rows and columnNumber columns."
5✔
89
        ^ self
5✔
90
                rows: rowNumber
5✔
91
                columns: columnNumber
5✔
92
                contents: (Array new: rowNumber*columnNumber)
5✔
93
]
5✔
94

95
{ #category : 'private' }
96
Array2D class >> rows: rowNumber columns: columnNumber contents: contents [
5✔
97
        "Private! Creates a Matrix of the given size with an adequate contents."
5✔
98
        ^ self new rows: rowNumber columns: columnNumber contents: contents
5✔
99
]
5✔
100

101
{ #category : 'instance creation' }
102
Array2D class >> rows: rowNumber columns: columnNumber element: element [
×
103
        "Create a Matrix of rowNumber rows and columnNumber columns filled with element."
×
104
        ^ self
×
105
                rows: rowNumber
×
106
                columns: columnNumber
×
107
                contents: ((Array new: rowNumber * columnNumber) atAllPut: element; yourself)
×
108
]
×
109

110
{ #category : 'instance creation' }
111
Array2D class >> rows: rowNumber columns: columnNumber tabulate: aTwoArgumentBlock [
×
112
        "Answer a new Matrix of the given dimensions where
×
113
         result at: i at: j is aTwoArgumentBlock value: i value: j"
×
114
        |a i|
×
115
        a := Array new: rowNumber*columnNumber.
×
116
        i := 0.
×
117
        1 to: rowNumber do: [:row |
×
118
                1 to: columnNumber do: [:column |
×
119
                        a at: (i := i + 1) put: (aTwoArgumentBlock value: row value: column)]].
×
120
        ^ self rows: rowNumber columns: columnNumber contents: a
×
121
]
×
122

123
{ #category : 'special instance creation' }
124
Array2D class >> zeros: dimension [
×
125
        "Create a Matrix of dimensionxdimemsion"
×
126
        ^ self new: dimension element: 0
×
127
]
×
128

129
{ #category : 'arithmetic' }
130
Array2D >> +* aCollection [
×
131
        "Premultiply aCollection by self.  aCollection should be an Array or Matrix.
×
132
         The name of this method is APL's +.x squished into Smalltalk syntax."
×
133

×
134
        ^aCollection preMultiplyByMatrix: self
×
135
]
×
136

137
{ #category : 'copying' }
138
Array2D >> , aMatrix [
×
139
        "Answer a new matrix having the same number of rows as the receiver and aMatrix,
×
140
         its columns being the columns of the receiver followed by the columns of aMatrix."
×
141
        |newCont newCols anArray oldCols a b c|
×
142

×
143
        [numberOfRows = aMatrix numberOfRows] assert.
×
144
        newCont := Array new: self size + aMatrix size.
×
145
        anArray := aMatrix privateContents.
×
146
        oldCols := aMatrix numberOfColumns.
×
147
        newCols := numberOfColumns + oldCols.
×
148
        a := b := c := 1.
×
149
        1 to: numberOfRows do: [:r |
×
150
                newCont replaceFrom: a to: a + numberOfColumns - 1 with: contents startingAt: b.
×
151
                newCont replaceFrom: a+numberOfColumns to: a + newCols - 1 with: anArray startingAt: c.
×
152
                a := a + newCols.
×
153
                b := b + numberOfColumns.
×
154
                c := c + oldCols].
×
155
        ^self class rows: numberOfRows columns: newCols contents: newCont
×
156
]
×
157

158
{ #category : 'copying' }
159
Array2D >> ,, aMatrix [
×
160
        "Answer a new matrix having the same number of columns as the receiver and aMatrix,
×
161
         its rows being the rows of the receiver followed by the rows of aMatrix."
×
162

×
163
        [numberOfColumns = aMatrix numberOfColumns] assert.
×
164
        ^self class
×
165
                        rows: numberOfRows + aMatrix numberOfRows
×
166
                        columns: numberOfColumns
×
167
                        contents: contents , aMatrix privateContents
×
168
]
×
169

170
{ #category : 'comparing' }
171
Array2D >> = aMatrix [
5✔
172
        ^ aMatrix class == self class
5✔
173
                and: [ aMatrix numberOfRows = numberOfRows
5✔
174
                                and: [ aMatrix numberOfColumns = numberOfColumns
5✔
175
                                        and: [ aMatrix privateContents = contents ] ] ]
5✔
176
]
5✔
177

178
{ #category : 'adding' }
179
Array2D >> add: newObject [
×
180
        self shouldNotImplement
×
181
]
×
182

183
{ #category : 'accessing' }
184
Array2D >> anyOne [
×
185
        "Return one element from the receiver"
×
186
        ^ contents anyOne
×
187
]
×
188

189
{ #category : 'converting' }
190
Array2D >> asArray [
×
191
        ^ contents shallowCopy
×
192
]
×
193

194
{ #category : 'converting' }
195
Array2D >> asBag [
×
196
        ^ contents asBag
×
197
]
×
198

199
{ #category : 'converting' }
200
Array2D >> asByteArray [
×
201
        ^ contents asByteArray
×
202
]
×
203

204
{ #category : 'converting' }
205
Array2D >> asCharacterSet [
×
206
        ^ contents asCharacterSet
×
207
]
×
208

209
{ #category : 'converting' }
210
Array2D >> asFloatArray [
×
211
        ^ contents asFloatArray
×
212
]
×
213

214
{ #category : 'converting' }
215
Array2D >> asIdentitySet [
×
216
        ^ contents asIdentitySet
×
217
]
×
218

219
{ #category : 'converting' }
220
Array2D >> asIntegerArray [
×
221
        ^ contents asIntegerArray
×
222
]
×
223

224
{ #category : 'converting' }
225
Array2D >> asOrderedCollection [
×
226
        ^ contents asOrderedCollection
×
227
]
×
228

229
{ #category : 'converting' }
230
Array2D >> asSet [
×
231
        ^ contents asSet
×
232
]
×
233

234
{ #category : 'converting' }
235
Array2D >> asSortedCollection [
×
236
        ^ contents asSortedCollection
×
237
]
×
238

239
{ #category : 'converting' }
240
Array2D >> asSortedCollection: aBlock [
×
241
        ^ contents asSortedCollection: aBlock
×
242
]
×
243

244
{ #category : 'converting' }
245
Array2D >> asWordArray [
×
246
        ^ contents asWordArray
×
247
]
×
248

249
{ #category : 'accessing' }
250
Array2D >> at: rowNumber at: columnNumber [
5✔
251
        ^ contents at: (self indexForRow: rowNumber andColumn: columnNumber)
5✔
252
]
5✔
253

254
{ #category : 'accessing' }
255
Array2D >> at: rowNumber at: columnNumber ifInvalid: value [
×
256
        "If rowNumber,columnNumber is a valid index for the receiver, answer the corresponding element. Otherwise, answer value."
×
257

×
258
        (rowNumber between: 1 and: numberOfRows) ifFalse: [ ^ value ].
×
259
        (columnNumber between: 1 and: numberOfColumns) ifFalse: [ ^ value ].
×
260
        ^contents at: (rowNumber - 1) * numberOfColumns + columnNumber
×
261
]
×
262

263
{ #category : 'accessing' }
264
Array2D >> at: rowNumber at: columnNumber incrementBy: value [
×
265
        "Add a value to the element available at rowNumber,columNumber."
×
266

×
267
        ^ contents at: (self indexForRow: rowNumber andColumn: columnNumber) incrementBy: value
×
268
]
×
269

270
{ #category : 'accessing' }
271
Array2D >> at: rowNumber at: columnNumber put: value [
5✔
272
        "Put value at rowNumber,columnNumber"
5✔
273
        ^ contents at: (self indexForRow: rowNumber andColumn: columnNumber) put: value
5✔
274
]
5✔
275

276
{ #category : 'accessing' }
277
Array2D >> atAllPut: value [
×
278
        "Put value as value of all the receiver elements."
×
279
        contents atAllPut: value
×
280
]
×
281

282
{ #category : 'row/column operations' }
283
Array2D >> atColumn: column [
×
284

×
285
        |p|
×
286
        p := (self indexForRow: 1 andColumn: column)-numberOfColumns.
×
287
        ^(1 to: numberOfRows) collect: [:row | contents at: (p := p+numberOfColumns)]
×
288
]
×
289

290
{ #category : 'row/column operations' }
291
Array2D >> atColumn: column put: aCollection [
×
292
        | p |
×
293
        aCollection size = numberOfRows ifFalse: [ self error: 'wrong column size' ].
×
294
        p := (self indexForRow: 1 andColumn: column) - numberOfColumns.
×
295
        aCollection do: [ :each | contents at: (p := p + numberOfColumns) put: each ].
×
296
        ^ aCollection
×
297
]
×
298

299
{ #category : 'random' }
300
Array2D >> atRandom [
×
301
        "Return the contents of the receiver in a random order."
×
302
        ^ contents atRandom
×
303
]
×
304

305
{ #category : 'random' }
306
Array2D >> atRandom: aGenerator [
×
307
        ^ contents atRandom: aGenerator
×
308
]
×
309

310
{ #category : 'row/column operations' }
311
Array2D >> atRow: rowNumber [
5✔
312
        (rowNumber between: 1 and: numberOfRows)
5✔
313
                ifFalse: [self error: '1st subscript out of range'].
5✔
314
        ^ contents
5✔
315
                        copyFrom: (rowNumber - 1) * numberOfColumns + 1
5✔
316
                        to: rowNumber*numberOfColumns
5✔
317
]
5✔
318

319
{ #category : 'row/column operations' }
320
Array2D >> atRow: row put: aCollection [
5✔
321
        |p|
5✔
322

5✔
323
        aCollection size = numberOfColumns ifFalse: [self error: 'wrong row size'].
5✔
324
        p := (self indexForRow: row andColumn: 1)-1.
5✔
325
        aCollection do: [:each | contents at: (p := p+1) put: each].
5✔
326
        ^aCollection
5✔
327
]
5✔
328

329
{ #category : 'accessing - submatrices' }
330
Array2D >> atRows: rs columns: cs [
×
331
        "Answer a Matrix obtained by slicing the receiver.
×
332
         rs and cs should be sequenceable collections of positive integers."
×
333

×
334
        ^self class rows: rs size columns: cs size tabulate: [:r :c |
×
335
                self at: (rs at: r) at: (cs at: c)]
×
336
]
×
337

338
{ #category : 'accessing - submatrices' }
339
Array2D >> atRows: r1 to: r2 columns: c1 to: c2 [
×
340
        "Answer a submatrix [r1..r2][c1..c2] of the receiver."
×
341
        |rd cd|
×
342

×
343
        rd := r1 - 1.
×
344
        cd := c1 - 1.
×
345
        ^self class rows: r2-rd columns: c2-cd tabulate: [:r :c| self at: r+rd at: c+cd]
×
346
]
×
347

348
{ #category : 'accessing - submatrices' }
349
Array2D >> atRows: r1 to: r2 columns: c1 to: c2 ifInvalid: element [
×
350
        "Answer a submatrix [r1..r2][c1..c2] of the receiver.
×
351
         Portions of the result outside the bounds of the original matrix are filled in with element."
×
352
        |rd cd|
×
353
        rd := r1 - 1.
×
354
        cd := c1 - 1.
×
355
        ^self class rows: r2-rd columns: c2-cd tabulate: [ :r :c| self at: r+rd at: c+cd ifInvalid: element]
×
356
]
×
357

358
{ #category : 'accessing - submatrices' }
359
Array2D >> atRows: r1 to: r2 columns: c1 to: c2 put: aMatrix [
×
360
        "Set the [r1..r2][c1..c2] submatrix of the receiver
×
361
         from the [1..r2-r1+1][1..c2-c1+1] submatrix of aMatrix.
×
362
         As long as aMatrix responds to at:at: and accepts arguments in the range shown,
×
363
         we don't care if it is bigger or even if it is a Matrix at all."
×
364
        |rd cd|
×
365

×
366
        rd := r1 - 1.
×
367
        cd := c1 - 1.
×
368
        r1 to: r2 do: [:r |
×
369
                c1 to: c2 do: [:c |
×
370
                        self at: r at: c put: (aMatrix at: r-rd at: c-cd)]].
×
371
        ^aMatrix
×
372
]
×
373

374
{ #category : 'enumerating' }
375
Array2D >> collect: aBlock [
5✔
376
        "Answer a new matrix with transformed elements; transformations should be independent."
5✔
377

5✔
378
        ^self class
5✔
379
                rows: numberOfRows
5✔
380
                columns: numberOfColumns
5✔
381
                contents: (contents collect: aBlock)
5✔
382
]
5✔
383

384
{ #category : 'accessing' }
385
Array2D >> columnCount [
5✔
386
        ^ numberOfColumns
5✔
387
]
5✔
388

389
{ #category : 'row/column operations' }
390
Array2D >> diagonal [
×
391
        "Answer (1 to: (numberOfRows min: numberOfColumns)) collect: [:i | self at: i at: i]"
×
392
        |i|
×
393
        i := numberOfColumns negated.
×
394
        ^ (1 to: (numberOfRows min: numberOfColumns)) collect: [:j | contents at: (i := i + numberOfColumns + 1)]
×
395
]
×
396

397
{ #category : 'enumerating' }
398
Array2D >> difference: aCollection [
×
399
        "Union is in because the result is always a Set.
×
400
         Difference and intersection are out because the result is like the receiver,
×
401
         and with irregular seleection that cannot be."
×
402
        self shouldNotImplement
×
403
]
×
404

405
{ #category : 'enumerating' }
406
Array2D >> do: aBlock [
5✔
407
        "Pass elements to aBlock one at a time in row-major order."
5✔
408
        contents do: aBlock
5✔
409
]
5✔
410

411
{ #category : 'accessing' }
412
Array2D >> extent [
×
413
    "Answer the receiver's dimensions as point."
×
414

×
415
    ^ self numberOfColumns @ self numberOfRows
×
416
]
×
417

418
{ #category : 'comparing' }
419
Array2D >> hash [
×
420
        "I'm really not sure what would be a good hash function here.
×
421
         The essential thing is that it must be compatible with #=, and
×
422
         this satisfies that requirement."
×
423

×
424
        ^contents hash
×
425
]
×
426

427
{ #category : 'testing' }
428
Array2D >> identityIncludes: anObject [
×
429
        ^ contents identityIncludes: anObject
×
430
]
×
431

432
{ #category : 'accessing' }
433
Array2D >> identityIndexOf: anElement [
×
434

×
435
        ^ self identityIndexOf: anElement ifAbsent: [ 0@0 ]
×
436
]
×
437

438
{ #category : 'accessing' }
439
Array2D >> identityIndexOf: anElement ifAbsent: anExceptionBlock [
×
440
        ^self rowAndColumnForIndex:
×
441
                 (contents identityIndexOf: anElement ifAbsent: [^anExceptionBlock value])
×
442
]
×
443

444
{ #category : 'testing' }
445
Array2D >> includes: anObject [
×
446
        ^ contents includes: anObject
×
447
]
×
448

449
{ #category : 'testing' }
450
Array2D >> includesAll: aCollection [
×
451
        ^ contents includesAll: aCollection
×
452
]
×
453

454
{ #category : 'testing' }
455
Array2D >> includesAny: aCollection [
×
456
        ^ contents includesAny: aCollection
×
457
]
×
458

459
{ #category : 'private' }
460
Array2D >> indexForRow: row andColumn: column [
5✔
461
        (row between: 1 and: numberOfRows)
5✔
462
                ifFalse: [self error: '1st subscript out of range'].
5✔
463
        (column between: 1 and: numberOfColumns)
5✔
464
                ifFalse: [self error: '2nd subscript out of range'].
5✔
465
        ^(row-1) * numberOfColumns + column
5✔
466
]
5✔
467

468
{ #category : 'accessing' }
469
Array2D >> indexOf: anElement [
×
470
        "If there are integers r, c such that (self at: r at: c) = anElement, answer some such r@c, otherwise answer 0@0. The order in which the receiver are searched is UNSPECIFIED except that it is the same as the order used by #indexOf:ifAbsent: and #readStream."
×
471

×
472
        ^self indexOf: anElement ifAbsent: [0@0]
×
473
]
×
474

475
{ #category : 'accessing' }
476
Array2D >> indexOf: anElement ifAbsent: anExceptionBlock [
×
477
        "If there are integers r, c such that (self at: r at: c) = anElement, answer some such r@c, otherwise answer the result of anExceptionBlock."
×
478

×
479
        ^self rowAndColumnForIndex:
×
480
                 (contents indexOf: anElement ifAbsent: [^ anExceptionBlock value])
×
481
]
×
482

483
{ #category : 'enumerating' }
484
Array2D >> indicesCollect: aBlock [
×
485

×
486
        | r i |
×
487
        r := Array new: numberOfRows * numberOfColumns.
×
488
        i := 0.
×
489
        1 to: numberOfRows do: [:row |
×
490
                1 to: numberOfColumns do: [:column |
×
491
                        r at: (i := i+1) put: (aBlock value: row value: column)]].
×
492
        ^ self class rows: numberOfRows columns: numberOfColumns contents: r
×
493
]
×
494

495
{ #category : 'enumerating' }
496
Array2D >> indicesDo: aBlock [
×
497
        1 to: numberOfRows do: [ :row |
×
498
                1 to: numberOfColumns do: [ :column |
×
499
                        aBlock value: row value: column]]
×
500
]
×
501

502
{ #category : 'enumerating' }
503
Array2D >> indicesInject: start into: aBlock [
×
504

×
505
        |current|
×
506
        current := start.
×
507
        1 to: numberOfRows do: [ :row |
×
508
                1 to: numberOfColumns do: [ :column |
×
509
                        current := aBlock value: current value: row value: column ] ].
×
510
        ^ current
×
511
]
×
512

513
{ #category : 'enumerating' }
514
Array2D >> intersection: aCollection [
×
515
        "Union is in because the result is always a Set.
×
516
         Difference and intersection are out because the result is like the receiver,
×
517
         and with irregular seleection that cannot be."
×
518
        self shouldNotImplement
×
519
]
×
520

521
{ #category : 'testing' }
522
Array2D >> isSequenceable [
×
523
        "LIE so that arithmetic on matrices will work.
×
524
         What matters for arithmetic is not that there should be random indexing
×
525
         but that the structure should be stable and independent of the values of
×
526
         the elements.  #isSequenceable is simply the wrong question to ask."
×
527
        ^ true
×
528
]
×
529

530
{ #category : 'accessing' }
531
Array2D >> numberOfColumns [
5✔
532
        ^ numberOfColumns
5✔
533
]
5✔
534

535
{ #category : 'accessing' }
536
Array2D >> numberOfColumns: anObject [
×
537
        numberOfColumns := anObject
×
538
]
×
539

540
{ #category : 'accessing' }
541
Array2D >> numberOfRows [
5✔
542
        ^ numberOfRows
5✔
543
]
5✔
544

545
{ #category : 'accessing' }
546
Array2D >> numberOfRows: anObject [
×
547
        numberOfRows := anObject
×
548
]
×
549

550
{ #category : 'testing' }
551
Array2D >> occurrencesOf: anObject [
×
552
        ^ contents occurrencesOf: anObject
×
553
]
×
554

555
{ #category : 'copying' }
556
Array2D >> postCopy [
×
557
        super postCopy.
×
558
        contents := contents copy
×
559
]
×
560

561
{ #category : 'arithmetic' }
562
Array2D >> preMultiplyByArray: a [
×
563
        "Answer a +* self where a is an Array."
×
564

×
565
        numberOfRows = 1 ifFalse: [self error: 'dimensions do not conform'].
×
566
        ^Array2D rows: a size columns: numberOfColumns tabulate: [:row :col |
×
567
                (a at: row) * (contents at: col)]
×
568
]
×
569

570
{ #category : 'arithmetic' }
571
Array2D >> preMultiplyByMatrix: m [
×
572
        "Answer m +* self where m is a Matrix."
×
573
        |s|
×
574
        numberOfRows = m numberOfColumns ifFalse: [self error: 'dimensions do not conform'].
×
575
        ^ Array2D
×
576
                rows: m numberOfRows
×
577
                columns: numberOfColumns
×
578
                tabulate: [:row :col |
×
579
                        s := 0.
×
580
                        1 to: numberOfRows do: [:k | s := (m at: row at: k) * (self at: k at: col) + s].
×
581
                        s ]
×
582
]
×
583

584
{ #category : 'printing' }
585
Array2D >> printOn: aStream [
5✔
586

5✔
587
        aStream nextPutAll: '('.
5✔
588
        (1 to: self numberOfRows)
5✔
589
                do: [ :r |
5✔
590
                                (self atRow: r)
5✔
591
                                        do: [ :each | aStream print: each ]
5✔
592
                                        separatedBy: [ aStream space ]]
5✔
593
                separatedBy: [ aStream cr ].
5✔
594
        aStream nextPutAll: ' )'
5✔
595
]
5✔
596

597
{ #category : 'private' }
598
Array2D >> privateContents [
5✔
599
        "Only used in #, #,, and #= so far.
5✔
600
         It used to be called #contents, but that clashes with Collection>>contents."
5✔
601

5✔
602
        ^ contents
5✔
603
]
5✔
604

605
{ #category : 'converting' }
606
Array2D >> readStream [
×
607
        "Answer a ReadStream that returns all the elements of the receiver in some UNSPECIFIED order."
×
608
        ^ contents readStream
×
609
]
×
610

611
{ #category : 'enumerating' }
612
Array2D >> reject: aBlock [
×
613
        self shouldNotImplement
×
614
]
×
615

616
{ #category : 'removing' }
617
Array2D >> remove: anObject ifAbsent: anExceptionBlock [
×
618
        self shouldNotImplement
×
619
]
×
620

621
{ #category : 'removing' }
622
Array2D >> removeAll [
×
623

×
624
        self shouldNotImplement
×
625
]
×
626

627
{ #category : 'accessing' }
628
Array2D >> replaceAll: oldObject with: newObject [
×
629
        "Replace all occurrences of oldObject with newObject in the receiver."
×
630
        contents replaceAll: oldObject with: newObject
×
631
]
×
632

633
{ #category : 'private' }
634
Array2D >> rowAndColumnForIndex: index [
×
635
        |t|
×
636

×
637
        t := index - 1.
×
638
        ^(t // numberOfColumns + 1)@(t \\ numberOfColumns + 1)
×
639
]
×
640

641
{ #category : 'accessing' }
642
Array2D >> rowCount [
5✔
643
        ^numberOfRows
5✔
644
]
5✔
645

646
{ #category : 'private' }
647
Array2D >> rows: rows columns: columns contents: anArray [
5✔
648
        [rows isInteger and: [rows >= 0]] assert.
5✔
649
        [columns isInteger and: [columns >= 0]] assert.
5✔
650
        [rows * columns = anArray size] assert.
5✔
651
        numberOfRows := rows.
5✔
652
        numberOfColumns := columns.
5✔
653
        contents := anArray.
5✔
654
        ^self
5✔
655
]
5✔
656

657
{ #category : 'enumerating' }
658
Array2D >> select: aBlock [
×
659
        self shouldNotImplement
×
660
]
×
661

662
{ #category : 'copying' }
663
Array2D >> shuffled [
×
664
        ^self class rows: numberOfRows columns: numberOfColumns contents: (contents shuffled)
×
665
]
×
666

667
{ #category : 'copying' }
668
Array2D >> shuffledBy: aRandom [
×
669
        ^self class rows: numberOfRows columns: numberOfColumns contents: (contents copy shuffleBy: aRandom)
×
670
]
×
671

672
{ #category : 'accessing' }
673
Array2D >> size [
×
674
        ^ contents size
×
675
]
×
676

677
{ #category : 'printing' }
678
Array2D >> storeOn: aStream [
×
679
        aStream nextPut: $(; nextPutAll: self class name;
×
680
                nextPutAll: ' rows: '; store: numberOfRows;
×
681
                nextPutAll: ' columns: '; store: numberOfColumns;
×
682
                nextPutAll: ' contents: '; store: contents;
×
683
                nextPut: $)
×
684
]
×
685

686
{ #category : 'accessing' }
687
Array2D >> swap: r1 at: c1 with: r2 at: c2 [
×
688
        contents swap: (self indexForRow: r1 andColumn: c1)
×
689
                         with: (self indexForRow: r2 andColumn: c2)
×
690
]
×
691

692
{ #category : 'row/column operations' }
693
Array2D >> swapColumn: anIndex withColumn: anotherIndex [
×
694
        |a b|
×
695

×
696
        a := self indexForRow: 1 andColumn: anIndex.
×
697
        b := self indexForRow: 1 andColumn: anotherIndex.
×
698
        numberOfRows timesRepeat: [
×
699
                contents swap: a with: b.
×
700
                a := a + numberOfColumns.
×
701
                b := b + numberOfColumns]
×
702
]
×
703

704
{ #category : 'row/column operations' }
705
Array2D >> swapRow: anIndex withRow: anotherIndex [
×
706
        | a b |
×
707
        a := self indexForRow: anIndex andColumn: 1.
×
708
        b := self indexForRow: anotherIndex andColumn: 1.
×
709
        numberOfColumns timesRepeat: [
×
710
                contents swap: a with: b.
×
711
                a := a + 1.
×
712
                b := b + 1]
×
713
]
×
714

715
{ #category : 'row/column operations' }
716
Array2D >> transposed [
×
717
        [numberOfRows = numberOfColumns] assert.
×
718
        ^ self indicesCollect: [ :row :column | self at: column at: row ]
×
719
]
×
720

721
{ #category : 'enumerating' }
722
Array2D >> with: aCollection collect: aBlock [
×
723
        "aCollection must support #at:at: and be at least as large as the receiver."
×
724

×
725
        ^self withIndicesCollect: [:each :row :column |
×
726
                aBlock value: each value: (aCollection at: row at: column)]
×
727
]
×
728

729
{ #category : 'enumerating' }
730
Array2D >> with: aCollection do: aBlock [
×
731
        "aCollection must support #at:at: and be at least as large as the receiver."
×
732

×
733
        self withIndicesDo: [:each :row :column |
×
734
                aBlock value: each value: (aCollection at: row at: column)]
×
735
]
×
736

737
{ #category : 'enumerating' }
738
Array2D >> with: aCollection inject: startingValue into: aBlock [
×
739
        "aCollection must support #at:at: and be at least as large as the receiver."
×
740

×
741
        ^ self withIndicesInject: startingValue into: [:value :each :row :column |
×
742
                        aBlock value: value value: each value: (aCollection at: row at: column)]
×
743
]
×
744

745
{ #category : 'enumerating' }
746
Array2D >> withIndicesCollect: aBlock [
5✔
747

5✔
748
        |i r|
5✔
749
        i := 0.
5✔
750
        r := contents shallowCopy.
5✔
751
        1 to: numberOfRows do: [ :row |
5✔
752
                1 to: numberOfColumns do: [ :column |
5✔
753
                        i := i+1.
5✔
754
                        r at: i put: (aBlock value: (r at: i) value: row value: column)]].
5✔
755
        ^ self class rows: numberOfRows columns: numberOfColumns contents: r
5✔
756
]
5✔
757

758
{ #category : 'enumerating' }
759
Array2D >> withIndicesDo: aBlock [
5✔
760

5✔
761
        | i |
5✔
762
        i := 0.
5✔
763
        1 to: numberOfRows do: [:row |
5✔
764
                1 to: numberOfColumns do: [:column |
5✔
765
                        aBlock value: (contents at: (i := i+1)) value: row value: column]]
5✔
766
]
5✔
767

768
{ #category : 'enumerating' }
769
Array2D >> withIndicesInject: start into: aBlock [
×
770

×
771
        | i current |
×
772
        i := 0.
×
773
        current := start.
×
774
        1 to: numberOfRows do: [ :row |
×
775
                1 to: numberOfColumns do: [ :column |
×
776
                        current := aBlock
×
777
                                                                value: current
×
778
                                                                value: (contents at: (i := i+1))
×
779
                                                                value: row value: column ] ].
×
780
        ^ current
×
781
]
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc