1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Services for matrices of `Float` values
18 # A rectangular array of `Float`
20 # Require: `width > 0 and height > 0`
30 # Items of this matrix, rows by rows
31 var items
: Array[Float] is lazy
do
32 return new Array[Float].filled_with
(0.0, width
*height
)
35 # Create a matrix from nested sequences
37 # Require: all rows are of the same length
40 # var matrix = new Matrix.from([[1.0, 2.0],
42 # assert matrix.to_s == """
46 init from
(items
: SequenceRead[SequenceRead[Float]])
48 if items
.is_empty
then
53 init(items
.first
.length
, items
.length
)
55 for j
in height
.times
do assert items
[j
].length
== width
57 for j
in height
.times
do
58 for i
in width
.times
do
59 self[j
, i
] = items
[j
][i
]
64 # Get each row of this matrix in nested arrays
67 # var items = [[1.0, 2.0],
69 # var matrix = new Matrix.from(items)
70 # assert matrix.to_a == items
72 fun to_a
: Array[Array[Float]]
74 var a
= new Array[Array[Float]]
75 for j
in height
.times
do
76 var row
= new Array[Float]
77 for i
in width
.times
do
85 # Create a matrix from an `Array[Float]` composed of rows after rows
87 # Require: `width > 0 and height > 0`
88 # Require: `array.length >= width*height`
91 # var matrix = new Matrix.from_array(2, 2, [1.0, 2.0,
93 # assert matrix.to_s == """
97 init from_array
(width
, height
: Int, array
: SequenceRead[Float])
101 assert array
.length
>= width
*height
105 for i
in height
.times
do
106 for j
in width
.times
do
107 self[j
, i
] = array
[i
+ j
*width
]
112 # Create an identity matrix
114 # Require: `size >= 0`
117 # var i = new Matrix.identity(3)
118 # assert i.to_s == """
123 new identity
(size
: Int)
127 var matrix
= new Matrix(size
, size
)
128 for i
in size
.times
do
129 for j
in size
.times
do
130 matrix
[j
, i
] = if i
== j
then 1.0 else 0.0
136 # Create a new clone of this matrix
137 redef fun clone
do return new Matrix.from_array
(width
, height
, items
.clone
)
139 # Get the value at column `y` and row `x`
141 # Require: `x >= 0 and x <= width and y >= 0 and y <= height`
144 # var matrix = new Matrix.from([[0.0, 0.1],
147 # assert matrix[0, 0] == 0.0
148 # assert matrix[0, 1] == 0.1
149 # assert matrix[1, 0] == 1.0
150 # assert matrix[1, 1] == 1.1
152 fun [](y
, x
: Int): Float
154 assert x
>= 0 and x
< width
155 assert y
>= 0 and y
< height
157 return items
[x
+ y
*width
]
160 # Set the `value` at row `y` and column `x`
162 # Require: `x >= 0 and x <= width and y >= 0 and y <= height`
165 # var matrix = new Matrix.identity(2)
172 # assert matrix.to_s == """
176 fun []=(y
, x
: Int, value
: Float)
178 assert x
>= 0 and x
< width
179 assert y
>= 0 and y
< height
181 items
[x
+ y
*width
] = value
186 # Require: `self.width == other.height`
189 # var m = new Matrix.from([[3.0, 4.0],
191 # var i = new Matrix.identity(2)
194 # assert (m * m).to_s == """
198 # var a = new Matrix.from([[1.0, 2.0, 3.0],
200 # var b = new Matrix.from([[1.0],
204 # assert c.to_s == """
208 fun *(other
: Matrix): Matrix
210 assert self.width
== other
.height
212 var out
= new Matrix(other
.width
, self.height
)
213 for j
in self.height
.times
do
214 for i
in other
.width
.times
do
215 var sum
= items
.first
.zero
216 for k
in self.width
.times
do sum
+= self[j
, k
] * other
[k
, i
]
223 # Get the transpose of this matrix
226 # var matrix = new Matrix.from([[1.0, 2.0, 3.0],
228 # assert matrix.transposed.to_a == [[1.0, 4.0],
232 # var i = new Matrix.identity(3)
233 # assert i.transposed == i
235 fun transposed
: Matrix
237 var out
= new Matrix(height
, width
)
238 for k
, v
in self do out
[k
.x
, k
.y
] = v
242 # Iterate over the values in this matrix
243 fun iterator
: MapIterator[MatrixCoordinate, Float] do return new MatrixIndexIterator(self)
247 var lines
= new Array[String]
248 for y
in height
.times
do
249 lines
.add items
.subarray
(y
*width
, width
).join
(" ")
251 return lines
.join
("\n")
254 redef fun ==(other
) do return other
isa Matrix and other
.items
== self.items
255 redef fun hash
do return items
.hash
258 private class MatrixIndexIterator
259 super MapIterator[MatrixCoordinate, Float]
263 redef var key
= new MatrixCoordinate(0, 0)
265 redef fun is_ok
do return key
.y
< matrix
.height
270 return matrix
[key
.y
, key
.x
]
277 if key
.x
== matrix
.width
- 1 then
286 # Position key when iterating over the values of a matrix
287 class MatrixCoordinate
288 # Index of the current column
291 # Index of the current row
294 redef fun to_s
do return "({x},{y})"