X-Git-Url: http://nitlanguage.org diff --git a/lib/matrix/matrix.nit b/lib/matrix/matrix.nit index ab5755d..0c3acac 100644 --- a/lib/matrix/matrix.nit +++ b/lib/matrix/matrix.nit @@ -28,9 +28,7 @@ class Matrix var height: Int # Items of this matrix, rows by rows - private var items: Array[Float] is lazy do - return new Array[Float].filled_with(0.0, width*height) - end + private var items = new NativeDoubleArray(width*height) is lazy # Create a matrix from nested sequences # @@ -54,11 +52,32 @@ class Matrix for j in height.times do assert items[j].length == width + for j in [0..height[ do + for i in [0..width[ do + self[j, i] = items[j][i] + end + end + end + + # Get each row of this matrix in nested arrays + # + # ~~~ + # var items = [[1.0, 2.0], + # [3.0, 4.0]] + # var matrix = new Matrix.from(items) + # assert matrix.to_a == items + # ~~~ + fun to_a: Array[Array[Float]] + do + var a = new Array[Array[Float]] for j in height.times do + var row = new Array[Float] for i in width.times do - self[j, i] = items[j][i] + row.add self[j, i] end + a.add row end + return a end # Create a matrix from an `Array[Float]` composed of rows after rows @@ -104,8 +123,8 @@ class Matrix assert size >= 0 var matrix = new Matrix(size, size) - for i in size.times do - for j in size.times do + for i in [0..size[ do + for j in [0..size[ do matrix[j, i] = if i == j then 1.0 else 0.0 end end @@ -113,7 +132,12 @@ class Matrix end # Create a new clone of this matrix - redef fun clone do return new Matrix.from_array(width, height, items.clone) + redef fun clone + do + var c = new Matrix(width, height) + for i in [0..width*height[ do c.items[i] = items[i] + return c + end # Get the value at column `y` and row `x` # @@ -189,13 +213,26 @@ class Matrix assert self.width == other.height var out = new Matrix(other.width, self.height) - for j in self.height.times do - for i in other.width.times do - var sum = items.first.zero - for k in self.width.times do sum += self[j, k] * other[k, i] - out[j, i] = sum - end - end + out.items.mul(items, other.items, self.width, self.height, other.width) + return out + end + + # Get the transpose of this matrix + # + # ~~~ + # var matrix = new Matrix.from([[1.0, 2.0, 3.0], + # [4.0, 5.0, 6.0]]) + # assert matrix.transposed.to_a == [[1.0, 4.0], + # [2.0, 5.0], + # [3.0, 6.0]] + # + # var i = new Matrix.identity(3) + # assert i.transposed == i + # ~~~ + fun transposed: Matrix + do + var out = new Matrix(height, width) + for k, v in self do out[k.x, k.y] = v return out end @@ -204,15 +241,22 @@ class Matrix redef fun to_s do - var lines = new Array[String] - for y in height.times do - lines.add items.subarray(y*width, width).join(" ") + var s = new FlatBuffer + for y in [0..height[ do + for x in [0..width[ do + s.append items[y*width+x].to_s + if x < width-1 then s.add ' ' + end + if y < height-1 then s.add '\n' end - return lines.join("\n") + return s.to_s end - redef fun ==(other) do return other isa Matrix and other.items == self.items - redef fun hash do return items.hash + redef fun ==(other) do return other isa Matrix and + width == other.width and height == other.height and + items.equal_items(items, width*height) + + redef fun hash do return items.hash_items(width*height) end private class MatrixIndexIterator @@ -253,3 +297,46 @@ class MatrixCoordinate redef fun to_s do return "({x},{y})" end + +# Specialized native structure to store matrix items and avoid boxing cost +private extern class NativeDoubleArray `{ double* `} + + new(size: Int) do + var sizeof_double = 8 + var buf = new CString(sizeof_double*size) + return new NativeDoubleArray.in_buffer(buf) + end + + new in_buffer(buffer: CString) `{ return (double*)buffer; `} + + fun [](i: Int): Float `{ return self[i]; `} + + fun []=(i: Int, value: Float) `{ self[i] = value; `} + + fun equal_items(other: NativeDoubleArray, len: Int): Bool `{ + int i; + for (i = 0; i < len; i ++) + if (self[i] != other[i]) + return 0; + return 1; + `} + + fun hash_items(len: Int): Int `{ + // Adapted from `SequenceRead::hash` + long r = 17+len; + int i; + for (i = 0; i < len; i ++) + r = r * 3 / 2 + (long)(i*1024.0); + return r; + `} + + fun mul(a, b: NativeDoubleArray, a_width, a_height, b_width: Int) `{ + int i, j, k; + for (j = 0; j < a_height; j ++) + for (i = 0; i < b_width; i ++) { + float sum = 0.0; + for (k = 0; k < a_width; k ++) sum += a[j*a_width + k] * b[k*b_width + i]; + self[j*b_width + i] = sum; + } + `} +end