ruby-gsl-ng 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,22 @@
1
+ module GSLng
2
+ backend.instance_eval do
3
+ # memory handling
4
+ attach_function :gsl_rng_alloc, [ :pointer ], :pointer
5
+ attach_function :gsl_rng_free, [ :pointer ], :void
6
+
7
+ # RNG types
8
+ algorithms = %w(mt19937 ranlxs0 ranlxs1 ranlxs2 ranlxd1 ranlxd2 ranlux ranlux389 cmrg mrg taus taus2 gfsr4)
9
+ algorithms.each do |alg|
10
+ attach_variable :"gsl_rng_#{alg}", :pointer
11
+ end
12
+
13
+ # Uniform
14
+ attach_function :gsl_ran_flat, [ :pointer, :double, :double ], :double
15
+ attach_function :gsl_ran_flat_pdf, [ :double, :double, :double ], :double
16
+
17
+ # Gaussian
18
+ attach_function :gsl_ran_gaussian, [ :pointer, :double ], :double
19
+ attach_function :gsl_ran_gaussian_ziggurat, [ :pointer, :double ], :double
20
+ attach_function :gsl_ran_gaussian_ratio_method, [ :pointer, :double ], :double
21
+ end
22
+ end
@@ -0,0 +1,7 @@
1
+ module GSLng
2
+ backend.instance_eval do
3
+ # trigonometric
4
+ attach_function :gsl_sf_angle_restrict_symm, [ :double ], :double
5
+ attach_function :gsl_sf_angle_restrict_pos, [ :double ], :double
6
+ end
7
+ end
@@ -1,75 +1,63 @@
1
- module GSLng
2
- backend.instance_eval do
3
- # memory handling
4
- attach_function :gsl_vector_alloc, [ :size_t ], :pointer
5
- attach_function :gsl_vector_calloc, [ :size_t ], :pointer
6
- attach_function :gsl_vector_free, [ :pointer ], :void
7
-
8
- # initializing
9
- attach_function :gsl_vector_set_all, [ :pointer, :double ], :void
10
- attach_function :gsl_vector_set_zero, [ :pointer ], :void
11
- attach_function :gsl_vector_set_basis, [ :pointer, :size_t ], :int
12
-
13
- # operations
14
- attach_function :gsl_vector_add, [ :pointer, :pointer ], :int
15
- attach_function :gsl_vector_sub, [ :pointer, :pointer ], :int
16
- attach_function :gsl_vector_mul, [ :pointer, :pointer ], :int
17
- attach_function :gsl_vector_div, [ :pointer, :pointer ], :int
18
- attach_function :gsl_vector_scale, [ :pointer, :double ], :int
19
- attach_function :gsl_vector_add_constant, [ :pointer, :double ], :int
20
-
21
- # element access
22
- attach_function :gsl_vector_get, [ :pointer, :size_t ], :double
23
- attach_function :gsl_vector_set, [ :pointer, :size_t, :double ], :void
24
-
25
- # properties
26
- attach_function :gsl_vector_isnull, [ :pointer ], :int
27
- attach_function :gsl_vector_ispos, [ :pointer ], :int
28
- attach_function :gsl_vector_isneg, [ :pointer ], :int
29
- attach_function :gsl_vector_isnonneg, [ :pointer ], :int
30
-
31
- # max and min
32
- attach_function :gsl_vector_max, [ :pointer ], :double
33
- attach_function :gsl_vector_min, [ :pointer ], :double
34
- attach_function :gsl_vector_minmax, [ :pointer, :buffer_out, :buffer_out ], :void
35
- attach_function :gsl_vector_max_index, [ :pointer ], :size_t
36
- attach_function :gsl_vector_min_index, [ :pointer ], :size_t
37
- attach_function :gsl_vector_minmax_index, [ :pointer, :buffer_out, :buffer_out ], :void
38
-
39
- # copying
40
- attach_function :gsl_vector_memcpy, [ :pointer, :pointer ], :int
41
-
42
- # exchanging elements
43
- attach_function :gsl_vector_swap_elements, [ :pointer, :size_t, :size_t ], :int
44
- attach_function :gsl_vector_reverse, [ :pointer ], :int
45
-
46
- # BLAS functions
47
- attach_function :gsl_blas_ddot, [ :pointer, :pointer, :buffer_out ], :int
48
- attach_function :gsl_blas_dnrm2, [ :pointer ], :double
49
- attach_function :gsl_blas_dasum, [ :pointer ], :double
50
- #attach_function :gsl_blas_idamax, [ :pointer ], clbas_index??
51
- #attach_function :gsl_blas_dcopy, use this instead of memcpy?
52
- attach_function :gsl_blas_daxpy, [ :double, :pointer, :pointer ], :int
53
- attach_function :gsl_blas_dscal, [ :double, :pointer ], :void
54
-
55
- # views
56
- attach_function :gsl_vector_subvector2, [ :pointer, :size_t, :size_t ], :pointer
57
- attach_function :gsl_vector_subvector_with_stride2, [ :pointer, :size_t, :size_t, :size_t ], :pointer
58
-
59
- # From local extension
60
- callback :gsl_vector_callback, [ :double ], :double
61
- attach_function :gsl_vector_map, [ :pointer, :gsl_vector_callback ], :void
62
-
63
- callback :gsl_vector_index_callback, [ :size_t ], :double
64
- attach_function :gsl_vector_map_index, [ :pointer, :gsl_vector_index_callback ], :void
65
-
66
- callback :gsl_vector_each_callback, [ :double ], :void
67
- attach_function :gsl_vector_each, [ :pointer, :gsl_vector_each_callback ], :void
68
-
69
- callback :gsl_vector_each_with_index_callback, [ :double, :size_t ], :void
70
- attach_function :gsl_vector_each_with_index, [ :pointer, :gsl_vector_each_with_index_callback ], :void
71
-
72
- # Sorting
73
- attach_function :gsl_sort_vector, [ :pointer ], :void
74
- end
75
- end
1
+ module GSLng
2
+ backend.instance_eval do
3
+ # memory handling
4
+ attach_function :gsl_vector_alloc, [ :size_t ], :pointer
5
+ attach_function :gsl_vector_calloc, [ :size_t ], :pointer
6
+ attach_function :gsl_vector_free, [ :pointer ], :void
7
+
8
+ # initializing
9
+ attach_function :gsl_vector_set_all, [ :pointer, :double ], :void
10
+ attach_function :gsl_vector_set_zero, [ :pointer ], :void
11
+ attach_function :gsl_vector_set_basis, [ :pointer, :size_t ], :int
12
+
13
+ # operations
14
+ attach_function :gsl_vector_add, [ :pointer, :pointer ], :int
15
+ attach_function :gsl_vector_sub, [ :pointer, :pointer ], :int
16
+ attach_function :gsl_vector_mul, [ :pointer, :pointer ], :int
17
+ attach_function :gsl_vector_div, [ :pointer, :pointer ], :int
18
+ attach_function :gsl_vector_scale, [ :pointer, :double ], :int
19
+ attach_function :gsl_vector_add_constant, [ :pointer, :double ], :int
20
+
21
+ # element access
22
+ attach_function :gsl_vector_get, [ :pointer, :size_t ], :double
23
+ attach_function :gsl_vector_set, [ :pointer, :size_t, :double ], :void
24
+
25
+ # properties
26
+ attach_function :gsl_vector_isnull, [ :pointer ], :int
27
+ attach_function :gsl_vector_ispos, [ :pointer ], :int
28
+ attach_function :gsl_vector_isneg, [ :pointer ], :int
29
+ attach_function :gsl_vector_isnonneg, [ :pointer ], :int
30
+
31
+ # max and min
32
+ attach_function :gsl_vector_max, [ :pointer ], :double
33
+ attach_function :gsl_vector_min, [ :pointer ], :double
34
+ attach_function :gsl_vector_minmax, [ :pointer, :buffer_out, :buffer_out ], :void
35
+ attach_function :gsl_vector_max_index, [ :pointer ], :size_t
36
+ attach_function :gsl_vector_min_index, [ :pointer ], :size_t
37
+ attach_function :gsl_vector_minmax_index, [ :pointer, :buffer_out, :buffer_out ], :void
38
+
39
+ # copying
40
+ attach_function :gsl_vector_memcpy, [ :pointer, :pointer ], :int
41
+
42
+ # exchanging elements
43
+ attach_function :gsl_vector_swap_elements, [ :pointer, :size_t, :size_t ], :int
44
+ attach_function :gsl_vector_reverse, [ :pointer ], :int
45
+
46
+ # BLAS functions
47
+ attach_function :gsl_blas_ddot, [ :pointer, :pointer, :buffer_out ], :int
48
+ attach_function :gsl_blas_dnrm2, [ :pointer ], :double
49
+ attach_function :gsl_blas_dasum, [ :pointer ], :double
50
+ #attach_function :gsl_blas_idamax, [ :pointer ], clbas_index??
51
+ #attach_function :gsl_blas_dcopy, use this instead of memcpy?
52
+ attach_function :gsl_blas_daxpy, [ :double, :pointer, :pointer ], :int
53
+ attach_function :gsl_blas_dscal, [ :double, :pointer ], :void
54
+
55
+ # Sorting
56
+ attach_function :gsl_sort_vector, [ :pointer ], :void
57
+
58
+ # From local extension
59
+ # views
60
+ attach_function :gsl_vector_subvector2, [ :pointer, :size_t, :size_t ], :pointer
61
+ attach_function :gsl_vector_subvector_with_stride2, [ :pointer, :size_t, :size_t, :size_t ], :pointer
62
+ end
63
+ end
@@ -1,5 +1,9 @@
1
1
  module GSLng
2
- def GSLng.set_finalizer(obj, func, ptr) # @private
3
- ObjectSpace.define_finalizer(obj, lambda {|id| GSLng.backend.send(func, ptr)})
2
+ def GSLng.define_finalizer(obj, func, ptr) # @private
3
+ ObjectSpace.define_finalizer(obj, self.get_finalizer(func, ptr))
4
+ end
5
+
6
+ def GSLng.get_finalizer(func, ptr) # @private
7
+ lambda {|id| GSLng.backend.send(func, ptr)}
4
8
  end
5
9
  end
data/lib/gslng/matrix.rb CHANGED
@@ -2,75 +2,82 @@ module GSLng
2
2
  # A fixed-size MxN matrix.
3
3
  #
4
4
  # =Notes
5
- # See Vector notes. Everything applies with the following differences/additions:
6
- # * The * operator performs actual matrix-matrix and matrix-vector products. To perform element-by-element
7
- # multiplication use the ^ operator (or multiply method) instead. The rest of the operators work element-by-element.
8
- # * Operators can handle matrix-matrix, matrix-vector and matrix-scalar (also in reversed order). See #coerce.
9
- # * The [] and []= operators can handle a "wildcard" value for any dimension, just like MATLAB's colon (:).
5
+ # See Vector notes. Everything applies with the following *differences/additions*:
6
+ # * The {#*} operator performs actual matrix-matrix and matrix-vector products. To perform element-by-element
7
+ # multiplication use the {#^} operator (or {#multiply} method) instead. The rest of the operators work element-by-element.
8
+ # * Operators can handle matrix-matrix, matrix-vector and matrix-scalar (also in reversed order). See {#coerce}.
9
+ # * The {#[]} and {#[]=} operators can handle a "wildcard" value for any dimension, just like MATLAB's colon (:).
10
10
  class Matrix
11
- attr_reader :m, :n, :ptr
11
+ attr_reader :m, :n
12
+ attr_reader :ptr # @private
12
13
 
13
- alias_method :height, :m
14
- alias_method :width, :n
15
- alias_method :rows, :m
16
- alias_method :columns, :n
14
+ alias_method :height, :m
15
+ alias_method :width, :n
16
+ alias_method :rows, :m
17
+ alias_method :columns, :n
17
18
 
18
- # Returns [ #rows, #columns ]
19
- def size; [ @m, @n ] end
19
+ # Shorthand for [{#rows},{#columns}]
20
+ def size; [ @m, @n ] end
20
21
 
21
22
  #--------------------- constructors -------------------------#
22
23
 
23
- # Create a Matrix of m-by-n (rows and columns). If zero is true, the Matrix is initialized with zeros.
24
+ # Create a Matrix of m-by-n (rows and columns). If zero is true, the Matrix is initialized with zeros.
24
25
  # Otherwise, the Matrix will contain garbage.
25
- # You can optionally pass a block, in which case #map_index! will be called with it (i.e.: it works like Array.new).
26
+ # You can optionally pass a block, in which case {#map_index!} will be called with it (i.e.: it works like Array.new).
26
27
  def initialize(m, n, zero = false)
27
28
  @ptr = (zero ? GSLng.backend::gsl_matrix_calloc(m, n) : GSLng.backend::gsl_matrix_alloc(m, n))
28
- GSLng.set_finalizer(self, :gsl_matrix_free, @ptr)
29
+ GSLng.define_finalizer(self, :gsl_matrix_free, @ptr)
29
30
 
30
31
  @m,@n = m,n
31
- if (block_given?) then self.map_index!(Proc.new) end
32
+ if (block_given?) then self.map_index!(Proc.new) end
32
33
  end
33
34
 
34
35
  def initialize_copy(other) # @private
35
36
  ObjectSpace.undefine_finalizer(self) # TODO: ruby bug?
36
37
  @ptr = GSLng.backend::gsl_matrix_alloc(other.m, other.n)
37
- GSLng.set_finalizer(self, :gsl_matrix_free, @ptr)
38
+ GSLng.define_finalizer(self, :gsl_matrix_free, @ptr)
38
39
 
39
40
  @m,@n = other.size
40
41
  GSLng.backend::gsl_matrix_memcpy(@ptr, other.ptr)
41
42
  end
42
43
 
43
- # Same as Matrix.new(m, n, true)
44
- def Matrix.zero(m, n); Matrix.new(m, n, true) end
45
-
46
- # Create a matrix from an Array
47
- # If array is unidimensional, a row Matrix is created. If it is multidimensional, each sub-array
48
- # corresponds to a row of the resulting Matrix. Also, _array_ can be an Array of Ranges, in which case
49
- # each Range will correspond to a row.
50
- def Matrix.from_array(array)
51
- if (array.empty?) then raise "Can't create empty matrix" end
52
-
53
- if (Numeric === array[0]) then
54
- Matrix.new(1, array.size) {|i,j| array[j]}
44
+ # Same as Matrix.new(m, n, true)
45
+ def Matrix.zero(m, n); Matrix.new(m, n, true) end
46
+
47
+ # Create a matrix from an Array
48
+ # @see Matrix::[]
49
+ def Matrix.from_array(array)
50
+ if (array.empty?) then raise "Can't create empty matrix" end
51
+
52
+ if (Numeric === array[0])
53
+ m = Matrix.new(1, array.size)
54
+ GSLng.backend.gsl_matrix_from_array(m.ptr.to_i, [ array ])
55
+ return m
56
+ elsif (Array === array[0])
57
+ m = Matrix.new(array.size, array[0].size)
58
+ GSLng.backend.gsl_matrix_from_array(m.ptr.to_i, array)
59
+ return m
55
60
  else
56
61
  Matrix.new(array.size, array[0].to_a.size) {|i,j| array[i].to_a[j]}
57
62
  end
58
- end
63
+ end
59
64
 
60
- # Create a Matrix from an Array of Arrays/Ranges (see #from_array). For example:
61
- # Matrix[[1,2],[3,4]]
62
- # Matrix[1,2,3]
63
- # Matrix[[1..2],[5..10]]
64
- def Matrix.[](*args)
65
+ # Create a Matrix from an Array/Array of Arrays/Range
66
+ # @example
67
+ # Matrix[[1,2],[3,4]] => [1.0 2.0; 3.0 4.0]:Matrix
68
+ # Matrix[1,2,3] => [1.0 2.0 3.0]:Matrix
69
+ # Matrix[[1..3],[5..7]] => [1.0 2.0 3.0; 5.0 6.0 7.0]:Matrix
70
+ # @see Matrix::from_array
71
+ def Matrix.[](*args)
65
72
  Matrix.from_array(args)
66
- end
73
+ end
67
74
 
68
75
  # Generates a Matrix of m by n, of random numbers between 0 and 1.
69
- # NOTE: This simply uses Kernel::rand
76
+ # NOTE: This simply uses {Kernel::rand}
70
77
  def Matrix.random(m, n)
71
- Matrix.new(m, n).map!{|x| Kernel::rand}
78
+ Matrix.new(m, n).map!{|x| Kernel::rand}
72
79
  end
73
- class << self; alias_method :rand, :random end
80
+ class << self; alias_method :rand, :random end
74
81
 
75
82
  #--------------------- setting values -------------------------#
76
83
 
@@ -87,139 +94,159 @@ module GSLng
87
94
 
88
95
  #--------------------- set/get -------------------------#
89
96
 
90
- # Access the element (i,j), which means (row,column). *NOTE*: throws exception if out-of-bounds.
91
- # If either i or j are :* or :all, it serves as a wildcard for that dimension, returning all rows or columns,
92
- # respectively.
97
+ # Access the element (i,j), which means (row,column).
98
+ # Symbols :* or :all can be used as wildcards for both dimensions.
99
+ # @example If +m = Matrix[[1,2],[3,4]]+
100
+ # m[0,0] => 1.0
101
+ # m[0,:*] => [1.0, 2.0]:Matrix
102
+ # m[:*,0] => [1.0, 3.0]:Matrix
103
+ # m[:*,:*] => [1.0, 2.0; 3.0, 4.0]:Matrix
104
+ # @raise [RuntimeError] if out-of-bounds
105
+ # @return [Numeric,Matrix] the element/sub-matrix
93
106
  def [](i, j = :*)
94
- if (Symbol === i && Symbol === j) then return self
95
- elsif (Symbol === i)
96
- col = Vector.new(@m)
97
- GSLng.backend::gsl_matrix_get_col(col.ptr, @ptr, j)
98
- return col
99
- elsif (Symbol === j)
100
- row = Vector.new(@n)
101
- GSLng.backend::gsl_matrix_get_row(row.ptr, @ptr, i)
102
- return row
103
- else
104
- GSLng.backend::gsl_matrix_get(@ptr, i, j)
105
- end
106
- end
107
-
108
- # Set the element (i,j), which means (row,column). *NOTE*: throws exception if out-of-bounds.
109
- # Same indexing options as #[].
110
- # _value_ can be a single Numeric, a Vector or a Matrix, depending on the indexing.
107
+ if (Symbol === i && Symbol === j) then return self
108
+ elsif (Symbol === i)
109
+ col = Vector.new(@m)
110
+ GSLng.backend::gsl_matrix_get_col(col.ptr, @ptr, j)
111
+ return col.to_matrix
112
+ elsif (Symbol === j)
113
+ row = Vector.new(@n)
114
+ GSLng.backend::gsl_matrix_get_row(row.ptr, @ptr, i)
115
+ return row.to_matrix
116
+ else
117
+ GSLng.backend::gsl_matrix_get(@ptr, i, j)
118
+ end
119
+ end
120
+
121
+ # Set the element (i,j), which means (row,column).
122
+ # @param [Numeric,Vector,Matrix] value depends on indexing
123
+ # @raise [RuntimeError] if out-of-bounds
124
+ # @see #[]
111
125
  def []=(i, j, value)
112
- if (Symbol === i && Symbol === j) then
113
- if (Numeric === value) then self.fill!(value)
126
+ if (Symbol === i && Symbol === j) then
127
+ if (Numeric === value) then self.fill!(value)
114
128
  else
115
129
  x,y = self.coerce(value)
116
130
  GSLng.backend::gsl_matrix_memcpy(@ptr, x.ptr)
117
131
  end
118
- elsif (Symbol === i)
119
- col = Vector.new(@m)
132
+ elsif (Symbol === i)
133
+ col = Vector.new(@m)
120
134
  x,y = col.coerce(value)
121
- GSLng.backend::gsl_matrix_set_col(@ptr, j, x.ptr)
122
- return col
123
- elsif (Symbol === j)
124
- row = Vector.new(@n)
135
+ GSLng.backend::gsl_matrix_set_col(@ptr, j, x.ptr)
136
+ return col
137
+ elsif (Symbol === j)
138
+ row = Vector.new(@n)
125
139
  x,y = row.coerce(value)
126
- GSLng.backend::gsl_matrix_set_row(@ptr, i, x.ptr)
127
- return row
128
- else
129
- GSLng.backend::gsl_matrix_set(@ptr, i, j, value)
130
- end
140
+ GSLng.backend::gsl_matrix_set_row(@ptr, i, x.ptr)
141
+ return row
142
+ else
143
+ GSLng.backend::gsl_matrix_set(@ptr, i, j, value)
144
+ end
131
145
 
132
- return self
133
- end
146
+ return self
147
+ end
134
148
 
135
149
  #--------------------- view -------------------------#
136
150
 
137
- # Create a Matrix::View from this Matrix.
138
- # If either _m_ or _n_ are nil, they're computed from _x_, _y_ and the Matrix's #size
151
+ # Create a {Matrix::View} from this Matrix.
152
+ # If either _m_ or _n_ are nil, they're computed from _x_, _y_ and the Matrix's {#size}
153
+ # @return [Matrix::View]
139
154
  def view(x = 0, y = 0, m = nil, n = nil)
140
155
  View.new(self, x, y, (m or @m - x), (n or @n - y))
141
156
  end
142
157
  alias_method :submatrix_view, :view
143
158
 
144
- # Shorthand for submatrix_view(..).to_matrix.
159
+ # Shorthand for #submatrix_view(..).to_matrix.
160
+ # @return [Matrix]
145
161
  def submatrix(*args); self.submatrix_view(*args).to_matrix end
146
162
 
147
- # Creates a Matrix::View for the i-th column
163
+ # Creates a {Matrix::View} for the i-th column
164
+ # @return [Matrix::View]
148
165
  def column_view(i, offset = 0, size = nil); self.view(offset, i, (size or (@m - offset)), 1) end
149
166
 
150
- # Analogous to #submatrix
167
+ # Analogous to {#submatrix}
168
+ # @return [Matrix]
151
169
  def column(*args); self.column_view(*args).to_matrix end
152
170
 
153
- # Creates a Matrix::View for the i-th row
171
+ # Creates a {Matrix::View} for the i-th row
172
+ # @return [Matrix::View]
154
173
  def row_view(i, offset = 0, size = nil); self.view(i, offset, 1, (size or (@n - offset))) end
155
174
 
156
- # Same as #row_view, but returns a Vector::View
175
+ # Analogous to {#submatrix}
176
+ # @return [Matrix]
177
+ def row(*args); self.row_view(*args).to_matrix end
178
+
179
+ # Same as {#row_view}, but returns a {Vector::View}
180
+ # @return [Vector::View]
157
181
  def row_vecview(i, offset = 0, size = nil)
158
182
  size = (@n - offset) if size.nil?
159
183
  ptr = GSLng.backend.gsl_matrix_row_view(self.ptr, i, offset, size)
160
184
  Vector::View.new(ptr, self, offset, size)
161
185
  end
162
186
 
163
- # Same as #column_view, but returns a Vector::View
187
+ # Same as {#column_view}, but returns a {Vector::View}
188
+ # @return [Vector::View]
164
189
  def column_vecview(i, offset = 0, size = nil)
165
190
  size = (@m - offset) if size.nil?
166
191
  ptr = GSLng.backend.gsl_matrix_column_view(self.ptr, i, offset, size)
167
192
  Vector::View.new(ptr, self, offset, size)
168
193
  end
169
194
 
170
- # Analogous to #submatrix
171
- def row(*args); self.row_view(*args).to_matrix end
172
-
195
+
173
196
  #--------------------- operators -------------------------#
174
197
 
175
198
  # Add other to self
199
+ # @return [Matrix] self
176
200
  def add!(other)
177
201
  case other
178
202
  when Numeric; GSLng.backend::gsl_matrix_add_constant(self.ptr, other.to_f)
179
203
  when Matrix; GSLng.backend::gsl_matrix_add(self.ptr, other.ptr)
180
204
  else
181
- x,y = other.coerce(self)
182
- x.add!(y)
183
- end
184
- return self
205
+ x,y = other.coerce(self)
206
+ x.add!(y)
207
+ end
208
+ return self
185
209
  end
186
210
 
187
211
  # Substract other from self
212
+ # @return [Matrix] self
188
213
  def substract!(other)
189
214
  case other
190
215
  when Numeric; GSLng.backend::gsl_matrix_add_constant(self.ptr, -other.to_f)
191
216
  when Matrix; GSLng.backend::gsl_matrix_sub(self.ptr, other.ptr)
192
217
  else
193
- x,y = other.coerce(self)
194
- x.substract!(y)
195
- end
196
- return self
218
+ x,y = other.coerce(self)
219
+ x.substract!(y)
220
+ end
221
+ return self
197
222
  end
198
223
  alias_method :sub!, :substract!
199
224
 
200
225
  # Multiply (element-by-element) other with self
226
+ # @return [Matrix] self
201
227
  def multiply!(other)
202
228
  case other
203
229
  when Numeric; GSLng.backend::gsl_matrix_scale(self.ptr, other.to_f)
204
230
  when Matrix; GSLng.backend::gsl_matrix_mul_elements(self.ptr, other.ptr)
205
231
  else
206
- x,y = other.coerce(self)
207
- x.multiply!(y)
208
- end
209
- return self
232
+ x,y = other.coerce(self)
233
+ x.multiply!(y)
234
+ end
235
+ return self
210
236
  end
211
237
  alias_method :mul!, :multiply!
212
238
 
213
239
  # Divide (element-by-element) self by other
240
+ # @return [Matrix] self
214
241
  def divide!(other)
215
242
  case other
216
243
  when Numeric; GSLng.backend::gsl_matrix_scale(self.ptr, 1.0 / other)
217
244
  when Matrix; GSLng.backend::gsl_matrix_div_elements(self.ptr, other.ptr)
218
245
  else
219
- x,y = other.coerce(self)
220
- x.divide!(y)
221
- end
222
- return self
246
+ x,y = other.coerce(self)
247
+ x.divide!(y)
248
+ end
249
+ return self
223
250
  end
224
251
  alias_method :div!, :divide!
225
252
 
@@ -237,8 +264,10 @@ module GSLng
237
264
  alias_method :multiply, :^
238
265
  alias_method :mul, :^
239
266
 
240
- # Matrix Product. self#n should equal other#m (or other#size, if a Vector).
241
- # TODO: some cases could be optimized when doing Matrix-Matrix, by using dgemv
267
+ # Matrix Product. self.n should equal other.m (or other.size, if a Vector).
268
+ # @example
269
+ # Matrix[[1,2],[2,3]] * 2 => [2.0 4.0; 4.0 6.0]:Matrix
270
+ # @todo some cases could be optimized when doing Matrix-Matrix, by using dgemv
242
271
  def *(other)
243
272
  case other
244
273
  when Numeric
@@ -265,7 +294,10 @@ module GSLng
265
294
  # Returns the transpose of self, in a new matrix
266
295
  def transpose; matrix = Matrix.new(@n, @m); GSLng.backend::gsl_matrix_transpose_memcpy(matrix.ptr, self.ptr); return matrix end
267
296
 
297
+ # Swap the i-th and j-th columnos
268
298
  def swap_columns(i, j); GSLng.backend::gsl_matrix_swap_columns(self.ptr, i, j); return self end
299
+
300
+ # Swap the i-th and j-th rows
269
301
  def swap_rows(i, j); GSLng.backend::gsl_matrix_swap_rows(self.ptr, i, j); return self end
270
302
 
271
303
  # Swap the i-th row with the j-th column. The Matrix must be square.
@@ -281,7 +313,7 @@ module GSLng
281
313
 
282
314
  #if all elements are strictly negative (<0)
283
315
  def negative?; GSLng.backend::gsl_matrix_isneg(@ptr) == 1 ? true : false end
284
-
316
+
285
317
  # if all elements are non-negative (>=0)
286
318
  def nonnegative?; GSLng.backend::gsl_matrix_isnonneg(@ptr) == 1 ? true : false end
287
319
 
@@ -296,7 +328,7 @@ module GSLng
296
328
  # Minimum element of the Matrix
297
329
  def min; GSLng.backend::gsl_matrix_min(self.ptr) end
298
330
 
299
- # Same as Array#minmax
331
+ # Same as {Array#minmax}
300
332
  def minmax
301
333
  min = FFI::Buffer.new(:double)
302
334
  max = FFI::Buffer.new(:double)
@@ -304,7 +336,7 @@ module GSLng
304
336
  return [min[0].get_float64(0),max[0].get_float64(0)]
305
337
  end
306
338
 
307
- # Same as #minmax, but returns the indices to the i-th and j-th min, and i-th and j-th max.
339
+ # Same as {#minmax}, but returns the indices to the i-th and j-th min, and i-th and j-th max.
308
340
  def minmax_index
309
341
  i_min = FFI::Buffer.new(:size_t)
310
342
  j_min = FFI::Buffer.new(:size_t)
@@ -312,10 +344,10 @@ module GSLng
312
344
  j_max = FFI::Buffer.new(:size_t)
313
345
  GSLng.backend::gsl_matrix_minmax_index(self.ptr, i_min, j_min, i_max, j_max)
314
346
  #return [min[0].get_size_t(0),max[0].get_size_t(0)]
315
- return [i_min[0].get_ulong(0),j_min[0].get_ulong(0),i_max[0].get_ulong(0),j_max[0].get_ulong(0)]
347
+ return [i_min[0].get_ulong(0),j_min[0].get_ulong(0),i_max[0].get_ulong(0),j_max[0].get_ulong(0)]
316
348
  end
317
349
 
318
- # Same as #min, but returns the indices to the i-th and j-th minimum elements
350
+ # Same as {#min}, but returns the indices to the i-th and j-th minimum elements
319
351
  def min_index
320
352
  i_min = FFI::Buffer.new(:size_t)
321
353
  j_min = FFI::Buffer.new(:size_t)
@@ -323,7 +355,7 @@ module GSLng
323
355
  return [i_min[0].get_ulong(0), j_min[0].get_ulong(0)]
324
356
  end
325
357
 
326
- # Same as #max, but returns the indices to the i-th and j-th maximum elements
358
+ # Same as {#max}, but returns the indices to the i-th and j-th maximum elements
327
359
  def max_index
328
360
  i_max = FFI::Buffer.new(:size_t)
329
361
  j_max = FFI::Buffer.new(:size_t)
@@ -334,54 +366,80 @@ module GSLng
334
366
  #--------------------- block handling -------------------------#
335
367
 
336
368
  # Yields the specified block for each element going row-by-row
337
- def each # :yields: elem
369
+ # @yield [elem]
370
+ def each
338
371
  @m.times {|i| @n.times {|j| yield(self[i,j]) } }
339
372
  end
340
373
 
341
374
  # Yields the specified block for each element going row-by-row
342
- def each_with_index # :yields: elem, i, j
375
+ # @yield [elem, i, j]
376
+ def each_with_index
343
377
  @m.times {|i| @n.times {|j| yield(self[i,j], i, j) } }
344
378
  end
345
379
 
346
- # Same as #each, but faster. The catch is that this method returns nothing.
347
- def fast_each(block = Proc.new) #:yield: elem
348
- GSLng.backend::gsl_matrix_each(self.ptr, block)
380
+ # Calls the block on each element of the matrix
381
+ # @yield [elem]
382
+ # @return [void]
383
+ def each(block = Proc.new)
384
+ GSLng.backend::gsl_matrix_each(self.ptr.to_i, &block)
349
385
  end
350
-
351
- # Yields the block for each row *view* (Matrix::View).
386
+
387
+ # @see #each
388
+ # @yield [elem,i,j]
389
+ def each_with_index(block = Proc.new)
390
+ GSLng.backend::gsl_matrix_each_with_index(self.ptr.to_i, &block)
391
+ end
392
+
393
+ # Yields the block for each row *view* ({Matrix::View}).
394
+ # @yield [view]
352
395
  def each_row; self.rows.times {|i| yield(row_view(i))} end
353
396
 
354
- # Same as #each_row, but yields Vector::View's
397
+ # Same as {#each_row}, but yields {Vector::View}'s
398
+ # @yield [vector_view]
355
399
  def each_vec_row; self.rows.times {|i| yield(row_vecview(i))} end
356
400
 
357
- # Same as #each_column, but yields Vector::View's
401
+ # Same as #each_column, but yields {Vector::View}'s
402
+ # @yield [vector_view]
358
403
  def each_vec_column; self.columns.times {|i| yield(column_vecview(i))} end
359
404
 
360
- # Yields the block for each column *view* (Matrix::View).
405
+ # Yields the block for each column *view* ({Matrix::View}).
406
+ # @yield [view]
361
407
  def each_column; self.columns.times {|i| yield(column_view(i))} end
362
408
 
363
- # Efficient map! implementation
364
- def map!(block = Proc.new); GSLng.backend::gsl_matrix_map(@ptr, block); return self end
409
+ # Efficient {#map!} implementation
410
+ # @yield [elem]
411
+ def map!(block = Proc.new); GSLng.backend::gsl_matrix_map!(@ptr.to_i, &block); return self end
412
+
413
+ # Alternate version of {#map!}, in this case the block receives the index (row, column) as a parameter.
414
+ # @yield [i,j]
415
+ def map_index!(block = Proc.new); GSLng.backend::gsl_matrix_map_index!(@ptr.to_i, &block); return self end
365
416
 
366
- # Alternate version of #map!, in this case the block receives the index as a parameter.
367
- def map_index!(block = Proc.new); GSLng.backend::gsl_matrix_map_index(@ptr, block); return self end
417
+ # Similar to {#map_index!}, in this case it receives both the element and the index to it
418
+ # @yield [elem,i,j]
419
+ def map_with_index!(block = Proc.new); GSLng.backend::gsl_matrix_map_with_index!(@ptr.to_i, &block); return self end
368
420
 
369
- # See #map!. Returns a Matrix.
370
- def map(block = Proc.new); self.dup.map!(block) end
421
+ # @see #map!
422
+ # @return [Matrix]
423
+ # @yield [elem]
424
+ def map(block = Proc.new); self.dup.map!(block) end
371
425
 
372
426
  #--------------------- conversions -------------------------#
373
427
 
374
- # Same as Array#join, for example:
428
+ # Same as {Array#join}
429
+ # @example
375
430
  # Matrix[[1,2],[2,3]].join => "1.0 2.0 2.0 3.0"
376
431
  def join(sep = $,)
377
- s = ''
378
- GSLng.backend::gsl_matrix_each(@ptr, lambda {|e| s += (s.empty?() ? e.to_s : "#{sep}#{e}")})
379
- return s
380
- end
432
+ s = ''
433
+ self.each do |e|
434
+ s += (s.empty?() ? e.to_s : "#{sep}#{e}")
435
+ end
436
+ return s
437
+ end
381
438
 
382
- # Converts the matrix to a String, separating each element with a space and each row with a ';' and a newline:
439
+ # Converts the matrix to a String, separating each element with a space and each row with a ';' and a newline.
440
+ # @example
383
441
  # Matrix[[1,2],[2,3]] => "[1.0 2.0;\n 2.0 3.0]"
384
- def to_s
442
+ def to_s
385
443
  s = '['
386
444
  @m.times do |i|
387
445
  s += ' ' unless i == 0
@@ -392,7 +450,14 @@ module GSLng
392
450
  end
393
451
 
394
452
  return s
395
- end
453
+ end
454
+
455
+ # Converts the matrix to an Array (of Arrays).
456
+ # @example
457
+ # Matrix[[1,2],[2,3]] => [[1.0,2.0],[2.0,3.0]]
458
+ def to_a
459
+ GSLng.backend.gsl_matrix_to_a(self.ptr.to_i)
460
+ end
396
461
 
397
462
  def inspect # @private
398
463
  "#{self}:Matrix"
@@ -400,7 +465,7 @@ module GSLng
400
465
 
401
466
  # Coerces _other_ to be of Matrix class.
402
467
  # If _other_ is a scalar (Numeric) a Matrix filled with _other_ values is created.
403
- # Vectors are coerced using Vector#to_matrix (which results in a row matrix).
468
+ # Vectors are coerced using {Vector#to_matrix} (which results in a row matrix).
404
469
  def coerce(other)
405
470
  case other
406
471
  when Matrix