From 805149ddbb1a81e6a88841e479603bf25f17bf0f Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Sat, 17 Jul 2021 19:39:58 +0100 Subject: [PATCH 01/21] Addition of class and operations on rank 2 tensors --- src/Math-Matrix/PMTensorRank2.class.st | 157 +++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 src/Math-Matrix/PMTensorRank2.class.st diff --git a/src/Math-Matrix/PMTensorRank2.class.st b/src/Math-Matrix/PMTensorRank2.class.st new file mode 100644 index 00000000..b69d368c --- /dev/null +++ b/src/Math-Matrix/PMTensorRank2.class.st @@ -0,0 +1,157 @@ +Class { + #name : #PMTensorRank2, + #superclass : #Object, + #instVars : [ + 'array', + 'shape' + ], + #category : #'Math-Matrix' +} + +{ #category : #arithmetic } +PMTensorRank2 >> * aPMTensor [ + + (self checkProductMatrixSize: aPMTensor) + ifTrue: [ + | t | + t := self class zerosWithShape: { + self numberOfLines. + aPMTensor numberOfColumns }. + + 1 to: self numberOfLines do: [ :i | + 1 to: aPMTensor numberOfColumns do: [ :j | + t + set: { i. j } + value: + ((1 to: self numberOfColumns) inject: 0 into: [ :sum :k | + (self get: { i. k }) * (aPMTensor get: { k. j }) + sum ]) ] ]. + ^ t ] + ifFalse: [ ShapeMismatch signal ] +] + +{ #category : #comparing } +PMTensorRank2 >> = aPMTensorRank2 [ + +^ (self hasSameShapeAs: aPMTensorRank2) & (self array = aPMTensorRank2 array) +] + +{ #category : #accessing } +PMTensorRank2 >> array [ + ^ array +] + +{ #category : #'as yet unclassified' } +PMTensorRank2 >> array: aFlatArray withShape: aShape [ + array := aFlatArray. + shape := aShape +] + +{ #category : #'as yet unclassified' } +PMTensorRank2 >> checkProductMatrixSize: aPMTensorRank2 [ + + ^ self numberOfColumns = aPMTensorRank2 numberOfLines +] + +{ #category : #'as yet unclassified' } +PMTensorRank2 >> checkReshapeIsPossibleWith: aNewShape [ + + ^ (shape first * shape second) = ((aNewShape first) * (aNewShape second)) +] + +{ #category : #public } +PMTensorRank2 >> get: coords [ + | row column | + row := coords first. + column := coords second. + ^ array at: (row - 1) * (shape second) + column +] + +{ #category : #operation } +PMTensorRank2 >> hadamardProduct: aPMTensorRank2 [ + (self hasSameShapeAs: aPMTensorRank2) + ifTrue:[ + ^ self class new array: ((self array) with: (aPMTensorRank2 array) collect:[:a :b| a*b]) + withShape: self shape. + ] + ifFalse:[ShapeMismatch signal ] +] + +{ #category : #testing } +PMTensorRank2 >> hasSameShapeAs: aTensorRank2 [ + ^ self shape = aTensorRank2 shape +] + +{ #category : #'as yet unclassified' } +PMTensorRank2 >> kroneckerProduct: aPMTensor [ + + | t | + t := self class zerosWithShape: { + ((self numberOfLines) * (aPMTensor numberOfLines)). + ((self numberOfColumns) * (aPMTensor numberOfColumns)) }. + + 1 to: self numberOfLines do: [ :i1 | + 1 to: self numberOfColumns do: [ :j1 | + 1 to: aPMTensor numberOfLines do: [ :i2 | + 1 to: aPMTensor numberOfColumns do: [ :j2 | + t set: { (i1-1)*(aPMTensor numberOfLines)+i2. (j1-1)*(aPMTensor numberOfColumns)+j2 } + value: (self get:{i1. j1})* (aPMTensor get:{ i2.j2 }) + ] + ] + ] + ]. + ^t +] + +{ #category : #accessing } +PMTensorRank2 >> numberOfColumns [ + ^ shape second +] + +{ #category : #accessing } +PMTensorRank2 >> numberOfLines [ + ^ shape first +] + +{ #category : #'as yet unclassified' } +PMTensorRank2 >> outerProduct: aPMTensor [ + + | t | + t := self class zerosWithShape: { + ((self numberOfLines) * (aPMTensor numberOfLines)). + ((self numberOfColumns) * (aPMTensor numberOfColumns)) }. + + 1 to: self numberOfLines do: [ :i1 | + 1 to: self numberOfColumns do: [ :j1 | + 1 to: aPMTensor numberOfLines do: [ :i2 | + 1 to: aPMTensor numberOfColumns do: [ :j2 | + t set: { (i1-1)*(aPMTensor numberOfLines)+i2. (j1-1)*(aPMTensor numberOfColumns)+j2 } + value: (self get:{i1. i2}) * (aPMTensor get:{ j1. j2 }) + ] + ] + ] + ]. + ^t +] + +{ #category : #'as yet unclassified' } +PMTensorRank2 >> reshape: aNewShape [ + + (self checkReshapeIsPossibleWith: aNewShape) + ifTrue: [ shape := aNewShape ] + ifFalse: [ ShapeMismatch signal ] +] + +{ #category : #initialization } +PMTensorRank2 >> set: coords value: aValue [ + + | row column | + row := coords first. + column := coords second. + array at: row - 1 * shape second + column put: aValue +] + +{ #category : #accessing } +PMTensorRank2 >> shape [ + + ^ shape +] From 8d6033e068d4b7f2a434eaea09581a40c1733c03 Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Sat, 17 Jul 2021 20:53:58 +0100 Subject: [PATCH 02/21] Rank2 tensor class methods --- src/Math-Matrix/PMTensorRank2.class.st | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/Math-Matrix/PMTensorRank2.class.st b/src/Math-Matrix/PMTensorRank2.class.st index b69d368c..ca38700e 100644 --- a/src/Math-Matrix/PMTensorRank2.class.st +++ b/src/Math-Matrix/PMTensorRank2.class.st @@ -8,6 +8,23 @@ Class { #category : #'Math-Matrix' } +{ #category : #'instance creation' } +PMTensorRank2 class >> rows: anArray [ + + + ^ self new array: anArray flattened withShape: { + anArray size. + (anArray at: 1) size } +] + +{ #category : #'as yet unclassified' } +PMTensorRank2 class >> zerosWithShape: aShape [ + + ^ self new + array: (Array new: aShape first * aShape second withAll:0) + withShape: aShape +] + { #category : #arithmetic } PMTensorRank2 >> * aPMTensor [ From cc9056da20a246232c24dc52adc8aa2483ade4a6 Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Sat, 17 Jul 2021 20:54:39 +0100 Subject: [PATCH 03/21] Rank2 tensor tests --- src/Math-Matrix/PMTensorRank2Test.class.st | 154 +++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 src/Math-Matrix/PMTensorRank2Test.class.st diff --git a/src/Math-Matrix/PMTensorRank2Test.class.st b/src/Math-Matrix/PMTensorRank2Test.class.st new file mode 100644 index 00000000..0709167b --- /dev/null +++ b/src/Math-Matrix/PMTensorRank2Test.class.st @@ -0,0 +1,154 @@ +Class { + #name : #PMTensorRank2Test, + #superclass : #TestCase, + #instVars : [ + 'array' + ], + #category : #'Math-Matrix' +} + +{ #category : #tests } +PMTensorRank2Test >> testHadamardProduct [ +|t1 t2| + t1 := PMTensorRank2 rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + t2 := PMTensorRank2 rows: #( #( 4 3 2 9 ) #( 9 7 6 5 ) ). + self assert: (t1 hadamardProduct: t2) equals: (PMTensorRank2 rows:#( #( 4 6 6 36 ) #( 45 42 42 40 ) )) +] + +{ #category : #tests } +PMTensorRank2Test >> testHadamardProductWithDifferentShapes [ +|t1 t2| + t1 := PMTensorRank2 rows: #( #( 1 2) #(3 4) #(5 6) #(7 8)). + t2 := PMTensorRank2 rows: #( #( 4 3 2 9 ) #( 9 7 6 5 ) ). + self should: [t1 hadamardProduct: t2] raise: ShapeMismatch +] + +{ #category : #tests } +PMTensorRank2Test >> testKroneckerProduct [ +|t1 t2| + t1 := PMTensorRank2 rows: #( #( 1 2 ) + #( 3 1 )). + t2 := PMTensorRank2 rows: #( #( 1 3 ) + #( 2 1 )). + self assert: (t1 kroneckerProduct: t2) equals: (PMTensorRank2 rows:#( + #( 1 3 2 6 ) + #( 2 1 4 2 ) + #( 3 9 1 3 ) + #( 6 3 2 1 ) )). + t1 := PMTensorRank2 rows: #( #( 1 2) + #(3 4) + #( 1 0 )). + t2 := PMTensorRank2 rows: #( #( 0 5 2 ) + #( 6 7 3)). + self assert: (t1 kroneckerProduct: t2) equals: (PMTensorRank2 rows:#( + #( 0 5 2 0 10 4) + #( 6 7 3 12 14 6) + #( 0 15 6 0 20 8) + #( 18 21 9 24 28 12) + #( 0 5 2 0 0 0) + #( 6 7 3 0 0 0 ) + )) +] + +{ #category : #tests } +PMTensorRank2Test >> testOrdinaryProduct [ +|t1 t2| + t1 := PMTensorRank2 rows: #( #( 1 2 ) + #( 3 4 )). + t2 := PMTensorRank2 rows: #( #( 4 3 ) + #( 2 5 )). + self assert: (t1 * t2) equals: (PMTensorRank2 rows:#( #( 8 13 ) #( 20 29 ) )) +] + +{ #category : #tests } +PMTensorRank2Test >> testOrdinaryProductWithTheNumberOFLineOfFirstTensorIsEqualsOfNumberOfColumnToSecondTensor [ + + | t1 t2 | + t1 := PMTensorRank2 rows: #( #( 1 2 ) #( 3 4 ) #( 5 6 ) ). + t2 := PMTensorRank2 rows: #( #( 4 3 2 ) #( 9 7 6 ) #(10 11 12)). + self should: [ t1 * t2 ] raise: ShapeMismatch +] + +{ #category : #tests } +PMTensorRank2Test >> testOuterProduct [ +|t1 t2| + t1 := PMTensorRank2 rows: #( #( 1 2 ) + #( 3 1 ) ). + t2 := PMTensorRank2 rows: #( #( 1 3 ) + #( 2 1 ) ). + self assert: (t1 outerProduct: t2) equals: (PMTensorRank2 rows:#( #( 1 3 2 1 ) + #( 2 6 4 2 ) + #( 3 9 6 3 ) + #(1 3 2 1))). + +t1 := PMTensorRank2 rows: #( #( 1 2) + #(3 4) + #( 1 0 )). + t2 := PMTensorRank2 rows: #( #( 0 5 2 ) + #( 6 7 3)). + self assert: (t1 outerProduct: t2) equals: (PMTensorRank2 rows:#( + #( 0 5 2 6 7 3) + #( 0 10 4 12 14 6) + #( 0 15 6 18 21 9) + #( 0 20 8 24 28 12) + #( 0 5 2 6 7 3) + #( 0 0 0 0 0 0 ) + )) +] + +{ #category : #tests } +PMTensorRank2Test >> testReShape [ + + | t | + t := PMTensorRank2 rows: #(#(0 1) #(2 3) #(4 5)). + self assert: (t reshape: #(2 3)) equals: (PMTensorRank2 rows:#(#(0 1 2) #(3 4 5))) +] + +{ #category : #tests } +PMTensorRank2Test >> testReShapeNotPossible [ + + | t | + t := PMTensorRank2 rows: #( #( 0 1 ) #( 2 3 ) #( 4 5 ) ). + self + should: [t reshape: #( 5 3 )] + raise: ShapeMismatch +] + +{ #category : #tests } +PMTensorRank2Test >> testRows [ + + | t1 t2| + t1 := PMTensorRank2 rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: (t1 get: #(1 1)) equals: 1. + self assert: (t1 get: #(2 1)) equals: 5. + self assert: (t1 get: #(2 4)) equals: 8. + t2 := PMTensorRank2 rows: #( #( 1 2) #(3 4) #( 5 6) #(7 8 )). + self assert: (t2 get: #(1 1)) equals: 1. + self assert: (t2 get: #(2 1)) equals: 3. + self assert: (t2 get: #(4 2)) equals: 8. + + + +] + +{ #category : #tests } +PMTensorRank2Test >> testShape [ + + | t | + t := PMTensorRank2 rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: t shape equals: #( 2 4 ) +] + +{ #category : #tests } +PMTensorRank2Test >> testZerosWithShape [ + + | t | + t := PMTensorRank2 zerosWithShape: #( 10 10 ). + 1 to: t numberOfColumns do: [ :i | + 1 to: t numberOfLines do: [ :j | + self + assert: (t get: { + i. + j }) + equals: 0 ] ] +] From 3df00c5976e36edc73d0916aba3d1bad76f9ecb4 Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Sat, 17 Jul 2021 20:55:38 +0100 Subject: [PATCH 04/21] The general class for a tensor > 2 --- src/Math-Matrix/PMTensor.class.st | 123 ++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/Math-Matrix/PMTensor.class.st diff --git a/src/Math-Matrix/PMTensor.class.st b/src/Math-Matrix/PMTensor.class.st new file mode 100644 index 00000000..68a04c45 --- /dev/null +++ b/src/Math-Matrix/PMTensor.class.st @@ -0,0 +1,123 @@ +Class { + #name : #PMTensor, + #superclass : #Object, + #instVars : [ + 'array', + 'shape', + 'first', + 'strides' + ], + #category : #'Math-Matrix' +} + +{ #category : #comparing } +PMTensor >> = aTensor [ + + ^ array = aTensor array & (first = aTensor first) + & (strides = aTensor strides) & (shape = aTensor shape) +] + +{ #category : #accessing } +PMTensor >> array [ +^array +] + +{ #category : #'as yet unclassified' } +PMTensor >> array: aFlatArray withShape: aShape [ + + array := aFlatArray. + shape := aShape copy. + self updateFirst. + shape ifNotEmpty: [ self updateStrides] +] + +{ #category : #accessing } +PMTensor >> first [ +^first +] + +{ #category : #public } +PMTensor >> get: coords [ + + | position | + position := self getPosition: coords. + ^ array at: position +] + +{ #category : #'primitives - file' } +PMTensor >> getPosition: coords [ + + | position | + position := 1. + coords withIndexDo: [ :elt :i | + position := elt - 1 * (strides at: i) + position ]. + ^ position +] + +{ #category : #accessing } +PMTensor >> rank [ + ^ shape size +] + +{ #category : #'as yet unclassified' } +PMTensor >> reshape: aNewShape [ + + ^ self viewWithShape: aNewShape. + +] + +{ #category : #initialization } +PMTensor >> set: coords value: aValue [ + +array at: (self getPosition: coords) put: aValue +] + +{ #category : #accessing } +PMTensor >> shape [ + + ^ shape +] + +{ #category : #accessing } +PMTensor >> size [ + + | product | + product := 1. + shape do: [ :each | product := each * product ]. + ^ product +] + +{ #category : #accessing } +PMTensor >> strides [ +^strides +] + +{ #category : #'as yet unclassified' } +PMTensor >> updateFirst [ + + first := Array new: shape size withAll: 1 +] + +{ #category : #'as yet unclassified' } +PMTensor >> updateStrides [ + + strides := Array new: shape size. + strides at: shape size put: 1. + ((shape size -1) to: 1 by: -1) do: [ :i | + strides at: i put: ((strides at: i + 1) * (shape at: i+1))] +] + +{ #category : #'as yet unclassified' } +PMTensor >> view [ + + "Share only the array" + + ^ self viewWithShape: shape +] + +{ #category : #'as yet unclassified' } +PMTensor >> viewWithShape: aNewShape [ + + ^ PMTensor new array: self array withShape: aNewShape + +] From b1b923d697af60d6f49c039ddd3df5a227d5a9be Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Sat, 17 Jul 2021 20:56:31 +0100 Subject: [PATCH 05/21] Class methods for the tensor of rank greater than 2 --- src/Math-Matrix/PMTensor.class.st | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Math-Matrix/PMTensor.class.st b/src/Math-Matrix/PMTensor.class.st index 68a04c45..9bace9df 100644 --- a/src/Math-Matrix/PMTensor.class.st +++ b/src/Math-Matrix/PMTensor.class.st @@ -10,6 +10,28 @@ Class { #category : #'Math-Matrix' } +{ #category : #'instance creation' } +PMTensor class >> newWith: anInteger [ + + ^ self new array: {anInteger} withShape: #( ) +] + +{ #category : #'instance creation' } +PMTensor class >> rows: anArray [ + + ^ self new array: anArray flattened withShape: (self shape:anArray) +] + +{ #category : #accessing } +PMTensor class >> shape: anArray [ + +anArray isArray ifFalse:[^#()] +ifTrue:[ + ^ {anArray size}, (self shape: anArray first) + ] + +] + { #category : #comparing } PMTensor >> = aTensor [ From c3d803a31387c9749ea797515926a975e8f04a03 Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Sat, 17 Jul 2021 20:57:13 +0100 Subject: [PATCH 06/21] The test class and the operations defined for the tensor of rank greater than 2 --- src/Math-Matrix/PMTensorTest.class.st | 191 ++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 src/Math-Matrix/PMTensorTest.class.st diff --git a/src/Math-Matrix/PMTensorTest.class.st b/src/Math-Matrix/PMTensorTest.class.st new file mode 100644 index 00000000..6464a909 --- /dev/null +++ b/src/Math-Matrix/PMTensorTest.class.st @@ -0,0 +1,191 @@ +Class { + #name : #PMTensorTest, + #superclass : #TestCase, + #category : #'Math-Matrix' +} + +{ #category : #tests } +PMTensorTest >> testArray [ + + | t1 t2 | + t1 := PMTensor rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: t1 array equals: #( 1 2 3 4 5 6 7 8 ). + + t2 := PMTensor rows: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self + assert: t2 array + equals: #( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ) +] + +{ #category : #tests } +PMTensorTest >> testCreateScalarTensor [ + + | s | + s := PMTensor newWith: 2. + self assert: (s get: #( )) equals: 2. + self should: [ s get: #( 1 1 ) ] raise: Error. + self assert: s rank equals: 0. + s set: #( ) value: 1. + self assert: (s get: #( )) equals: 1. + self assert: s shape equals: #( ). + self assert: s size equals: 1 +] + +{ #category : #tests } +PMTensorTest >> testFirst [ + + | a b | + a := PMTensor rows: (1 to: 6) asArray. + self assert: a first equals: #( 1). + b := a reshape: #( 3 2 ). + self assert: b first equals: #( 1 1 ) +] + +{ #category : #tests } +PMTensorTest >> testGet [ + + | t1 t2 | + t1 := PMTensor rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: (t1 get: #( 2 2 )) equals: 6. + + t2 := PMTensor rows: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self assert: (t2 get: #( 3 2 1 )) equals: 11. + + self should:[t1 get: #( 4 4 )] raise:Error +] + +{ #category : #tests } +PMTensorTest >> testGetPosition [ + + | t1 t2 | + t1 := PMTensor rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: (t1 getPosition: #( 1 2 )) equals: 2. + + t2 := PMTensor rows: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self assert: (t2 getPosition: #( 1 2 2 )) equals: 4 +] + +{ #category : #tests } +PMTensorTest >> testRank [ + + | t1 t2 | + + t1 := PMTensor rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: t1 rank equals: 2. + + t2 := PMTensor rows: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self assert: t2 rank equals: 3 +] + +{ #category : #tests } +PMTensorTest >> testReshape [ + + | t t1 | + t := PMTensor rows: #( #( 0 1 ) #( 2 3 ) #( 4 5 ) ). + t1 := t reshape: #( 2 3 ). + + self assert: t shape equals: #( 3 2 ). + self assert: t1 shape equals: #( 2 3 ). + self assert: t1 array == t array equals: true +] + +{ #category : #tests } +PMTensorTest >> testRows [ + + | t1 t2 | + t1 := PMTensor rows: #( #( 1 2 3 4 ) + #( 5 6 7 8 ) ). + self assert: t1 class equals: PMTensor. + + t2 := PMTensor rows: #( #( #( 1 1 ) #( 2 2 ) ) + #( #( 3 3 ) #( 4 4 ) ) + #( #( 4 4 ) #( 4 4 ) ) + #( #( 4 4 ) #( 4 4 ) ) ). + self assert: t2 class equals: PMTensor. + +] + +{ #category : #tests } +PMTensorTest >> testSetValue [ + + | t1 t2 | + t1 := PMTensor rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + t1 set: #( 2 2 ) value: 3. + self assert: (t1 get: #( 2 2 ) ) equals: 3. + + t2 := PMTensor rows: #( #( #( 1 2 ) #( 3 4 ) ) + #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) + #( #( 13 14 ) #( 15 16 ) ) ). + t2 set: #( 2 2 1) value: 10. + self assert: (t2 get: #( 2 2 1 )) equals: 10 +] + +{ #category : #tests } +PMTensorTest >> testShape [ + + | t1 t2 | + t1 := PMTensor rows: #( #( 1 2 3 4 ) + #( 5 6 7 8 ) ). + self assert: t1 shape equals: #( 2 4 ). + + t2 := PMTensor rows: #( #( #( 1 1 ) #( 2 2 ) ) + #( #( 3 3 ) #( 4 4 ) ) + #( #( 4 4 ) #( 4 4 ) ) + #( #( 4 4 ) #( 4 4 ) ) ). + self assert: t2 shape equals: #( 4 2 2 ) +] + +{ #category : #tests } +PMTensorTest >> testSize [ + + | t1 t2 | + t1 := PMTensor rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: t1 size equals: 8. + + t2 := PMTensor rows: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self assert: t2 size equals: 16 +] + +{ #category : #tests } +PMTensorTest >> testStrides [ + + | a b | + a := PMTensor rows: (1 to: 24) asArray. + self assert: a strides equals: #( 1 ). + b := a reshape: #( 4 6 ). + self assert: b strides equals: #( 6 1 ). + b := a reshape: #( 6 4 ). + self assert: b strides equals: #( 4 1 ). + self assert: (b getPosition: #( 4 2 )) equals: 14. + b := a reshape: #( 3 4 2 ). + self assert: b strides equals: #( 8 2 1 ). + self assert: (b getPosition: #( 3 2 1)) equals: 19. + b := a reshape: #( 2 3 4 ). + self assert: b strides equals: #( 12 4 1 ). + self assert: (b getPosition: #( 2 2 3 )) equals: 19 +] + +{ #category : #tests } +PMTensorTest >> testView [ + + | t t1 | + t := PMTensor rows: + #( #( 10 11 12 ) #( 13 14 15 ) #( 16 17 18 ) #( #( 20 21 22 ) + #( 23 24 25 ) #( 26 27 28 ) ) + #( #( 30 31 32 ) #( 33 34 35 ) #( 36 37 38 ) ) ). + t1 := t view. + self assert: t array == t1 array equals: true. + self assert: t shape equals: t1 shape. + self assert: t shape == t1 shape equals: false. + self assert: t strides equals: t1 strides. + self assert: t strides == t1 strides equals: false. + self assert: t first equals: t1 first. + self assert: t first == t1 first equals: false. + +] From a0d567dcd7bade434767155415d102801a30393f Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Sat, 17 Jul 2021 20:57:51 +0100 Subject: [PATCH 07/21] The error management mechanism for our tensors --- src/Math-Matrix/ShapeMismatch.class.st | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/Math-Matrix/ShapeMismatch.class.st diff --git a/src/Math-Matrix/ShapeMismatch.class.st b/src/Math-Matrix/ShapeMismatch.class.st new file mode 100644 index 00000000..a56c23fa --- /dev/null +++ b/src/Math-Matrix/ShapeMismatch.class.st @@ -0,0 +1,19 @@ +Class { + #name : #ShapeMismatch, + #superclass : #Error, + #category : #'Math-Matrix' +} + +{ #category : #accessing } +ShapeMismatch >> messageText [ + "Overwritten to initialiaze the message text to a standard text if it has not yet been set" + + ^ messageText ifNil: [ messageText := self standardMessageText ] +] + +{ #category : #printing } +ShapeMismatch >> standardMessageText [ + "Generate a standard textual description" + + ^ 'Tensor shapes do not match' +] From fb2ba9aba40a6b8945885f095d0aa769824b057d Mon Sep 17 00:00:00 2001 From: Yvan Guifo <56076081+YvanGuifo@users.noreply.github.com> Date: Wed, 21 Jul 2021 07:48:53 +0100 Subject: [PATCH 08/21] Delete PMTensorRank2.class.st --- src/Math-Matrix/PMTensorRank2.class.st | 174 ------------------------- 1 file changed, 174 deletions(-) delete mode 100644 src/Math-Matrix/PMTensorRank2.class.st diff --git a/src/Math-Matrix/PMTensorRank2.class.st b/src/Math-Matrix/PMTensorRank2.class.st deleted file mode 100644 index ca38700e..00000000 --- a/src/Math-Matrix/PMTensorRank2.class.st +++ /dev/null @@ -1,174 +0,0 @@ -Class { - #name : #PMTensorRank2, - #superclass : #Object, - #instVars : [ - 'array', - 'shape' - ], - #category : #'Math-Matrix' -} - -{ #category : #'instance creation' } -PMTensorRank2 class >> rows: anArray [ - - - ^ self new array: anArray flattened withShape: { - anArray size. - (anArray at: 1) size } -] - -{ #category : #'as yet unclassified' } -PMTensorRank2 class >> zerosWithShape: aShape [ - - ^ self new - array: (Array new: aShape first * aShape second withAll:0) - withShape: aShape -] - -{ #category : #arithmetic } -PMTensorRank2 >> * aPMTensor [ - - (self checkProductMatrixSize: aPMTensor) - ifTrue: [ - | t | - t := self class zerosWithShape: { - self numberOfLines. - aPMTensor numberOfColumns }. - - 1 to: self numberOfLines do: [ :i | - 1 to: aPMTensor numberOfColumns do: [ :j | - t - set: { i. j } - value: - ((1 to: self numberOfColumns) inject: 0 into: [ :sum :k | - (self get: { i. k }) * (aPMTensor get: { k. j }) + sum ]) ] ]. - ^ t ] - ifFalse: [ ShapeMismatch signal ] -] - -{ #category : #comparing } -PMTensorRank2 >> = aPMTensorRank2 [ - -^ (self hasSameShapeAs: aPMTensorRank2) & (self array = aPMTensorRank2 array) -] - -{ #category : #accessing } -PMTensorRank2 >> array [ - ^ array -] - -{ #category : #'as yet unclassified' } -PMTensorRank2 >> array: aFlatArray withShape: aShape [ - array := aFlatArray. - shape := aShape -] - -{ #category : #'as yet unclassified' } -PMTensorRank2 >> checkProductMatrixSize: aPMTensorRank2 [ - - ^ self numberOfColumns = aPMTensorRank2 numberOfLines -] - -{ #category : #'as yet unclassified' } -PMTensorRank2 >> checkReshapeIsPossibleWith: aNewShape [ - - ^ (shape first * shape second) = ((aNewShape first) * (aNewShape second)) -] - -{ #category : #public } -PMTensorRank2 >> get: coords [ - | row column | - row := coords first. - column := coords second. - ^ array at: (row - 1) * (shape second) + column -] - -{ #category : #operation } -PMTensorRank2 >> hadamardProduct: aPMTensorRank2 [ - (self hasSameShapeAs: aPMTensorRank2) - ifTrue:[ - ^ self class new array: ((self array) with: (aPMTensorRank2 array) collect:[:a :b| a*b]) - withShape: self shape. - ] - ifFalse:[ShapeMismatch signal ] -] - -{ #category : #testing } -PMTensorRank2 >> hasSameShapeAs: aTensorRank2 [ - ^ self shape = aTensorRank2 shape -] - -{ #category : #'as yet unclassified' } -PMTensorRank2 >> kroneckerProduct: aPMTensor [ - - | t | - t := self class zerosWithShape: { - ((self numberOfLines) * (aPMTensor numberOfLines)). - ((self numberOfColumns) * (aPMTensor numberOfColumns)) }. - - 1 to: self numberOfLines do: [ :i1 | - 1 to: self numberOfColumns do: [ :j1 | - 1 to: aPMTensor numberOfLines do: [ :i2 | - 1 to: aPMTensor numberOfColumns do: [ :j2 | - t set: { (i1-1)*(aPMTensor numberOfLines)+i2. (j1-1)*(aPMTensor numberOfColumns)+j2 } - value: (self get:{i1. j1})* (aPMTensor get:{ i2.j2 }) - ] - ] - ] - ]. - ^t -] - -{ #category : #accessing } -PMTensorRank2 >> numberOfColumns [ - ^ shape second -] - -{ #category : #accessing } -PMTensorRank2 >> numberOfLines [ - ^ shape first -] - -{ #category : #'as yet unclassified' } -PMTensorRank2 >> outerProduct: aPMTensor [ - - | t | - t := self class zerosWithShape: { - ((self numberOfLines) * (aPMTensor numberOfLines)). - ((self numberOfColumns) * (aPMTensor numberOfColumns)) }. - - 1 to: self numberOfLines do: [ :i1 | - 1 to: self numberOfColumns do: [ :j1 | - 1 to: aPMTensor numberOfLines do: [ :i2 | - 1 to: aPMTensor numberOfColumns do: [ :j2 | - t set: { (i1-1)*(aPMTensor numberOfLines)+i2. (j1-1)*(aPMTensor numberOfColumns)+j2 } - value: (self get:{i1. i2}) * (aPMTensor get:{ j1. j2 }) - ] - ] - ] - ]. - ^t -] - -{ #category : #'as yet unclassified' } -PMTensorRank2 >> reshape: aNewShape [ - - (self checkReshapeIsPossibleWith: aNewShape) - ifTrue: [ shape := aNewShape ] - ifFalse: [ ShapeMismatch signal ] -] - -{ #category : #initialization } -PMTensorRank2 >> set: coords value: aValue [ - - | row column | - row := coords first. - column := coords second. - array at: row - 1 * shape second + column put: aValue -] - -{ #category : #accessing } -PMTensorRank2 >> shape [ - - ^ shape -] From 4de26bd6a6f6f7ec80c39f8c91336cc7f912da3d Mon Sep 17 00:00:00 2001 From: Yvan Guifo <56076081+YvanGuifo@users.noreply.github.com> Date: Wed, 21 Jul 2021 07:51:18 +0100 Subject: [PATCH 09/21] Delete PMTensorRank2Test.class.st --- src/Math-Matrix/PMTensorRank2Test.class.st | 154 --------------------- 1 file changed, 154 deletions(-) delete mode 100644 src/Math-Matrix/PMTensorRank2Test.class.st diff --git a/src/Math-Matrix/PMTensorRank2Test.class.st b/src/Math-Matrix/PMTensorRank2Test.class.st deleted file mode 100644 index 0709167b..00000000 --- a/src/Math-Matrix/PMTensorRank2Test.class.st +++ /dev/null @@ -1,154 +0,0 @@ -Class { - #name : #PMTensorRank2Test, - #superclass : #TestCase, - #instVars : [ - 'array' - ], - #category : #'Math-Matrix' -} - -{ #category : #tests } -PMTensorRank2Test >> testHadamardProduct [ -|t1 t2| - t1 := PMTensorRank2 rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - t2 := PMTensorRank2 rows: #( #( 4 3 2 9 ) #( 9 7 6 5 ) ). - self assert: (t1 hadamardProduct: t2) equals: (PMTensorRank2 rows:#( #( 4 6 6 36 ) #( 45 42 42 40 ) )) -] - -{ #category : #tests } -PMTensorRank2Test >> testHadamardProductWithDifferentShapes [ -|t1 t2| - t1 := PMTensorRank2 rows: #( #( 1 2) #(3 4) #(5 6) #(7 8)). - t2 := PMTensorRank2 rows: #( #( 4 3 2 9 ) #( 9 7 6 5 ) ). - self should: [t1 hadamardProduct: t2] raise: ShapeMismatch -] - -{ #category : #tests } -PMTensorRank2Test >> testKroneckerProduct [ -|t1 t2| - t1 := PMTensorRank2 rows: #( #( 1 2 ) - #( 3 1 )). - t2 := PMTensorRank2 rows: #( #( 1 3 ) - #( 2 1 )). - self assert: (t1 kroneckerProduct: t2) equals: (PMTensorRank2 rows:#( - #( 1 3 2 6 ) - #( 2 1 4 2 ) - #( 3 9 1 3 ) - #( 6 3 2 1 ) )). - t1 := PMTensorRank2 rows: #( #( 1 2) - #(3 4) - #( 1 0 )). - t2 := PMTensorRank2 rows: #( #( 0 5 2 ) - #( 6 7 3)). - self assert: (t1 kroneckerProduct: t2) equals: (PMTensorRank2 rows:#( - #( 0 5 2 0 10 4) - #( 6 7 3 12 14 6) - #( 0 15 6 0 20 8) - #( 18 21 9 24 28 12) - #( 0 5 2 0 0 0) - #( 6 7 3 0 0 0 ) - )) -] - -{ #category : #tests } -PMTensorRank2Test >> testOrdinaryProduct [ -|t1 t2| - t1 := PMTensorRank2 rows: #( #( 1 2 ) - #( 3 4 )). - t2 := PMTensorRank2 rows: #( #( 4 3 ) - #( 2 5 )). - self assert: (t1 * t2) equals: (PMTensorRank2 rows:#( #( 8 13 ) #( 20 29 ) )) -] - -{ #category : #tests } -PMTensorRank2Test >> testOrdinaryProductWithTheNumberOFLineOfFirstTensorIsEqualsOfNumberOfColumnToSecondTensor [ - - | t1 t2 | - t1 := PMTensorRank2 rows: #( #( 1 2 ) #( 3 4 ) #( 5 6 ) ). - t2 := PMTensorRank2 rows: #( #( 4 3 2 ) #( 9 7 6 ) #(10 11 12)). - self should: [ t1 * t2 ] raise: ShapeMismatch -] - -{ #category : #tests } -PMTensorRank2Test >> testOuterProduct [ -|t1 t2| - t1 := PMTensorRank2 rows: #( #( 1 2 ) - #( 3 1 ) ). - t2 := PMTensorRank2 rows: #( #( 1 3 ) - #( 2 1 ) ). - self assert: (t1 outerProduct: t2) equals: (PMTensorRank2 rows:#( #( 1 3 2 1 ) - #( 2 6 4 2 ) - #( 3 9 6 3 ) - #(1 3 2 1))). - -t1 := PMTensorRank2 rows: #( #( 1 2) - #(3 4) - #( 1 0 )). - t2 := PMTensorRank2 rows: #( #( 0 5 2 ) - #( 6 7 3)). - self assert: (t1 outerProduct: t2) equals: (PMTensorRank2 rows:#( - #( 0 5 2 6 7 3) - #( 0 10 4 12 14 6) - #( 0 15 6 18 21 9) - #( 0 20 8 24 28 12) - #( 0 5 2 6 7 3) - #( 0 0 0 0 0 0 ) - )) -] - -{ #category : #tests } -PMTensorRank2Test >> testReShape [ - - | t | - t := PMTensorRank2 rows: #(#(0 1) #(2 3) #(4 5)). - self assert: (t reshape: #(2 3)) equals: (PMTensorRank2 rows:#(#(0 1 2) #(3 4 5))) -] - -{ #category : #tests } -PMTensorRank2Test >> testReShapeNotPossible [ - - | t | - t := PMTensorRank2 rows: #( #( 0 1 ) #( 2 3 ) #( 4 5 ) ). - self - should: [t reshape: #( 5 3 )] - raise: ShapeMismatch -] - -{ #category : #tests } -PMTensorRank2Test >> testRows [ - - | t1 t2| - t1 := PMTensorRank2 rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: (t1 get: #(1 1)) equals: 1. - self assert: (t1 get: #(2 1)) equals: 5. - self assert: (t1 get: #(2 4)) equals: 8. - t2 := PMTensorRank2 rows: #( #( 1 2) #(3 4) #( 5 6) #(7 8 )). - self assert: (t2 get: #(1 1)) equals: 1. - self assert: (t2 get: #(2 1)) equals: 3. - self assert: (t2 get: #(4 2)) equals: 8. - - - -] - -{ #category : #tests } -PMTensorRank2Test >> testShape [ - - | t | - t := PMTensorRank2 rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: t shape equals: #( 2 4 ) -] - -{ #category : #tests } -PMTensorRank2Test >> testZerosWithShape [ - - | t | - t := PMTensorRank2 zerosWithShape: #( 10 10 ). - 1 to: t numberOfColumns do: [ :i | - 1 to: t numberOfLines do: [ :j | - self - assert: (t get: { - i. - j }) - equals: 0 ] ] -] From d4f52debf9aca45cb2f1d24e9930552e297b4ac5 Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Mon, 26 Jul 2021 12:58:10 +0100 Subject: [PATCH 10/21] Renaming methods. To make the names more expressive --- src/Math-Matrix/PMTensor.class.st | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/Math-Matrix/PMTensor.class.st b/src/Math-Matrix/PMTensor.class.st index 9bace9df..5b7c848e 100644 --- a/src/Math-Matrix/PMTensor.class.st +++ b/src/Math-Matrix/PMTensor.class.st @@ -11,15 +11,15 @@ Class { } { #category : #'instance creation' } -PMTensor class >> newWith: anInteger [ +PMTensor class >> fromNestedArray: anArray [ - ^ self new array: {anInteger} withShape: #( ) + ^ self new array: anArray flattened withShape: (self shape:anArray) ] { #category : #'instance creation' } -PMTensor class >> rows: anArray [ +PMTensor class >> newWith: anInteger [ - ^ self new array: anArray flattened withShape: (self shape:anArray) + ^ self new array: {anInteger} withShape: #( ) ] { #category : #accessing } @@ -58,6 +58,15 @@ PMTensor >> first [ ^first ] +{ #category : #'as yet unclassified' } +PMTensor >> flattenedIndexOf: aFlatArray withShape: aShape [ + + array := aFlatArray. + shape := aShape copy. + self updateFirst. + shape ifNotEmpty: [ self updateStrides] +] + { #category : #public } PMTensor >> get: coords [ From 2c9d247ec140d5037a4beef57e641a514672c845 Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Mon, 26 Jul 2021 13:03:01 +0100 Subject: [PATCH 11/21] Modification of the tests taking into account the modified methods --- src/Math-Matrix/PMTensorTest.class.st | 68 +++++++++++++-------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/Math-Matrix/PMTensorTest.class.st b/src/Math-Matrix/PMTensorTest.class.st index 6464a909..395fe10c 100644 --- a/src/Math-Matrix/PMTensorTest.class.st +++ b/src/Math-Matrix/PMTensorTest.class.st @@ -8,10 +8,10 @@ Class { PMTensorTest >> testArray [ | t1 t2 | - t1 := PMTensor rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). self assert: t1 array equals: #( 1 2 3 4 5 6 7 8 ). - t2 := PMTensor rows: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + t2 := PMTensor fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). self assert: t2 array @@ -36,20 +36,36 @@ PMTensorTest >> testCreateScalarTensor [ PMTensorTest >> testFirst [ | a b | - a := PMTensor rows: (1 to: 6) asArray. + a := PMTensor fromNestedArray: (1 to: 6) asArray. self assert: a first equals: #( 1). b := a reshape: #( 3 2 ). self assert: b first equals: #( 1 1 ) ] +{ #category : #tests } +PMTensorTest >> testFromNestedArray [ + + | t1 t2 | + t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) + #( 5 6 7 8 ) ). + self assert: t1 class equals: PMTensor. + + t2 := PMTensor fromNestedArray: #( #( #( 1 1 ) #( 2 2 ) ) + #( #( 3 3 ) #( 4 4 ) ) + #( #( 4 4 ) #( 4 4 ) ) + #( #( 4 4 ) #( 4 4 ) ) ). + self assert: t2 class equals: PMTensor. + +] + { #category : #tests } PMTensorTest >> testGet [ | t1 t2 | - t1 := PMTensor rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). self assert: (t1 get: #( 2 2 )) equals: 6. - t2 := PMTensor rows: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + t2 := PMTensor fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). self assert: (t2 get: #( 3 2 1 )) equals: 11. @@ -60,10 +76,10 @@ PMTensorTest >> testGet [ PMTensorTest >> testGetPosition [ | t1 t2 | - t1 := PMTensor rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). self assert: (t1 getPosition: #( 1 2 )) equals: 2. - t2 := PMTensor rows: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + t2 := PMTensor fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). self assert: (t2 getPosition: #( 1 2 2 )) equals: 4 ] @@ -73,10 +89,10 @@ PMTensorTest >> testRank [ | t1 t2 | - t1 := PMTensor rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). self assert: t1 rank equals: 2. - t2 := PMTensor rows: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + t2 := PMTensor fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). self assert: t2 rank equals: 3 ] @@ -85,7 +101,7 @@ PMTensorTest >> testRank [ PMTensorTest >> testReshape [ | t t1 | - t := PMTensor rows: #( #( 0 1 ) #( 2 3 ) #( 4 5 ) ). + t := PMTensor fromNestedArray: #( #( 0 1 ) #( 2 3 ) #( 4 5 ) ). t1 := t reshape: #( 2 3 ). self assert: t shape equals: #( 3 2 ). @@ -93,31 +109,15 @@ PMTensorTest >> testReshape [ self assert: t1 array == t array equals: true ] -{ #category : #tests } -PMTensorTest >> testRows [ - - | t1 t2 | - t1 := PMTensor rows: #( #( 1 2 3 4 ) - #( 5 6 7 8 ) ). - self assert: t1 class equals: PMTensor. - - t2 := PMTensor rows: #( #( #( 1 1 ) #( 2 2 ) ) - #( #( 3 3 ) #( 4 4 ) ) - #( #( 4 4 ) #( 4 4 ) ) - #( #( 4 4 ) #( 4 4 ) ) ). - self assert: t2 class equals: PMTensor. - -] - { #category : #tests } PMTensorTest >> testSetValue [ | t1 t2 | - t1 := PMTensor rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). t1 set: #( 2 2 ) value: 3. self assert: (t1 get: #( 2 2 ) ) equals: 3. - t2 := PMTensor rows: #( #( #( 1 2 ) #( 3 4 ) ) + t2 := PMTensor fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). @@ -129,11 +129,11 @@ PMTensorTest >> testSetValue [ PMTensorTest >> testShape [ | t1 t2 | - t1 := PMTensor rows: #( #( 1 2 3 4 ) + t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). self assert: t1 shape equals: #( 2 4 ). - t2 := PMTensor rows: #( #( #( 1 1 ) #( 2 2 ) ) + t2 := PMTensor fromNestedArray: #( #( #( 1 1 ) #( 2 2 ) ) #( #( 3 3 ) #( 4 4 ) ) #( #( 4 4 ) #( 4 4 ) ) #( #( 4 4 ) #( 4 4 ) ) ). @@ -144,10 +144,10 @@ PMTensorTest >> testShape [ PMTensorTest >> testSize [ | t1 t2 | - t1 := PMTensor rows: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). self assert: t1 size equals: 8. - t2 := PMTensor rows: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + t2 := PMTensor fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). self assert: t2 size equals: 16 ] @@ -156,7 +156,7 @@ PMTensorTest >> testSize [ PMTensorTest >> testStrides [ | a b | - a := PMTensor rows: (1 to: 24) asArray. + a := PMTensor fromNestedArray: (1 to: 24) asArray. self assert: a strides equals: #( 1 ). b := a reshape: #( 4 6 ). self assert: b strides equals: #( 6 1 ). @@ -175,7 +175,7 @@ PMTensorTest >> testStrides [ PMTensorTest >> testView [ | t t1 | - t := PMTensor rows: + t := PMTensor fromNestedArray: #( #( 10 11 12 ) #( 13 14 15 ) #( 16 17 18 ) #( #( 20 21 22 ) #( 23 24 25 ) #( 26 27 28 ) ) #( #( 30 31 32 ) #( 33 34 35 ) #( 36 37 38 ) ) ). From 2ae081b0aee31aef25d1a4292cbf3741a0cb031d Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Mon, 26 Jul 2021 15:29:23 +0100 Subject: [PATCH 12/21] Renaming methods. --- src/Math-Matrix/PMTensor.class.st | 39 ++++++++++++++++++------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/Math-Matrix/PMTensor.class.st b/src/Math-Matrix/PMTensor.class.st index 5b7c848e..f5133199 100644 --- a/src/Math-Matrix/PMTensor.class.st +++ b/src/Math-Matrix/PMTensor.class.st @@ -58,6 +58,16 @@ PMTensor >> first [ ^first ] +{ #category : #'primitives - file' } +PMTensor >> flattenedIndexOf: coords [ + + | position | + position := 1. + coords withIndexDo: [ :elt :i | + position := elt - 1 * (strides at: i) + position ]. + ^ position +] + { #category : #'as yet unclassified' } PMTensor >> flattenedIndexOf: aFlatArray withShape: aShape [ @@ -67,22 +77,21 @@ PMTensor >> flattenedIndexOf: aFlatArray withShape: aShape [ shape ifNotEmpty: [ self updateStrides] ] -{ #category : #public } -PMTensor >> get: coords [ +{ #category : #'as yet unclassified' } +PMTensor >> fromNestedArray: aFlatArray withShape: aShape [ - | position | - position := self getPosition: coords. - ^ array at: position + array := aFlatArray. + shape := aShape copy. + self updateFirst. + shape ifNotEmpty: [ self updateStrides] ] -{ #category : #'primitives - file' } -PMTensor >> getPosition: coords [ +{ #category : #public } +PMTensor >> get: coords [ | position | - position := 1. - coords withIndexDo: [ :elt :i | - position := elt - 1 * (strides at: i) + position ]. - ^ position + position := self flattenedIndexOf: coords. + ^ array at: position ] { #category : #accessing } @@ -100,7 +109,7 @@ PMTensor >> reshape: aNewShape [ { #category : #initialization } PMTensor >> set: coords value: aValue [ -array at: (self getPosition: coords) put: aValue +array at: (self flattenedIndexOf: coords) put: aValue ] { #category : #accessing } @@ -112,10 +121,8 @@ PMTensor >> shape [ { #category : #accessing } PMTensor >> size [ - | product | - product := 1. - shape do: [ :each | product := each * product ]. - ^ product +^ shape inject: 1 into: [ :each :product | each * product]. + ] { #category : #accessing } From 8062a30d166f82ea2ff4ff29e892ee6402aa8628 Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Mon, 26 Jul 2021 15:30:32 +0100 Subject: [PATCH 13/21] Modification of the tests taking into account the modified methods --- src/Math-Matrix/PMTensor.class.st | 9 -------- src/Math-Matrix/PMTensorTest.class.st | 30 +++++++++++++-------------- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/src/Math-Matrix/PMTensor.class.st b/src/Math-Matrix/PMTensor.class.st index f5133199..2a35b3dd 100644 --- a/src/Math-Matrix/PMTensor.class.st +++ b/src/Math-Matrix/PMTensor.class.st @@ -68,15 +68,6 @@ PMTensor >> flattenedIndexOf: coords [ ^ position ] -{ #category : #'as yet unclassified' } -PMTensor >> flattenedIndexOf: aFlatArray withShape: aShape [ - - array := aFlatArray. - shape := aShape copy. - self updateFirst. - shape ifNotEmpty: [ self updateStrides] -] - { #category : #'as yet unclassified' } PMTensor >> fromNestedArray: aFlatArray withShape: aShape [ diff --git a/src/Math-Matrix/PMTensorTest.class.st b/src/Math-Matrix/PMTensorTest.class.st index 395fe10c..0796c1d3 100644 --- a/src/Math-Matrix/PMTensorTest.class.st +++ b/src/Math-Matrix/PMTensorTest.class.st @@ -42,6 +42,18 @@ PMTensorTest >> testFirst [ self assert: b first equals: #( 1 1 ) ] +{ #category : #tests } +PMTensorTest >> testFlattenedIndexOf [ + + | t1 t2 | + t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: (t1 flattenedIndexOf: #( 1 2 )) equals: 2. + + t2 := PMTensor fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self assert: (t2 flattenedIndexOf: #( 1 2 2 )) equals: 4 +] + { #category : #tests } PMTensorTest >> testFromNestedArray [ @@ -72,18 +84,6 @@ PMTensorTest >> testGet [ self should:[t1 get: #( 4 4 )] raise:Error ] -{ #category : #tests } -PMTensorTest >> testGetPosition [ - - | t1 t2 | - t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: (t1 getPosition: #( 1 2 )) equals: 2. - - t2 := PMTensor fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self assert: (t2 getPosition: #( 1 2 2 )) equals: 4 -] - { #category : #tests } PMTensorTest >> testRank [ @@ -162,13 +162,13 @@ PMTensorTest >> testStrides [ self assert: b strides equals: #( 6 1 ). b := a reshape: #( 6 4 ). self assert: b strides equals: #( 4 1 ). - self assert: (b getPosition: #( 4 2 )) equals: 14. + self assert: (b flattenedIndexOf: #( 4 2 )) equals: 14. b := a reshape: #( 3 4 2 ). self assert: b strides equals: #( 8 2 1 ). - self assert: (b getPosition: #( 3 2 1)) equals: 19. + self assert: (b flattenedIndexOf: #( 3 2 1)) equals: 19. b := a reshape: #( 2 3 4 ). self assert: b strides equals: #( 12 4 1 ). - self assert: (b getPosition: #( 2 2 3 )) equals: 19 + self assert: (b flattenedIndexOf: #( 2 2 3 )) equals: 19 ] { #category : #tests } From e8455f10f252ffaa7e8b89daf241d446fdb0cad4 Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Thu, 29 Jul 2021 20:30:49 +0100 Subject: [PATCH 14/21] Delete PMTensor class and PMTensorTest --- src/Math-Matrix/PMTensor.class.st | 152 -------------------- src/Math-Matrix/PMTensorTest.class.st | 191 -------------------------- 2 files changed, 343 deletions(-) delete mode 100644 src/Math-Matrix/PMTensor.class.st delete mode 100644 src/Math-Matrix/PMTensorTest.class.st diff --git a/src/Math-Matrix/PMTensor.class.st b/src/Math-Matrix/PMTensor.class.st deleted file mode 100644 index 2a35b3dd..00000000 --- a/src/Math-Matrix/PMTensor.class.st +++ /dev/null @@ -1,152 +0,0 @@ -Class { - #name : #PMTensor, - #superclass : #Object, - #instVars : [ - 'array', - 'shape', - 'first', - 'strides' - ], - #category : #'Math-Matrix' -} - -{ #category : #'instance creation' } -PMTensor class >> fromNestedArray: anArray [ - - ^ self new array: anArray flattened withShape: (self shape:anArray) -] - -{ #category : #'instance creation' } -PMTensor class >> newWith: anInteger [ - - ^ self new array: {anInteger} withShape: #( ) -] - -{ #category : #accessing } -PMTensor class >> shape: anArray [ - -anArray isArray ifFalse:[^#()] -ifTrue:[ - ^ {anArray size}, (self shape: anArray first) - ] - -] - -{ #category : #comparing } -PMTensor >> = aTensor [ - - ^ array = aTensor array & (first = aTensor first) - & (strides = aTensor strides) & (shape = aTensor shape) -] - -{ #category : #accessing } -PMTensor >> array [ -^array -] - -{ #category : #'as yet unclassified' } -PMTensor >> array: aFlatArray withShape: aShape [ - - array := aFlatArray. - shape := aShape copy. - self updateFirst. - shape ifNotEmpty: [ self updateStrides] -] - -{ #category : #accessing } -PMTensor >> first [ -^first -] - -{ #category : #'primitives - file' } -PMTensor >> flattenedIndexOf: coords [ - - | position | - position := 1. - coords withIndexDo: [ :elt :i | - position := elt - 1 * (strides at: i) + position ]. - ^ position -] - -{ #category : #'as yet unclassified' } -PMTensor >> fromNestedArray: aFlatArray withShape: aShape [ - - array := aFlatArray. - shape := aShape copy. - self updateFirst. - shape ifNotEmpty: [ self updateStrides] -] - -{ #category : #public } -PMTensor >> get: coords [ - - | position | - position := self flattenedIndexOf: coords. - ^ array at: position -] - -{ #category : #accessing } -PMTensor >> rank [ - ^ shape size -] - -{ #category : #'as yet unclassified' } -PMTensor >> reshape: aNewShape [ - - ^ self viewWithShape: aNewShape. - -] - -{ #category : #initialization } -PMTensor >> set: coords value: aValue [ - -array at: (self flattenedIndexOf: coords) put: aValue -] - -{ #category : #accessing } -PMTensor >> shape [ - - ^ shape -] - -{ #category : #accessing } -PMTensor >> size [ - -^ shape inject: 1 into: [ :each :product | each * product]. - -] - -{ #category : #accessing } -PMTensor >> strides [ -^strides -] - -{ #category : #'as yet unclassified' } -PMTensor >> updateFirst [ - - first := Array new: shape size withAll: 1 -] - -{ #category : #'as yet unclassified' } -PMTensor >> updateStrides [ - - strides := Array new: shape size. - strides at: shape size put: 1. - ((shape size -1) to: 1 by: -1) do: [ :i | - strides at: i put: ((strides at: i + 1) * (shape at: i+1))] -] - -{ #category : #'as yet unclassified' } -PMTensor >> view [ - - "Share only the array" - - ^ self viewWithShape: shape -] - -{ #category : #'as yet unclassified' } -PMTensor >> viewWithShape: aNewShape [ - - ^ PMTensor new array: self array withShape: aNewShape - -] diff --git a/src/Math-Matrix/PMTensorTest.class.st b/src/Math-Matrix/PMTensorTest.class.st deleted file mode 100644 index 0796c1d3..00000000 --- a/src/Math-Matrix/PMTensorTest.class.st +++ /dev/null @@ -1,191 +0,0 @@ -Class { - #name : #PMTensorTest, - #superclass : #TestCase, - #category : #'Math-Matrix' -} - -{ #category : #tests } -PMTensorTest >> testArray [ - - | t1 t2 | - t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: t1 array equals: #( 1 2 3 4 5 6 7 8 ). - - t2 := PMTensor fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self - assert: t2 array - equals: #( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ) -] - -{ #category : #tests } -PMTensorTest >> testCreateScalarTensor [ - - | s | - s := PMTensor newWith: 2. - self assert: (s get: #( )) equals: 2. - self should: [ s get: #( 1 1 ) ] raise: Error. - self assert: s rank equals: 0. - s set: #( ) value: 1. - self assert: (s get: #( )) equals: 1. - self assert: s shape equals: #( ). - self assert: s size equals: 1 -] - -{ #category : #tests } -PMTensorTest >> testFirst [ - - | a b | - a := PMTensor fromNestedArray: (1 to: 6) asArray. - self assert: a first equals: #( 1). - b := a reshape: #( 3 2 ). - self assert: b first equals: #( 1 1 ) -] - -{ #category : #tests } -PMTensorTest >> testFlattenedIndexOf [ - - | t1 t2 | - t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: (t1 flattenedIndexOf: #( 1 2 )) equals: 2. - - t2 := PMTensor fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self assert: (t2 flattenedIndexOf: #( 1 2 2 )) equals: 4 -] - -{ #category : #tests } -PMTensorTest >> testFromNestedArray [ - - | t1 t2 | - t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) - #( 5 6 7 8 ) ). - self assert: t1 class equals: PMTensor. - - t2 := PMTensor fromNestedArray: #( #( #( 1 1 ) #( 2 2 ) ) - #( #( 3 3 ) #( 4 4 ) ) - #( #( 4 4 ) #( 4 4 ) ) - #( #( 4 4 ) #( 4 4 ) ) ). - self assert: t2 class equals: PMTensor. - -] - -{ #category : #tests } -PMTensorTest >> testGet [ - - | t1 t2 | - t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: (t1 get: #( 2 2 )) equals: 6. - - t2 := PMTensor fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self assert: (t2 get: #( 3 2 1 )) equals: 11. - - self should:[t1 get: #( 4 4 )] raise:Error -] - -{ #category : #tests } -PMTensorTest >> testRank [ - - | t1 t2 | - - t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: t1 rank equals: 2. - - t2 := PMTensor fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self assert: t2 rank equals: 3 -] - -{ #category : #tests } -PMTensorTest >> testReshape [ - - | t t1 | - t := PMTensor fromNestedArray: #( #( 0 1 ) #( 2 3 ) #( 4 5 ) ). - t1 := t reshape: #( 2 3 ). - - self assert: t shape equals: #( 3 2 ). - self assert: t1 shape equals: #( 2 3 ). - self assert: t1 array == t array equals: true -] - -{ #category : #tests } -PMTensorTest >> testSetValue [ - - | t1 t2 | - t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - t1 set: #( 2 2 ) value: 3. - self assert: (t1 get: #( 2 2 ) ) equals: 3. - - t2 := PMTensor fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) - #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) - #( #( 13 14 ) #( 15 16 ) ) ). - t2 set: #( 2 2 1) value: 10. - self assert: (t2 get: #( 2 2 1 )) equals: 10 -] - -{ #category : #tests } -PMTensorTest >> testShape [ - - | t1 t2 | - t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) - #( 5 6 7 8 ) ). - self assert: t1 shape equals: #( 2 4 ). - - t2 := PMTensor fromNestedArray: #( #( #( 1 1 ) #( 2 2 ) ) - #( #( 3 3 ) #( 4 4 ) ) - #( #( 4 4 ) #( 4 4 ) ) - #( #( 4 4 ) #( 4 4 ) ) ). - self assert: t2 shape equals: #( 4 2 2 ) -] - -{ #category : #tests } -PMTensorTest >> testSize [ - - | t1 t2 | - t1 := PMTensor fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: t1 size equals: 8. - - t2 := PMTensor fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self assert: t2 size equals: 16 -] - -{ #category : #tests } -PMTensorTest >> testStrides [ - - | a b | - a := PMTensor fromNestedArray: (1 to: 24) asArray. - self assert: a strides equals: #( 1 ). - b := a reshape: #( 4 6 ). - self assert: b strides equals: #( 6 1 ). - b := a reshape: #( 6 4 ). - self assert: b strides equals: #( 4 1 ). - self assert: (b flattenedIndexOf: #( 4 2 )) equals: 14. - b := a reshape: #( 3 4 2 ). - self assert: b strides equals: #( 8 2 1 ). - self assert: (b flattenedIndexOf: #( 3 2 1)) equals: 19. - b := a reshape: #( 2 3 4 ). - self assert: b strides equals: #( 12 4 1 ). - self assert: (b flattenedIndexOf: #( 2 2 3 )) equals: 19 -] - -{ #category : #tests } -PMTensorTest >> testView [ - - | t t1 | - t := PMTensor fromNestedArray: - #( #( 10 11 12 ) #( 13 14 15 ) #( 16 17 18 ) #( #( 20 21 22 ) - #( 23 24 25 ) #( 26 27 28 ) ) - #( #( 30 31 32 ) #( 33 34 35 ) #( 36 37 38 ) ) ). - t1 := t view. - self assert: t array == t1 array equals: true. - self assert: t shape equals: t1 shape. - self assert: t shape == t1 shape equals: false. - self assert: t strides equals: t1 strides. - self assert: t strides == t1 strides equals: false. - self assert: t first equals: t1 first. - self assert: t first == t1 first equals: false. - -] From b28871f93512115a0312d9aa50f71d9d3b881ec3 Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Thu, 29 Jul 2021 20:34:13 +0100 Subject: [PATCH 15/21] Addition of the PMArray class replacing PMTensor --- src/Math-Matrix/PMArray.class.st | 152 +++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 src/Math-Matrix/PMArray.class.st diff --git a/src/Math-Matrix/PMArray.class.st b/src/Math-Matrix/PMArray.class.st new file mode 100644 index 00000000..dec83e4e --- /dev/null +++ b/src/Math-Matrix/PMArray.class.st @@ -0,0 +1,152 @@ +Class { + #name : #PMArray, + #superclass : #Object, + #instVars : [ + 'array', + 'shape', + 'first', + 'strides' + ], + #category : #'Math-Matrix' +} + +{ #category : #'instance creation' } +PMArray class >> fromNestedArray: anArray [ + + ^ self new array: anArray flattened withShape: (self shape:anArray) +] + +{ #category : #'instance creation' } +PMArray class >> newWith: anInteger [ + + ^ self new array: {anInteger} withShape: #( ) +] + +{ #category : #accessing } +PMArray class >> shape: anArray [ + +anArray isArray ifFalse:[^#()] +ifTrue:[ + ^ {anArray size}, (self shape: anArray first) + ] + +] + +{ #category : #comparing } +PMArray >> = anArray [ + + ^ array = anArray array & (first = anArray first) + & (strides = anArray strides) & (shape = anArray shape) +] + +{ #category : #accessing } +PMArray >> array [ +^array +] + +{ #category : #'as yet unclassified' } +PMArray >> array: aFlatArray withShape: aShape [ + + array := aFlatArray. + shape := aShape copy. + self updateFirst. + shape ifNotEmpty: [ self updateStrides] +] + +{ #category : #accessing } +PMArray >> first [ +^first +] + +{ #category : #'primitives - file' } +PMArray >> flattenedIndexOf: coords [ + + | position | + position := 1. + coords withIndexDo: [ :elt :i | + position := (elt - 1) * (strides at: i) + position ]. + ^ position +] + +{ #category : #'as yet unclassified' } +PMArray >> fromNestedArray: aFlatArray withShape: aShape [ + + array := aFlatArray. + shape := aShape copy. + self updateFirst. + shape ifNotEmpty: [ self updateStrides] +] + +{ #category : #public } +PMArray >> get: coords [ + + | position | + position := self flattenedIndexOf: coords. + ^ array at: position +] + +{ #category : #accessing } +PMArray >> rank [ + ^ shape size +] + +{ #category : #'as yet unclassified' } +PMArray >> reshape: aNewShape [ + + ^ self viewWithShape: aNewShape. + +] + +{ #category : #initialization } +PMArray >> set: coords value: aValue [ + +array at: (self flattenedIndexOf: coords) put: aValue +] + +{ #category : #accessing } +PMArray >> shape [ + + ^ shape +] + +{ #category : #accessing } +PMArray >> size [ + +^ shape inject: 1 into: [ :each :product | each * product]. + +] + +{ #category : #accessing } +PMArray >> strides [ +^strides +] + +{ #category : #'as yet unclassified' } +PMArray >> updateFirst [ + + first := Array new: shape size withAll: 1 +] + +{ #category : #'as yet unclassified' } +PMArray >> updateStrides [ + + strides := Array new: shape size. + strides at: shape size put: 1. + ((shape size -1) to: 1 by: -1) do: [ :i | + strides at: i put: ((strides at: i + 1) * (shape at: i+1))] +] + +{ #category : #'as yet unclassified' } +PMArray >> view [ + + "Share only the array" + + ^ self viewWithShape: shape +] + +{ #category : #'as yet unclassified' } +PMArray >> viewWithShape: aNewShape [ + + ^ PMArray new array: self array withShape: aNewShape + +] From 605be14ef1018b52637570bd833e1af3c9f7cb1d Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Thu, 29 Jul 2021 20:34:53 +0100 Subject: [PATCH 16/21] Addition of the PMArrayTest class replacing PMTensorTest --- src/Math-Matrix/PMArrayTest.class.st | 218 +++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 src/Math-Matrix/PMArrayTest.class.st diff --git a/src/Math-Matrix/PMArrayTest.class.st b/src/Math-Matrix/PMArrayTest.class.st new file mode 100644 index 00000000..283eb04e --- /dev/null +++ b/src/Math-Matrix/PMArrayTest.class.st @@ -0,0 +1,218 @@ +Class { + #name : #PMArrayTest, + #superclass : #TestCase, + #category : #'Math-Matrix' +} + +{ #category : #tests } +PMArrayTest >> testArray [ + + | t1 t2 | + t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: t1 array equals: #( 1 2 3 4 5 6 7 8 ). + + t2 := PMArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self + assert: t2 array + equals: #( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ) +] + +{ #category : #tests } +PMArrayTest >> testCreateScalarTensor [ + + | s | + s := PMArray newWith: 2. + self assert: (s get: #( )) equals: 2. + self should: [ s get: #( 1 1 ) ] raise: Error. + self assert: s rank equals: 0. + s set: #( ) value: 1. + self assert: (s get: #( )) equals: 1. + self assert: s shape equals: #( ). + self assert: s size equals: 1 +] + +{ #category : #tests } +PMArrayTest >> testFirst [ + + | a b | + a := PMArray fromNestedArray: (1 to: 6) asArray. + self assert: a first equals: #( 1). + b := a reshape: #( 3 2 ). + self assert: b first equals: #( 1 1 ) +] + +{ #category : #tests } +PMArrayTest >> testFlattenedIndexOf [ + + | t1 t2 | + t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: (t1 flattenedIndexOf: #( 1 2 )) equals: 2. + + t2 := PMArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self assert: (t2 flattenedIndexOf: #( 1 2 2 )) equals: 4 +] + +{ #category : #tests } +PMArrayTest >> testFromNestedArray [ + + | t1 t2 | + t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) + #( 5 6 7 8 ) ). + self assert: t1 class equals: PMArray. + + t2 := PMArray fromNestedArray: #( #( #( 1 1 ) #( 2 2 ) ) + #( #( 3 3 ) #( 4 4 ) ) + #( #( 4 4 ) #( 4 4 ) ) + #( #( 4 4 ) #( 4 4 ) ) ). + self assert: t2 class equals: PMArray. + +] + +{ #category : #tests } +PMArrayTest >> testGet [ + + | t1 t2 | + t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: (t1 get: #( 2 2 )) equals: 6. + + t2 := PMArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self assert: (t2 get: #( 3 2 1 )) equals: 11. + + self should:[t1 get: #( 4 4 )] raise:Error +] + +{ #category : #tests } +PMArrayTest >> testOuterProduct [ +|t1 t2| + t1 := PMArray fromNestedArray: #( #( 1 2 ) + #( 3 1 ) ). + t2 := PMArray fromNestedArray: #( #( 1 3 ) + #( 2 1 ) ). + self assert: (t1 outerProduct: t2) equals: (PMArray fromNestedArray:#( #( 1 3 2 1 ) + #( 2 6 4 2 ) + #( 3 9 6 3 ) + #(1 3 2 1))). + +t1 := PMArray fromNestedArray: #( #( 1 2) + #(3 4) + #( 1 0 )). + t2 := PMArray fromNestedArray: #( #( 0 5 2 ) + #( 6 7 3)). + self assert: (t1 outerProduct: t2) equals: (PMArray fromNestedArray:#( + #( 0 5 2 6 7 3) + #( 0 10 4 12 14 6) + #( 0 15 6 18 21 9) + #( 0 20 8 24 28 12) + #( 0 5 2 6 7 3) + #( 0 0 0 0 0 0 ) + )) +] + +{ #category : #tests } +PMArrayTest >> testRank [ + + | t1 t2 | + + t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: t1 rank equals: 2. + + t2 := PMArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self assert: t2 rank equals: 3 +] + +{ #category : #tests } +PMArrayTest >> testReshape [ + + | t t1 | + t := PMArray fromNestedArray: #( #( 0 1 ) #( 2 3 ) #( 4 5 ) ). + t1 := t reshape: #( 2 3 ). + + self assert: t shape equals: #( 3 2 ). + self assert: t1 shape equals: #( 2 3 ). + self assert: t1 array == t array equals: true +] + +{ #category : #tests } +PMArrayTest >> testSetValue [ + + | t1 t2 | + t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + t1 set: #( 2 2 ) value: 3. + self assert: (t1 get: #( 2 2 ) ) equals: 3. + + t2 := PMArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) + #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) + #( #( 13 14 ) #( 15 16 ) ) ). + t2 set: #( 2 2 1) value: 10. + self assert: (t2 get: #( 2 2 1 )) equals: 10 +] + +{ #category : #tests } +PMArrayTest >> testShape [ + + | t1 t2 | + t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) + #( 5 6 7 8 ) ). + self assert: t1 shape equals: #( 2 4 ). + + t2 := PMArray fromNestedArray: #( #( #( 1 1 ) #( 2 2 ) ) + #( #( 3 3 ) #( 4 4 ) ) + #( #( 4 4 ) #( 4 4 ) ) + #( #( 4 4 ) #( 4 4 ) ) ). + self assert: t2 shape equals: #( 4 2 2 ) +] + +{ #category : #tests } +PMArrayTest >> testSize [ + + | t1 t2 | + t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: t1 size equals: 8. + + t2 := PMArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self assert: t2 size equals: 16 +] + +{ #category : #tests } +PMArrayTest >> testStrides [ + + | a b | + a := PMArray fromNestedArray: (1 to: 24) asArray. + self assert: a strides equals: #( 1 ). + b := a reshape: #( 4 6 ). + self assert: b strides equals: #( 6 1 ). + b := a reshape: #( 6 4 ). + self assert: b strides equals: #( 4 1 ). + self assert: (b flattenedIndexOf: #( 4 2 )) equals: 14. + b := a reshape: #( 3 4 2 ). + self assert: b strides equals: #( 8 2 1 ). + self assert: (b flattenedIndexOf: #( 3 2 1)) equals: 19. + b := a reshape: #( 2 3 4 ). + self assert: b strides equals: #( 12 4 1 ). + self assert: (b flattenedIndexOf: #( 2 2 3 )) equals: 19 +] + +{ #category : #tests } +PMArrayTest >> testView [ + + | t t1 | + t := PMArray fromNestedArray: + #( #( 10 11 12 ) #( 13 14 15 ) #( 16 17 18 ) #( #( 20 21 22 ) + #( 23 24 25 ) #( 26 27 28 ) ) + #( #( 30 31 32 ) #( 33 34 35 ) #( 36 37 38 ) ) ). + t1 := t view. + self assert: t array == t1 array equals: true. + self assert: t shape equals: t1 shape. + self assert: t shape == t1 shape equals: false. + self assert: t strides equals: t1 strides. + self assert: t strides == t1 strides equals: false. + self assert: t first equals: t1 first. + self assert: t first == t1 first equals: false. + +] From ebc072125a99583bbce6dccebda1a196cfd4fbf4 Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Fri, 30 Jul 2021 07:14:42 +0100 Subject: [PATCH 17/21] Delete PMArray and MPArrayTest --- src/Math-Matrix/PMArray.class.st | 152 ------------------- src/Math-Matrix/PMArrayTest.class.st | 218 --------------------------- 2 files changed, 370 deletions(-) delete mode 100644 src/Math-Matrix/PMArray.class.st delete mode 100644 src/Math-Matrix/PMArrayTest.class.st diff --git a/src/Math-Matrix/PMArray.class.st b/src/Math-Matrix/PMArray.class.st deleted file mode 100644 index dec83e4e..00000000 --- a/src/Math-Matrix/PMArray.class.st +++ /dev/null @@ -1,152 +0,0 @@ -Class { - #name : #PMArray, - #superclass : #Object, - #instVars : [ - 'array', - 'shape', - 'first', - 'strides' - ], - #category : #'Math-Matrix' -} - -{ #category : #'instance creation' } -PMArray class >> fromNestedArray: anArray [ - - ^ self new array: anArray flattened withShape: (self shape:anArray) -] - -{ #category : #'instance creation' } -PMArray class >> newWith: anInteger [ - - ^ self new array: {anInteger} withShape: #( ) -] - -{ #category : #accessing } -PMArray class >> shape: anArray [ - -anArray isArray ifFalse:[^#()] -ifTrue:[ - ^ {anArray size}, (self shape: anArray first) - ] - -] - -{ #category : #comparing } -PMArray >> = anArray [ - - ^ array = anArray array & (first = anArray first) - & (strides = anArray strides) & (shape = anArray shape) -] - -{ #category : #accessing } -PMArray >> array [ -^array -] - -{ #category : #'as yet unclassified' } -PMArray >> array: aFlatArray withShape: aShape [ - - array := aFlatArray. - shape := aShape copy. - self updateFirst. - shape ifNotEmpty: [ self updateStrides] -] - -{ #category : #accessing } -PMArray >> first [ -^first -] - -{ #category : #'primitives - file' } -PMArray >> flattenedIndexOf: coords [ - - | position | - position := 1. - coords withIndexDo: [ :elt :i | - position := (elt - 1) * (strides at: i) + position ]. - ^ position -] - -{ #category : #'as yet unclassified' } -PMArray >> fromNestedArray: aFlatArray withShape: aShape [ - - array := aFlatArray. - shape := aShape copy. - self updateFirst. - shape ifNotEmpty: [ self updateStrides] -] - -{ #category : #public } -PMArray >> get: coords [ - - | position | - position := self flattenedIndexOf: coords. - ^ array at: position -] - -{ #category : #accessing } -PMArray >> rank [ - ^ shape size -] - -{ #category : #'as yet unclassified' } -PMArray >> reshape: aNewShape [ - - ^ self viewWithShape: aNewShape. - -] - -{ #category : #initialization } -PMArray >> set: coords value: aValue [ - -array at: (self flattenedIndexOf: coords) put: aValue -] - -{ #category : #accessing } -PMArray >> shape [ - - ^ shape -] - -{ #category : #accessing } -PMArray >> size [ - -^ shape inject: 1 into: [ :each :product | each * product]. - -] - -{ #category : #accessing } -PMArray >> strides [ -^strides -] - -{ #category : #'as yet unclassified' } -PMArray >> updateFirst [ - - first := Array new: shape size withAll: 1 -] - -{ #category : #'as yet unclassified' } -PMArray >> updateStrides [ - - strides := Array new: shape size. - strides at: shape size put: 1. - ((shape size -1) to: 1 by: -1) do: [ :i | - strides at: i put: ((strides at: i + 1) * (shape at: i+1))] -] - -{ #category : #'as yet unclassified' } -PMArray >> view [ - - "Share only the array" - - ^ self viewWithShape: shape -] - -{ #category : #'as yet unclassified' } -PMArray >> viewWithShape: aNewShape [ - - ^ PMArray new array: self array withShape: aNewShape - -] diff --git a/src/Math-Matrix/PMArrayTest.class.st b/src/Math-Matrix/PMArrayTest.class.st deleted file mode 100644 index 283eb04e..00000000 --- a/src/Math-Matrix/PMArrayTest.class.st +++ /dev/null @@ -1,218 +0,0 @@ -Class { - #name : #PMArrayTest, - #superclass : #TestCase, - #category : #'Math-Matrix' -} - -{ #category : #tests } -PMArrayTest >> testArray [ - - | t1 t2 | - t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: t1 array equals: #( 1 2 3 4 5 6 7 8 ). - - t2 := PMArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self - assert: t2 array - equals: #( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ) -] - -{ #category : #tests } -PMArrayTest >> testCreateScalarTensor [ - - | s | - s := PMArray newWith: 2. - self assert: (s get: #( )) equals: 2. - self should: [ s get: #( 1 1 ) ] raise: Error. - self assert: s rank equals: 0. - s set: #( ) value: 1. - self assert: (s get: #( )) equals: 1. - self assert: s shape equals: #( ). - self assert: s size equals: 1 -] - -{ #category : #tests } -PMArrayTest >> testFirst [ - - | a b | - a := PMArray fromNestedArray: (1 to: 6) asArray. - self assert: a first equals: #( 1). - b := a reshape: #( 3 2 ). - self assert: b first equals: #( 1 1 ) -] - -{ #category : #tests } -PMArrayTest >> testFlattenedIndexOf [ - - | t1 t2 | - t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: (t1 flattenedIndexOf: #( 1 2 )) equals: 2. - - t2 := PMArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self assert: (t2 flattenedIndexOf: #( 1 2 2 )) equals: 4 -] - -{ #category : #tests } -PMArrayTest >> testFromNestedArray [ - - | t1 t2 | - t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) - #( 5 6 7 8 ) ). - self assert: t1 class equals: PMArray. - - t2 := PMArray fromNestedArray: #( #( #( 1 1 ) #( 2 2 ) ) - #( #( 3 3 ) #( 4 4 ) ) - #( #( 4 4 ) #( 4 4 ) ) - #( #( 4 4 ) #( 4 4 ) ) ). - self assert: t2 class equals: PMArray. - -] - -{ #category : #tests } -PMArrayTest >> testGet [ - - | t1 t2 | - t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: (t1 get: #( 2 2 )) equals: 6. - - t2 := PMArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self assert: (t2 get: #( 3 2 1 )) equals: 11. - - self should:[t1 get: #( 4 4 )] raise:Error -] - -{ #category : #tests } -PMArrayTest >> testOuterProduct [ -|t1 t2| - t1 := PMArray fromNestedArray: #( #( 1 2 ) - #( 3 1 ) ). - t2 := PMArray fromNestedArray: #( #( 1 3 ) - #( 2 1 ) ). - self assert: (t1 outerProduct: t2) equals: (PMArray fromNestedArray:#( #( 1 3 2 1 ) - #( 2 6 4 2 ) - #( 3 9 6 3 ) - #(1 3 2 1))). - -t1 := PMArray fromNestedArray: #( #( 1 2) - #(3 4) - #( 1 0 )). - t2 := PMArray fromNestedArray: #( #( 0 5 2 ) - #( 6 7 3)). - self assert: (t1 outerProduct: t2) equals: (PMArray fromNestedArray:#( - #( 0 5 2 6 7 3) - #( 0 10 4 12 14 6) - #( 0 15 6 18 21 9) - #( 0 20 8 24 28 12) - #( 0 5 2 6 7 3) - #( 0 0 0 0 0 0 ) - )) -] - -{ #category : #tests } -PMArrayTest >> testRank [ - - | t1 t2 | - - t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: t1 rank equals: 2. - - t2 := PMArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self assert: t2 rank equals: 3 -] - -{ #category : #tests } -PMArrayTest >> testReshape [ - - | t t1 | - t := PMArray fromNestedArray: #( #( 0 1 ) #( 2 3 ) #( 4 5 ) ). - t1 := t reshape: #( 2 3 ). - - self assert: t shape equals: #( 3 2 ). - self assert: t1 shape equals: #( 2 3 ). - self assert: t1 array == t array equals: true -] - -{ #category : #tests } -PMArrayTest >> testSetValue [ - - | t1 t2 | - t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - t1 set: #( 2 2 ) value: 3. - self assert: (t1 get: #( 2 2 ) ) equals: 3. - - t2 := PMArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) - #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) - #( #( 13 14 ) #( 15 16 ) ) ). - t2 set: #( 2 2 1) value: 10. - self assert: (t2 get: #( 2 2 1 )) equals: 10 -] - -{ #category : #tests } -PMArrayTest >> testShape [ - - | t1 t2 | - t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) - #( 5 6 7 8 ) ). - self assert: t1 shape equals: #( 2 4 ). - - t2 := PMArray fromNestedArray: #( #( #( 1 1 ) #( 2 2 ) ) - #( #( 3 3 ) #( 4 4 ) ) - #( #( 4 4 ) #( 4 4 ) ) - #( #( 4 4 ) #( 4 4 ) ) ). - self assert: t2 shape equals: #( 4 2 2 ) -] - -{ #category : #tests } -PMArrayTest >> testSize [ - - | t1 t2 | - t1 := PMArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: t1 size equals: 8. - - t2 := PMArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self assert: t2 size equals: 16 -] - -{ #category : #tests } -PMArrayTest >> testStrides [ - - | a b | - a := PMArray fromNestedArray: (1 to: 24) asArray. - self assert: a strides equals: #( 1 ). - b := a reshape: #( 4 6 ). - self assert: b strides equals: #( 6 1 ). - b := a reshape: #( 6 4 ). - self assert: b strides equals: #( 4 1 ). - self assert: (b flattenedIndexOf: #( 4 2 )) equals: 14. - b := a reshape: #( 3 4 2 ). - self assert: b strides equals: #( 8 2 1 ). - self assert: (b flattenedIndexOf: #( 3 2 1)) equals: 19. - b := a reshape: #( 2 3 4 ). - self assert: b strides equals: #( 12 4 1 ). - self assert: (b flattenedIndexOf: #( 2 2 3 )) equals: 19 -] - -{ #category : #tests } -PMArrayTest >> testView [ - - | t t1 | - t := PMArray fromNestedArray: - #( #( 10 11 12 ) #( 13 14 15 ) #( 16 17 18 ) #( #( 20 21 22 ) - #( 23 24 25 ) #( 26 27 28 ) ) - #( #( 30 31 32 ) #( 33 34 35 ) #( 36 37 38 ) ) ). - t1 := t view. - self assert: t array == t1 array equals: true. - self assert: t shape equals: t1 shape. - self assert: t shape == t1 shape equals: false. - self assert: t strides equals: t1 strides. - self assert: t strides == t1 strides equals: false. - self assert: t first equals: t1 first. - self assert: t first == t1 first equals: false. - -] From 8a713dc845f57b450f50aaac6303875b50b66b66 Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Fri, 30 Jul 2021 07:15:56 +0100 Subject: [PATCH 18/21] Addition of the PMNDArray class replacing PMArray --- src/Math-Matrix/PMNDArray.class.st | 152 +++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 src/Math-Matrix/PMNDArray.class.st diff --git a/src/Math-Matrix/PMNDArray.class.st b/src/Math-Matrix/PMNDArray.class.st new file mode 100644 index 00000000..eef9f9aa --- /dev/null +++ b/src/Math-Matrix/PMNDArray.class.st @@ -0,0 +1,152 @@ +Class { + #name : #PMNDArray, + #superclass : #Object, + #instVars : [ + 'array', + 'shape', + 'first', + 'strides' + ], + #category : #'Math-Matrix' +} + +{ #category : #'instance creation' } +PMNDArray class >> fromNestedArray: anArray [ + + ^ self new array: anArray flattened withShape: (self shape:anArray) +] + +{ #category : #'instance creation' } +PMNDArray class >> newWith: anInteger [ + + ^ self new array: {anInteger} withShape: #( ) +] + +{ #category : #accessing } +PMNDArray class >> shape: anArray [ + +anArray isArray ifFalse:[^#()] +ifTrue:[ + ^ {anArray size}, (self shape: anArray first) + ] + +] + +{ #category : #comparing } +PMNDArray >> = anArray [ + + ^ array = anArray array & (first = anArray first) + & (strides = anArray strides) & (shape = anArray shape) +] + +{ #category : #accessing } +PMNDArray >> array [ +^array +] + +{ #category : #'as yet unclassified' } +PMNDArray >> array: aFlatArray withShape: aShape [ + + array := aFlatArray. + shape := aShape copy. + self updateFirst. + shape ifNotEmpty: [ self updateStrides] +] + +{ #category : #accessing } +PMNDArray >> first [ +^first +] + +{ #category : #'primitives - file' } +PMNDArray >> flattenedIndexOf: coords [ + + | position | + position := 1. + coords withIndexDo: [ :elt :i | + position := (elt - 1) * (strides at: i) + position ]. + ^ position +] + +{ #category : #'as yet unclassified' } +PMNDArray >> fromNestedArray: aFlatArray withShape: aShape [ + + array := aFlatArray. + shape := aShape copy. + self updateFirst. + shape ifNotEmpty: [ self updateStrides] +] + +{ #category : #public } +PMNDArray >> get: coords [ + + | position | + position := self flattenedIndexOf: coords. + ^ array at: position +] + +{ #category : #accessing } +PMNDArray >> rank [ + ^ shape size +] + +{ #category : #'as yet unclassified' } +PMNDArray >> reshape: aNewShape [ + + ^ self viewWithShape: aNewShape. + +] + +{ #category : #initialization } +PMNDArray >> set: coords value: aValue [ + +array at: (self flattenedIndexOf: coords) put: aValue +] + +{ #category : #accessing } +PMNDArray >> shape [ + + ^ shape +] + +{ #category : #accessing } +PMNDArray >> size [ + +^ shape inject: 1 into: [ :each :product | each * product]. + +] + +{ #category : #accessing } +PMNDArray >> strides [ +^strides +] + +{ #category : #'as yet unclassified' } +PMNDArray >> updateFirst [ + + first := Array new: shape size withAll: 1 +] + +{ #category : #'as yet unclassified' } +PMNDArray >> updateStrides [ + + strides := Array new: shape size. + strides at: shape size put: 1. + ((shape size -1) to: 1 by: -1) do: [ :i | + strides at: i put: ((strides at: i + 1) * (shape at: i+1))] +] + +{ #category : #'as yet unclassified' } +PMNDArray >> view [ + + "Share only the array" + + ^ self viewWithShape: shape +] + +{ #category : #'as yet unclassified' } +PMNDArray >> viewWithShape: aNewShape [ + + ^ PMNDArray new array: self array withShape: aNewShape + +] From edf3d8b97b3cd5f2c9edbb2bd7df1e07bc0573b3 Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Fri, 30 Jul 2021 07:16:57 +0100 Subject: [PATCH 19/21] Addition of the PMNDArrayTest class replacing PMArrayTest --- src/Math-Matrix/PMNDArrayTest.class.st | 191 +++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 src/Math-Matrix/PMNDArrayTest.class.st diff --git a/src/Math-Matrix/PMNDArrayTest.class.st b/src/Math-Matrix/PMNDArrayTest.class.st new file mode 100644 index 00000000..5414ec2a --- /dev/null +++ b/src/Math-Matrix/PMNDArrayTest.class.st @@ -0,0 +1,191 @@ +Class { + #name : #PMNDArrayTest, + #superclass : #TestCase, + #category : #'Math-Matrix' +} + +{ #category : #tests } +PMNDArrayTest >> testArray [ + + | t1 t2 | + t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: t1 array equals: #( 1 2 3 4 5 6 7 8 ). + + t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self + assert: t2 array + equals: #( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ) +] + +{ #category : #tests } +PMNDArrayTest >> testCreateScalarTensor [ + + | s | + s := PMNDArray newWith: 2. + self assert: (s get: #( )) equals: 2. + self should: [ s get: #( 1 1 ) ] raise: Error. + self assert: s rank equals: 0. + s set: #( ) value: 1. + self assert: (s get: #( )) equals: 1. + self assert: s shape equals: #( ). + self assert: s size equals: 1 +] + +{ #category : #tests } +PMNDArrayTest >> testFirst [ + + | a b | + a := PMNDArray fromNestedArray: (1 to: 6) asArray. + self assert: a first equals: #( 1). + b := a reshape: #( 3 2 ). + self assert: b first equals: #( 1 1 ) +] + +{ #category : #tests } +PMNDArrayTest >> testFlattenedIndexOf [ + + | t1 t2 | + t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: (t1 flattenedIndexOf: #( 1 2 )) equals: 2. + + t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self assert: (t2 flattenedIndexOf: #( 1 2 2 )) equals: 4 +] + +{ #category : #tests } +PMNDArrayTest >> testFromNestedArray [ + + | t1 t2 | + t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) + #( 5 6 7 8 ) ). + self assert: t1 class equals: PMNDArray. + + t2 := PMNDArray fromNestedArray: #( #( #( 1 1 ) #( 2 2 ) ) + #( #( 3 3 ) #( 4 4 ) ) + #( #( 4 4 ) #( 4 4 ) ) + #( #( 4 4 ) #( 4 4 ) ) ). + self assert: t2 class equals: PMNDArray. + +] + +{ #category : #tests } +PMNDArrayTest >> testGet [ + + | t1 t2 | + t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: (t1 get: #( 2 2 )) equals: 6. + + t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self assert: (t2 get: #( 3 2 1 )) equals: 11. + + self should:[t1 get: #( 4 4 )] raise:Error +] + +{ #category : #tests } +PMNDArrayTest >> testRank [ + + | t1 t2 | + + t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: t1 rank equals: 2. + + t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self assert: t2 rank equals: 3 +] + +{ #category : #tests } +PMNDArrayTest >> testReshape [ + + | t t1 | + t := PMNDArray fromNestedArray: #( #( 0 1 ) #( 2 3 ) #( 4 5 ) ). + t1 := t reshape: #( 2 3 ). + + self assert: t shape equals: #( 3 2 ). + self assert: t1 shape equals: #( 2 3 ). + self assert: t1 array == t array equals: true +] + +{ #category : #tests } +PMNDArrayTest >> testSetValue [ + + | t1 t2 | + t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + t1 set: #( 2 2 ) value: 3. + self assert: (t1 get: #( 2 2 ) ) equals: 3. + + t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) + #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) + #( #( 13 14 ) #( 15 16 ) ) ). + t2 set: #( 2 2 1) value: 10. + self assert: (t2 get: #( 2 2 1 )) equals: 10 +] + +{ #category : #tests } +PMNDArrayTest >> testShape [ + + | t1 t2 | + t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) + #( 5 6 7 8 ) ). + self assert: t1 shape equals: #( 2 4 ). + + t2 := PMNDArray fromNestedArray: #( #( #( 1 1 ) #( 2 2 ) ) + #( #( 3 3 ) #( 4 4 ) ) + #( #( 4 4 ) #( 4 4 ) ) + #( #( 4 4 ) #( 4 4 ) ) ). + self assert: t2 shape equals: #( 4 2 2 ) +] + +{ #category : #tests } +PMNDArrayTest >> testSize [ + + | t1 t2 | + t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: t1 size equals: 8. + + t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self assert: t2 size equals: 16 +] + +{ #category : #tests } +PMNDArrayTest >> testStrides [ + + | a b | + a := PMNDArray fromNestedArray: (1 to: 24) asArray. + self assert: a strides equals: #( 1 ). + b := a reshape: #( 4 6 ). + self assert: b strides equals: #( 6 1 ). + b := a reshape: #( 6 4 ). + self assert: b strides equals: #( 4 1 ). + self assert: (b flattenedIndexOf: #( 4 2 )) equals: 14. + b := a reshape: #( 3 4 2 ). + self assert: b strides equals: #( 8 2 1 ). + self assert: (b flattenedIndexOf: #( 3 2 1)) equals: 19. + b := a reshape: #( 2 3 4 ). + self assert: b strides equals: #( 12 4 1 ). + self assert: (b flattenedIndexOf: #( 2 2 3 )) equals: 19 +] + +{ #category : #tests } +PMNDArrayTest >> testView [ + + | t t1 | + t := PMNDArray fromNestedArray: + #( #( 10 11 12 ) #( 13 14 15 ) #( 16 17 18 ) #( #( 20 21 22 ) + #( 23 24 25 ) #( 26 27 28 ) ) + #( #( 30 31 32 ) #( 33 34 35 ) #( 36 37 38 ) ) ). + t1 := t view. + self assert: t array == t1 array equals: true. + self assert: t shape equals: t1 shape. + self assert: t shape == t1 shape equals: false. + self assert: t strides equals: t1 strides. + self assert: t strides == t1 strides equals: false. + self assert: t first equals: t1 first. + self assert: t first == t1 first equals: false. + +] From a1c3525fd0b5c938d15a5c36518ab102fe72be74 Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Fri, 30 Jul 2021 11:27:00 +0100 Subject: [PATCH 20/21] Refactoring of PMNDarray class --- src/Math-Matrix/PMNDArray.class.st | 46 +++++++++++++++++------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/Math-Matrix/PMNDArray.class.st b/src/Math-Matrix/PMNDArray.class.st index eef9f9aa..c136785f 100644 --- a/src/Math-Matrix/PMNDArray.class.st +++ b/src/Math-Matrix/PMNDArray.class.st @@ -16,6 +16,12 @@ PMNDArray class >> fromNestedArray: anArray [ ^ self new array: anArray flattened withShape: (self shape:anArray) ] +{ #category : #'instance creation' } +PMNDArray class >> fromScalar: anInteger [ + + ^ self new array: {anInteger} withShape: #( ) +] + { #category : #'instance creation' } PMNDArray class >> newWith: anInteger [ @@ -39,11 +45,6 @@ PMNDArray >> = anArray [ & (strides = anArray strides) & (shape = anArray shape) ] -{ #category : #accessing } -PMNDArray >> array [ -^array -] - { #category : #'as yet unclassified' } PMNDArray >> array: aFlatArray withShape: aShape [ @@ -53,6 +54,25 @@ PMNDArray >> array: aFlatArray withShape: aShape [ shape ifNotEmpty: [ self updateStrides] ] +{ #category : #private } +PMNDArray >> asArray [ + ^array +] + +{ #category : #public } +PMNDArray >> at: coords [ + + | position | + position := self flattenedIndexOf: coords. + ^ array at: position +] + +{ #category : #initialization } +PMNDArray >> at: coords put: aValue [ + +array at: (self flattenedIndexOf: coords) put: aValue +] + { #category : #accessing } PMNDArray >> first [ ^first @@ -77,14 +97,6 @@ PMNDArray >> fromNestedArray: aFlatArray withShape: aShape [ shape ifNotEmpty: [ self updateStrides] ] -{ #category : #public } -PMNDArray >> get: coords [ - - | position | - position := self flattenedIndexOf: coords. - ^ array at: position -] - { #category : #accessing } PMNDArray >> rank [ ^ shape size @@ -97,12 +109,6 @@ PMNDArray >> reshape: aNewShape [ ] -{ #category : #initialization } -PMNDArray >> set: coords value: aValue [ - -array at: (self flattenedIndexOf: coords) put: aValue -] - { #category : #accessing } PMNDArray >> shape [ @@ -147,6 +153,6 @@ PMNDArray >> view [ { #category : #'as yet unclassified' } PMNDArray >> viewWithShape: aNewShape [ - ^ PMNDArray new array: self array withShape: aNewShape + ^ PMNDArray new array: self asArray withShape: aNewShape ] From 0a77c47e79675a90fb38f3fa4184cb6a8dfa3b6b Mon Sep 17 00:00:00 2001 From: YvanGuifo Date: Fri, 30 Jul 2021 11:28:12 +0100 Subject: [PATCH 21/21] Refactoring of PMNDArrayTest --- src/Math-Matrix/PMNDArrayTest.class.st | 84 +++++++++++++------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/src/Math-Matrix/PMNDArrayTest.class.st b/src/Math-Matrix/PMNDArrayTest.class.st index 5414ec2a..d6edeba7 100644 --- a/src/Math-Matrix/PMNDArrayTest.class.st +++ b/src/Math-Matrix/PMNDArrayTest.class.st @@ -9,25 +9,55 @@ PMNDArrayTest >> testArray [ | t1 t2 | t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: t1 array equals: #( 1 2 3 4 5 6 7 8 ). + self assert: t1 asArray equals: #( 1 2 3 4 5 6 7 8 ). t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). self - assert: t2 array + assert: t2 asArray equals: #( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ) ] { #category : #tests } -PMNDArrayTest >> testCreateScalarTensor [ +PMNDArrayTest >> testAt [ + + | t1 t2 | + t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + self assert: (t1 at: #( 2 2 )) equals: 6. + + t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). + self assert: (t2 at: #( 3 2 1 )) equals: 11. + + self should:[t1 at: #( 4 4 )] raise:Error +] + +{ #category : #tests } +PMNDArrayTest >> testAtPut [ + + | t1 t2 | + t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). + t1 at: #( 2 2 ) put: 3. + self assert: (t1 at: #( 2 2 ) ) equals: 3. + + t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) + #( #( 5 6 ) #( 7 8 ) ) + #( #( 9 10 ) #( 11 12 ) ) + #( #( 13 14 ) #( 15 16 ) ) ). + t2 at: #( 2 2 1) put: 10. + self assert: (t2 at: #( 2 2 1 )) equals: 10 +] + +{ #category : #tests } +PMNDArrayTest >> testCreateScalarNDArray [ | s | - s := PMNDArray newWith: 2. - self assert: (s get: #( )) equals: 2. - self should: [ s get: #( 1 1 ) ] raise: Error. + s := PMNDArray fromScalar: 2. + self assert: (s at: #( )) equals: 2. + self should: [ s at: #( 1 1 ) ] raise: Error. self assert: s rank equals: 0. - s set: #( ) value: 1. - self assert: (s get: #( )) equals: 1. + s at: #( ) put: 1. + self assert: (s at: #( )) equals: 1. self assert: s shape equals: #( ). self assert: s size equals: 1 ] @@ -46,8 +76,8 @@ PMNDArrayTest >> testFirst [ PMNDArrayTest >> testFlattenedIndexOf [ | t1 t2 | - t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: (t1 flattenedIndexOf: #( 1 2 )) equals: 2. + t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8) #( 9 10 11 12)). + self assert: (t1 flattenedIndexOf: #( 3 2 )) equals: 10. t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). @@ -70,20 +100,6 @@ PMNDArrayTest >> testFromNestedArray [ ] -{ #category : #tests } -PMNDArrayTest >> testGet [ - - | t1 t2 | - t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - self assert: (t1 get: #( 2 2 )) equals: 6. - - t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) #( #( 13 14 ) #( 15 16 ) ) ). - self assert: (t2 get: #( 3 2 1 )) equals: 11. - - self should:[t1 get: #( 4 4 )] raise:Error -] - { #category : #tests } PMNDArrayTest >> testRank [ @@ -106,23 +122,7 @@ PMNDArrayTest >> testReshape [ self assert: t shape equals: #( 3 2 ). self assert: t1 shape equals: #( 2 3 ). - self assert: t1 array == t array equals: true -] - -{ #category : #tests } -PMNDArrayTest >> testSetValue [ - - | t1 t2 | - t1 := PMNDArray fromNestedArray: #( #( 1 2 3 4 ) #( 5 6 7 8 ) ). - t1 set: #( 2 2 ) value: 3. - self assert: (t1 get: #( 2 2 ) ) equals: 3. - - t2 := PMNDArray fromNestedArray: #( #( #( 1 2 ) #( 3 4 ) ) - #( #( 5 6 ) #( 7 8 ) ) - #( #( 9 10 ) #( 11 12 ) ) - #( #( 13 14 ) #( 15 16 ) ) ). - t2 set: #( 2 2 1) value: 10. - self assert: (t2 get: #( 2 2 1 )) equals: 10 + self assert: t1 asArray == t asArray equals: true ] { #category : #tests } @@ -180,7 +180,7 @@ PMNDArrayTest >> testView [ #( 23 24 25 ) #( 26 27 28 ) ) #( #( 30 31 32 ) #( 33 34 35 ) #( 36 37 38 ) ) ). t1 := t view. - self assert: t array == t1 array equals: true. + self assert: t asArray == t1 asArray equals: true. self assert: t shape equals: t1 shape. self assert: t shape == t1 shape equals: false. self assert: t strides equals: t1 strides.