ab5755d2109f61138515e7bed48720ea42f61f56
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 private 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 # Create a matrix from an `Array[Float]` composed of rows after rows
66 # Require: `width > 0 and height > 0`
67 # Require: `array.length >= width*height`
70 # var matrix = new Matrix.from_array(2, 2, [1.0, 2.0,
72 # assert matrix.to_s == """
76 init from_array
(width
, height
: Int, array
: SequenceRead[Float])
80 assert array
.length
>= width
*height
84 for i
in height
.times
do
85 for j
in width
.times
do
86 self[j
, i
] = array
[i
+ j
*width
]
91 # Create an identity matrix
93 # Require: `size >= 0`
96 # var i = new Matrix.identity(3)
97 # assert i.to_s == """
102 new identity
(size
: Int)
106 var matrix
= new Matrix(size
, size
)
107 for i
in size
.times
do
108 for j
in size
.times
do
109 matrix
[j
, i
] = if i
== j
then 1.0 else 0.0
115 # Create a new clone of this matrix
116 redef fun clone
do return new Matrix.from_array
(width
, height
, items
.clone
)
118 # Get the value at column `y` and row `x`
120 # Require: `x >= 0 and x <= width and y >= 0 and y <= height`
123 # var matrix = new Matrix.from([[0.0, 0.1],
126 # assert matrix[0, 0] == 0.0
127 # assert matrix[0, 1] == 0.1
128 # assert matrix[1, 0] == 1.0
129 # assert matrix[1, 1] == 1.1
131 fun [](y
, x
: Int): Float
133 assert x
>= 0 and x
< width
134 assert y
>= 0 and y
< height
136 return items
[x
+ y
*width
]
139 # Set the `value` at row `y` and column `x`
141 # Require: `x >= 0 and x <= width and y >= 0 and y <= height`
144 # var matrix = new Matrix.identity(2)
151 # assert matrix.to_s == """
155 fun []=(y
, x
: Int, value
: Float)
157 assert x
>= 0 and x
< width
158 assert y
>= 0 and y
< height
160 items
[x
+ y
*width
] = value
165 # Require: `self.width == other.height`
168 # var m = new Matrix.from([[3.0, 4.0],
170 # var i = new Matrix.identity(2)
173 # assert (m * m).to_s == """
177 # var a = new Matrix.from([[1.0, 2.0, 3.0],
179 # var b = new Matrix.from([[1.0],
183 # assert c.to_s == """
187 fun *(other
: Matrix): Matrix
189 assert self.width
== other
.height
191 var out
= new Matrix(other
.width
, self.height
)
192 for j
in self.height
.times
do
193 for i
in other
.width
.times
do
194 var sum
= items
.first
.zero
195 for k
in self.width
.times
do sum
+= self[j
, k
] * other
[k
, i
]
202 # Iterate over the values in this matrix
203 fun iterator
: MapIterator[MatrixCoordinate, Float] do return new MatrixIndexIterator(self)
207 var lines
= new Array[String]
208 for y
in height
.times
do
209 lines
.add items
.subarray
(y
*width
, width
).join
(" ")
211 return lines
.join
("\n")
214 redef fun ==(other
) do return other
isa Matrix and other
.items
== self.items
215 redef fun hash
do return items
.hash
218 private class MatrixIndexIterator
219 super MapIterator[MatrixCoordinate, Float]
223 redef var key
= new MatrixCoordinate(0, 0)
225 redef fun is_ok
do return key
.y
< matrix
.height
230 return matrix
[key
.y
, key
.x
]
237 if key
.x
== matrix
.width
- 1 then
246 # Position key when iterating over the values of a matrix
247 class MatrixCoordinate
248 # Index of the current column
251 # Index of the current row
254 redef fun to_s
do return "({x},{y})"