ruby-gsl-ng 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,16 +9,17 @@ module GSLng
9
9
  class View < Matrix
10
10
  attr_reader :owner # The Matrix owning the data this View uses
11
11
 
12
- # Create a MatrixView of the sub-matrix starting at (x,y), of size (m,n)
12
+ # Create a Matrix::View of the sub-matrix starting at (x,y), of size (m,n)
13
13
  def initialize(owner, x, y, m, n) # @private
14
14
  @owner = owner
15
15
  @m,@n = m,n
16
16
  @ptr = GSLng.backend::gsl_matrix_submatrix2(owner.ptr, x, y, m, n)
17
- GSLng.set_finalizer(self, :gsl_matrix_free, @ptr)
17
+ GSLng.define_finalizer(self, :gsl_matrix_free, @ptr)
18
18
  end
19
19
 
20
20
  # Returns a Matrix (*NOT* a View) copied from this view. In other words,
21
21
  # you'll get a Matrix which you can modify without modifying #owner elements.
22
+ # @return [Matrix]
22
23
  def dup
23
24
  matrix = Matrix.new(@m, @n)
24
25
  GSLng.backend::gsl_matrix_memcpy(matrix.ptr, @ptr)
@@ -0,0 +1,34 @@
1
+ module GSLng
2
+ class RNG
3
+ class Gaussian < RNG
4
+ attr_reader :ptr # @private
5
+
6
+ attr_reader :mu, :sigma
7
+
8
+ # Creates a new Gaussian distribution
9
+ # @param [Float] mu mean
10
+ # @param [Float] sigma standard deviation
11
+ # @param [Symbol] sample_method The method to use to sample numbers. Can be either :boxmuller, :ziggurat or :ratio_method
12
+ # @param generator_type (see GSLng::RNG#initialize)
13
+ # @see http://www.gnu.org/software/gsl/manual/html_node/The-Gaussian-Distribution.html
14
+ def initialize(mu = 0, sigma = 1, sample_method = :boxmuller, generator_type = nil)
15
+ super(generator_type)
16
+ @mu,@sigma = mu,sigma
17
+
18
+ case sample_method
19
+ when :boxmuller; @function = :gsl_ran_gaussian
20
+ when :ziggurat; @function = :gsl_ran_gaussian_ziggurat
21
+ when :ratio_method; @function = :gsl_ran_ratio_method
22
+ else raise "Unsupported method"
23
+ end
24
+ end
25
+
26
+ # Obtain a sample from this distribution
27
+ # @return [Float]
28
+ def sample
29
+ GSLng.backend.send(@function, self.ptr, @sigma) + @mu
30
+ end
31
+ alias_method :get, :sample
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,27 @@
1
+ module GSLng
2
+ # Random Number Generator class
3
+ # @abstract You should use any of the descendant classes which implement the {#sample} method.
4
+ class RNG
5
+ # Create a Generator of the given type
6
+ # @param [Symbol] generator_type the algorithm to use (without the +gsl_rng+ prefix). Default is :mt19937.
7
+ # @see http://www.gnu.org/software/gsl/manual/html_node/Random-number-generator-algorithms.html
8
+ def initialize(generator_type = nil)
9
+ @type = generator_type
10
+ if (@type.nil?) then @type = :mt19937 end # update comment above if changed
11
+
12
+ type = GSLng.backend.send(:"gsl_rng_#{@type}")
13
+ @ptr = GSLng.backend.gsl_rng_alloc(type)
14
+ GSLng.define_finalizer(self, :gsl_rng_free, @ptr)
15
+ end
16
+
17
+ def initialize_copy
18
+ ObjectSpace.undefine_finalizer(self)
19
+ type = GSLng.backend.send(:"gsl_rng_#{@type}")
20
+ @ptr = GSLng.backend.gsl_rng_alloc(type)
21
+ GSLng.define_finalizer(self, :gsl_rng_free, @ptr)
22
+ end
23
+ end
24
+ end
25
+
26
+ require 'gslng/rng/gaussian'
27
+ require 'gslng/rng/uniform'
@@ -0,0 +1,23 @@
1
+ module GSLng
2
+ class RNG
3
+ class Uniform < RNG
4
+ attr_reader :ptr # @private
5
+
6
+ # Creates a new Uniform distribution with values in [min,max)
7
+ # @param [Float] min
8
+ # @param [Float] max
9
+ # @param generator_type (see GSLng::RNG#initialize)
10
+ def initialize(min, max, generator_type = nil)
11
+ super(generator_type)
12
+ @min,@max = min,max
13
+ end
14
+
15
+ # Obtain a sample from this distribution
16
+ # @return [Float]
17
+ def sample
18
+ GSLng.backend.gsl_ran_flat(self.ptr, @min, @max)
19
+ end
20
+ alias_method :get, :sample
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ module GSLng
2
+ # A group of several different special functions.
3
+ #
4
+ # =Notes
5
+ # You can use this module simply by acessing its functions. Optionally, you can also extend the +Math+ standard module
6
+ # with these methods by doing:
7
+ # Math.extend(GSLng::Special)
8
+ #
9
+ module Special
10
+ extend self # allow this module to be used as such, and as a mixin
11
+
12
+ # Restrict the given angle to the interval (-pi,pi]
13
+ def angle_restrict_symm(theta)
14
+ GSLng.backend.gsl_sf_angle_restrict_symm(theta)
15
+ end
16
+
17
+ # Restrict the given angle to the interval (0,2pi]
18
+ def angle_restrict_pos(theta)
19
+ GSLng.backend.gsl_sf_angle_restrict_pos(theta)
20
+ end
21
+ end
22
+ end
data/lib/gslng/vector.rb CHANGED
@@ -2,31 +2,31 @@ module GSLng
2
2
  # A fixed-size n-dimensional vector.
3
3
  #
4
4
  # =Notes
5
- # * #each is implemented through calls to #[], which can be relatively slow (compared to direct C pointer access)
6
- # for big Vectors. There's a faster version (#fast_each) that can be used when there's not return value expected from the #each call.
7
- # * Since this class includes Enumerable, and Enumerable's methods call #each, certain methods are redefined (like #max and #min)
8
- # so they use #fast_each instead. Thus, any other Enumerable's method not defined here will be slower.
9
- # * Some functions (like #sum, #dot, and others) use BLAS functions (through GSLng's CBLAS interface).
10
- # * In contrary to Array, operators [] and []= will raise an exception when accessing out-of-bounds elements.
11
- # * Operator * multiplies two vectors element-by-element. To perform a dot product use the ^ operator instead (or the #dot method).
12
- # * Operands are coerced to vectors so you can do vector + scalar, etc. (see #coerce)
5
+ # * {#each}, {#map} and similar methods are implemented with C versions which should be fast.
6
+ # * {#map} returns a Vector, not an Array. Use {#map_array} for that.
7
+ # * While this class includes Enumerable, certain methods are redefined (like {#max} and {#min})
8
+ # so they use internal GSL methods.
9
+ # * Some functions (like {#sum}, {#dot}, and others) use BLAS functions (through GSLng's CBLAS interface).
10
+ # * In contrary to Array, operators {#[]} and {#[]=} will raise an exception when accessing out-of-bounds elements.
11
+ # * Operator {#*} multiplies two vectors element-by-element. To perform a dot product use the {#^} operator instead (or the {#dot} alias).
12
+ # * Operands are coerced to vectors so you can do vector + scalar, etc. (see {#coerce})
13
13
  #
14
14
  class Vector
15
15
  include Enumerable
16
-
17
- attr_reader :ptr # @private
18
- attr_reader :size # Vector size
16
+
17
+ attr_reader :size
18
+ attr_reader :ptr # @private
19
19
 
20
20
  #--------------------- constructors -------------------------#
21
21
 
22
22
  # Create a Vector of size n. If zero is true, the vector is initialized with zeros.
23
23
  # Otherwise, the vector will contain garbage.
24
- # You can optionally pass a block, in which case #map_index! will be called with it (i.e.: it works like Array.new).
24
+ # You can optionally pass a block, in which case {#map_index!} will be called with it (i.e.: it works like {Array.new}).
25
25
  def initialize(n, zero = false)
26
26
  @size = n
27
27
  @ptr = (zero ? GSLng.backend::gsl_vector_calloc(n) : GSLng.backend::gsl_vector_alloc(n))
28
- GSLng.set_finalizer(self, :gsl_vector_free, @ptr)
29
- if (block_given?) then self.map_index!(Proc.new) end
28
+ GSLng.define_finalizer(self, :gsl_vector_free, @ptr)
29
+ if (block_given?) then self.map_index!(Proc.new) end
30
30
  end
31
31
 
32
32
  def initialize_copy(other) # @private
@@ -34,41 +34,45 @@ module GSLng
34
34
 
35
35
  @size = other.size
36
36
  @ptr = GSLng.backend::gsl_vector_alloc(other.size)
37
- GSLng.set_finalizer(self, :gsl_vector_free, @ptr)
37
+ GSLng.define_finalizer(self, :gsl_vector_free, @ptr)
38
38
 
39
39
  GSLng.backend::gsl_vector_memcpy(@ptr, other.ptr)
40
40
  end
41
41
 
42
- # Same as Vector.new(n, true)
43
- def Vector.zero(n); Vector.new(n, true) end
42
+ # Same as Vector.new(n, true)
43
+ def Vector.zero(n); Vector.new(n, true) end
44
44
 
45
- # Create a vector from an Array.
46
- def Vector.from_array(array)
47
- if (array.empty?) then raise "Can't create empty vector" end
48
- Vector.new(array.size) {|i| array[i]}
49
- end
45
+ # Create a vector from an Array.
46
+ def Vector.from_array(array)
47
+ if (array.empty?) then raise "Can't create empty vector" end
48
+ v = Vector.new(array.size)
49
+ GSLng.backend.gsl_vector_from_array(v.ptr.to_i, array)
50
+ return v
51
+ end
50
52
 
51
- # Creates a Vector from an Array (see #from_array) or a Range. For example:
52
- # Vector[1,2,3]
53
- # Vector[1..3]
54
- def Vector.[](*args)
53
+ # Creates a Vector from an Array or a Range
54
+ # @see Vector::from_array
55
+ # @example
56
+ # Vector[1,2,3]
57
+ # Vector[1..3]
58
+ def Vector.[](*args)
55
59
  array = (args.size == 1 && Range === args[0] ? args[0].to_a : args)
56
- Vector.from_array(array)
57
- end
60
+ Vector.from_array(array)
61
+ end
58
62
 
59
63
  # Generates a Vector of n random numbers between 0 and 1.
60
- # NOTE: This simply uses Kernel::rand
64
+ # NOTE: This simply uses {Kernel::rand}
61
65
  def Vector.random(n)
62
- Vector.new(n).map!{|x| Kernel::rand}
66
+ Vector.new(n).map!{|x| Kernel::rand}
63
67
  end
64
- class << self; alias_method :rand, :random end
68
+ class << self; alias_method :rand, :random end
65
69
 
66
70
  #--------------------- setting values -------------------------#
67
71
 
68
72
  # Set all values to v
69
73
  def all!(v); GSLng.backend::gsl_vector_set_all(self.ptr, v); return self end
70
- alias_method :set!, :all!
71
- alias_method :fill!, :all!
74
+ alias_method :set!, :all!
75
+ alias_method :fill!, :all!
72
76
 
73
77
  # Set all values to zero
74
78
  def zero!; GSLng.backend::gsl_vector_set_zero(self.ptr); return self end
@@ -79,53 +83,57 @@ module GSLng
79
83
  #--------------------- operators -------------------------#
80
84
 
81
85
  # Add (element-by-element) other to self
86
+ # @return [Vector] self
82
87
  def add!(other)
83
88
  case other
84
89
  when Numeric; GSLng.backend::gsl_vector_add_constant(self.ptr, other.to_f)
85
90
  when Vector; GSLng.backend::gsl_vector_add(self.ptr, other.ptr)
86
91
  else
87
- x,y = other.coerce(self)
88
- x.add!(y)
89
- end
90
- return self
92
+ x,y = other.coerce(self)
93
+ x.add!(y)
94
+ end
95
+ return self
91
96
  end
92
97
 
93
98
  # Substract (element-by-element) other from self
99
+ # @return [Vector] self
94
100
  def substract!(other)
95
101
  case other
96
102
  when Numeric; GSLng.backend::gsl_vector_add_constant(self.ptr, -other.to_f)
97
103
  when Vector; GSLng.backend::gsl_vector_sub(self.ptr, other.ptr)
98
104
  else
99
- x,y = other.coerce(self)
100
- x.sub!(y)
101
- end
102
- return self
105
+ x,y = other.coerce(self)
106
+ x.sub!(y)
107
+ end
108
+ return self
103
109
  end
104
110
  alias_method :sub!, :substract!
105
111
 
106
112
  # Multiply (element-by-element) other with self
113
+ # @return [Vector] self
107
114
  def multiply!(other)
108
115
  case other
109
116
  when Numeric; GSLng.backend::gsl_blas_dscal(other.to_f, self.ptr)
110
117
  when Vector; GSLng.backend::gsl_vector_mul(self.ptr, other.ptr)
111
118
  else
112
- x,y = other.coerce(self)
113
- x.mul!(y)
114
- end
115
- return self
119
+ x,y = other.coerce(self)
120
+ x.mul!(y)
121
+ end
122
+ return self
116
123
  end
117
124
  alias_method :mul!, :multiply!
118
125
 
119
126
  # Divide (element-by-element) self by other
127
+ # @return [Vector] self
120
128
  def divide!(other)
121
129
  case other
122
130
  when Numeric; GSLng.backend::gsl_blas_dscal(1.0 / other, self.ptr)
123
131
  when Vector; GSLng.backend::gsl_vector_div(self.ptr, other.ptr)
124
132
  else
125
- x,y = other.coerce(self)
126
- x.div!(y)
127
- end
128
- return self
133
+ x,y = other.coerce(self)
134
+ x.div!(y)
135
+ end
136
+ return self
129
137
  end
130
138
  alias_method :div!, :divide!
131
139
 
@@ -136,14 +144,17 @@ module GSLng
136
144
  def -(other); self.dup.sub!(other) end
137
145
 
138
146
  # Element-by-element product
147
+ # @example
148
+ # Vector[1,2,3] * 2 => [2.0, 4.0, 6.0]:Vector
149
+ # Vector[1,2,3] * Vector[0,1,2] => [0.0, 2.0, 6.0]:Vector
139
150
  def *(other)
140
151
  case other
141
152
  when Numeric; self.dup.mul!(other)
142
153
  when Vector; self.dup.mul!(other)
143
154
  else
144
- x,y = other.coerce(self)
145
- x * y
146
- end
155
+ x,y = other.coerce(self)
156
+ x * y
157
+ end
147
158
  end
148
159
 
149
160
  # Element-by-element division
@@ -155,6 +166,9 @@ module GSLng
155
166
  #--------------------- other math -------------------------#
156
167
 
157
168
  # Dot product between self and other (uses BLAS's ddot)
169
+ # @return [Float]
170
+ # @example
171
+ # Vector[1,2,3] ^ Vector[0,1,2] => 8.0
158
172
  def dot(other)
159
173
  out = FFI::Buffer.new(:double)
160
174
  GSLng.backend::gsl_blas_ddot(self.ptr, other.ptr, out)
@@ -180,29 +194,54 @@ module GSLng
180
194
  # Swap the i-th element with the j-th element
181
195
  def swap(i,j); GSLng.backend::gsl_vector_swap_elements(self.ptr, i, j); return self end
182
196
 
183
- def sort!; GSLng.backend::gsl_sort_vector(self.ptr); return self end
184
- def sort; self.dup.sort! end
197
+ def sort!; GSLng.backend::gsl_sort_vector(self.ptr); return self end
198
+ def sort; self.dup.sort! end
185
199
 
186
200
  # Copy other's values into self
187
201
  def copy(other); GSLng.backend::gsl_vector_memcpy(self.ptr, other.ptr); return self end
188
202
 
203
+ # Wraps self into the interval [min,max) by adding or substracting (max-min) to each component as necessary.
204
+ # Note that wrapping is done only with a single addition/substraction.
205
+ # @param [Vector,Numeric] min
206
+ # @param [Vector,Numeric] max
207
+ # @return [Vector] a vector of values -1, 1 or 0, if (max-min) was substracted, added to the coordinate,
208
+ # or not modified, respectively.
209
+ # @example Assuming that +v = Vector[-8,2,8]+
210
+ # v.wrap(0, 5) => [1.0 0.0 -1.0]:Vector
211
+ # v => [-3.0 2.0 3.0]:Vector
212
+ def wrap!(min, max)
213
+ min,other = self.coerce(min)
214
+ max,other = self.coerce(max)
215
+ delta = Vector.new(self.size)
216
+ range = max - min
217
+
218
+ self.map_index! do |i|
219
+ if (self[i] < min[i]) then delta[i] = 1; self[i] + range[i]
220
+ elsif (self[i] >= max[i]) then delta[i] = -1; self[i] - range[i]
221
+ else delta[i] = 0; self[i] end
222
+ end
223
+ return delta
224
+ end
225
+
189
226
  #--------------------- set/get -------------------------#
190
227
 
191
- # Access the i-th element (*NOTE*: throws exception if out-of-bounds).
192
- # If _index_ is negative, it counts from the end (-1 is the last element).
193
- # TODO: support ranges
228
+ # Access the i-th element.
229
+ # If _index_ is negative, it counts from the end (-1 is the last element).
230
+ # @raise [RuntimeError] if out-of-bounds
231
+ # @todo support ranges
194
232
  def [](index)
195
- GSLng.backend::gsl_vector_get(self.ptr, (index < 0 ? @size + index : index))
233
+ GSLng.backend::gsl_vector_get(self.ptr, (index < 0 ? @size + index : index))
196
234
  end
197
235
 
198
- # Set the i-th element (*NOTE*: throws exception if out-of-bounds).
199
- # If _index_ is negative, it counts from the end (-1 is the last element).
200
- # TODO: support ranges
236
+ # Set the i-th element.
237
+ # If _index_ is negative, it counts from the end (-1 is the last element).
238
+ # @raise [RuntimeError] if out-of-bounds
239
+ # @todo support ranges
201
240
  def []=(index, value)
202
- GSLng.backend::gsl_vector_set(self.ptr, (index < 0 ? @size + index : index), value.to_f)
241
+ GSLng.backend::gsl_vector_set(self.ptr, (index < 0 ? @size + index : index), value.to_f)
203
242
  end
204
243
 
205
- # Create a Vector::View from this Vector.
244
+ # Create a {Vector::View} from this Vector.
206
245
  # If _size_ is nil, it is computed automatically from _offset_ and _stride_
207
246
  def view(offset = 0, size = nil, stride = 1)
208
247
  if (stride <= 0) then raise 'stride must be positive' end
@@ -223,15 +262,24 @@ module GSLng
223
262
  def subvector(*args); subvector_view(*args).to_vector end
224
263
 
225
264
  #------------ utility methods for 2D,3D and 4D vectors -----------#
265
+
266
+ # Same as Vector#[0]
226
267
  def x; GSLng.backend::gsl_vector_get(self.ptr, 0) end
268
+ # Same as Vector#[1]
227
269
  def y; GSLng.backend::gsl_vector_get(self.ptr, 1) end
228
- def z; GSLng.backend::gsl_vector_get(self.ptr, 2) end
229
- def w; GSLng.backend::gsl_vector_get(self.ptr, 3) end
270
+ # Same as Vector#[2]
271
+ def z; GSLng.backend::gsl_vector_get(self.ptr, 2) end
272
+ # Same as Vector#[3]
273
+ def w; GSLng.backend::gsl_vector_get(self.ptr, 3) end
230
274
 
275
+ # Same as Vector#[0]=
231
276
  def x=(v); GSLng.backend::gsl_vector_set(self.ptr, 0, v.to_f) end
277
+ # Same as Vector#[1]=
232
278
  def y=(v); GSLng.backend::gsl_vector_set(self.ptr, 1, v.to_f) end
279
+ # Same as Vector#[2]=
233
280
  def z=(v); GSLng.backend::gsl_vector_set(self.ptr, 2, v.to_f) end
234
- def w=(v); GSLng.backend::gsl_vector_set(self.ptr, 3, v.to_f) end
281
+ # Same as Vector#[3]=
282
+ def w=(v); GSLng.backend::gsl_vector_set(self.ptr, 3, v.to_f) end
235
283
 
236
284
  #--------------------- predicate methods -------------------------#
237
285
 
@@ -243,10 +291,22 @@ module GSLng
243
291
 
244
292
  #if all elements are strictly negative (<0)
245
293
  def negative?; GSLng.backend::gsl_vector_isneg(self.ptr) == 1 ? true : false end
246
-
294
+
247
295
  # if all elements are non-negative (>=0)
248
296
  def nonnegative?; GSLng.backend::gsl_vector_isnonneg(self.ptr) == 1 ? true : false end
249
297
 
298
+ # If each element of self is less than other's elements
299
+ def <(other); (other - self).positive? end
300
+
301
+ # If each element of self is greater than other's elements
302
+ def >(other); (other - self).negative? end
303
+
304
+ # If each element of self is less-or-equal than other's elements
305
+ def <=(other); (other - self).nonnegative? end
306
+
307
+ # If each element of self is less-or-equal than other's elements
308
+ def >=(other); (self - other).nonnegative? end
309
+
250
310
  #--------------------- min/max -------------------------#
251
311
 
252
312
  # Return maximum element of vector
@@ -255,7 +315,7 @@ module GSLng
255
315
  # Return minimum element of vector
256
316
  def min; GSLng.backend::gsl_vector_min(self.ptr) end
257
317
 
258
- # Same as Array#minmax
318
+ # Same as {Array#minmax}
259
319
  def minmax
260
320
  min = FFI::Buffer.new(:double)
261
321
  max = FFI::Buffer.new(:double)
@@ -263,87 +323,97 @@ module GSLng
263
323
  return [min[0].get_float64(0),max[0].get_float64(0)]
264
324
  end
265
325
 
266
- # Same as #minmax, but returns the indices to the elements
326
+ # Same as {#minmax}, but returns the indices to the elements
267
327
  def minmax_index
268
328
  min = FFI::Buffer.new(:size_t)
269
329
  max = FFI::Buffer.new(:size_t)
270
330
  GSLng.backend::gsl_vector_minmax_index(self.ptr, min, max)
271
331
  #return [min[0].get_size_t(0),max[0].get_size_t(0)]
272
- return [min[0].get_ulong(0),max[0].get_ulong(0)]
332
+ return [min[0].get_ulong(0),max[0].get_ulong(0)]
273
333
  end
274
334
 
275
- # Same as #min, but returns the index to the element
335
+ # Same as {#min}, but returns the index to the element
276
336
  def min_index; GSLng.backend::gsl_vector_min_index(self.ptr) end
277
337
 
278
- # Same as #max, but returns the index to the element
338
+ # Same as {#max}, but returns the index to the element
279
339
  def max_index; GSLng.backend::gsl_vector_max_index(self.ptr) end
280
340
 
281
341
  #--------------------- block handling -------------------------#
282
-
283
- # Yields the block for each element in the Vector
284
- def each # :yield: obj
285
- @size.times {|i| yield(self[i])}
286
- end
287
-
288
- # Same as #each, but faster. The catch is that this method returns nothing.
289
- def fast_each(block = Proc.new) #:yield: obj
290
- GSLng.backend::gsl_vector_each(self.ptr, block)
342
+
343
+ # Same as {#each}, but faster. The catch is that this method returns nothing.
344
+ # @yield [elem]
345
+ def each(block = Proc.new)
346
+ GSLng.backend::gsl_vector_each(self.ptr.to_i, &block)
291
347
  end
292
348
 
293
- def fast_each_with_index(block = Proc.new) #:yield: obj,i
294
- GSLng.backend::gsl_vector_each_with_index(self.ptr, block)
349
+ # @see #each
350
+ # @yield [elem,i]
351
+ def each_with_index(block = Proc.new)
352
+ GSLng.backend::gsl_vector_each_with_index(self.ptr.to_i, &block)
295
353
  end
296
354
 
297
- # Efficient map! implementation
298
- def map!(block = Proc.new); GSLng.backend::gsl_vector_map(self.ptr, block); return self end
355
+ # Efficient {#map!} implementation.
356
+ def map!(block = Proc.new); GSLng.backend::gsl_vector_map!(self.ptr.to_i, &block); return self end
299
357
 
300
- # Alternate version of #map!, in this case the block receives the index as a parameter.
301
- def map_index!(block = Proc.new); GSLng.backend::gsl_vector_map_index(self.ptr, block); return self end
358
+ # Similar to {#map!}, but passes the index to the element instead.
359
+ # @yield [i]
360
+ def map_index!(block = Proc.new); GSLng.backend::gsl_vector_map_index!(self.ptr.to_i, &block); return self end
302
361
 
303
- # See #map!. Returns a Vector.
304
- def map(block = Proc.new); self.dup.map!(block) end
362
+ # @return [Vector]
363
+ # @see map_index!
364
+ # @yield [i]
365
+ def map_index(block = Proc.new); self.dup.map_index!(block) end
305
366
 
306
- # Same as #map but returns an Array
307
- def map_array(block = Proc.new) ary = []; self.fast_each {|elem| ary << block.call(elem)}; return ary end
367
+ alias_method :map_array, :map
368
+
369
+ # @return [Vector]
370
+ # @yield [elem]
371
+ def map(block = Proc.new); self.dup.map!(block) end
308
372
 
309
373
  #--------------------- conversions -------------------------#
310
374
 
311
- # Same as Array#join
312
- def join(sep = $,)
313
- s = ''
314
- GSLng.backend::gsl_vector_each(self.ptr, lambda {|e| s += (s.empty?() ? e.to_s : "#{sep}#{e}")})
315
- return s
316
- end
375
+ # @see Array#join
376
+ # @return [String]
377
+ def join(sep = $,)
378
+ s = ''
379
+ self.each do |e|
380
+ s += (s.empty?() ? e.to_s : "#{sep}#{e}")
381
+ end
382
+ return s
383
+ end
317
384
 
318
- # Coerces _other_ to be a Vector. If _other_ is a scalar (a Numeric) a vector of the same size as self
319
- # will be created with all values set to _other_.
320
- def coerce(other)
385
+ # Coerces _other_ to be a Vector.
386
+ # @example
387
+ # Vector[1,2].coerce(5) => [[5.0, 5.0]:Vector, [1.0, 2.0]:Vector]
388
+ def coerce(other)
321
389
  case other
322
- when Vector
323
- [ other, self ]
324
- when Numeric
325
- [ Vector.new(@size).set!(other), self ]
326
- else
327
- raise TypeError, "Can't coerce #{other.class} into #{self.class}"
328
- end
329
- end
330
-
331
- # Convert to String (same format as Array#to_s):
390
+ when Vector
391
+ [ other, self ]
392
+ when Numeric
393
+ [ Vector.new(@size).set!(other), self ]
394
+ else
395
+ raise TypeError, "Can't coerce #{other.class} into #{self.class}"
396
+ end
397
+ end
398
+
399
+ # @return [String] same format as {Array#to_s}
400
+ # @example
332
401
  # Vector[1,2,3].to_s => "[1.0, 2.0, 3.0]"
333
- def to_s
334
- "[" + self.join(', ') + "]"
335
- end
402
+ def to_s
403
+ "[" + self.join(', ') + "]"
404
+ end
336
405
 
337
406
  def inspect # @private
338
407
  "#{self}:Vector"
339
408
  end
340
409
 
341
- # Convert to Array
342
- def to_a
343
- Array.new(@size) {|i| self[i]}
344
- end
410
+ # @return [Array]
411
+ def to_a
412
+ GSLng.backend.gsl_vector_to_a(self.ptr.to_i)
413
+ end
345
414
 
346
415
  # Create a row matrix from this vector
416
+ # @return [Matrix]
347
417
  def to_matrix
348
418
  m = Matrix.new(1, @size)
349
419
  GSLng.backend::gsl_matrix_set_row(m.ptr, 0, self.ptr)
@@ -352,6 +422,7 @@ module GSLng
352
422
  alias_method :to_row, :to_matrix
353
423
 
354
424
  # Create a column matrix from this vector
425
+ # @return [Matrix]
355
426
  def transpose
356
427
  m = Matrix.new(@size, 1)
357
428
  GSLng.backend::gsl_matrix_set_col(m.ptr, 0, self.ptr)
@@ -361,13 +432,13 @@ module GSLng
361
432
 
362
433
  #--------------------- equality -------------------------#
363
434
 
364
- # Element-by-element comparison. Admits comparing to Array.
365
- def ==(other)
366
- if (self.size != other.size) then return false end
367
- self.fast_each_with_index do |elem,i|
368
- if (elem != other[i]) then return false end
369
- end
370
- return true
371
- end
435
+ # Element-by-element comparison. Admits comparing to Array.
436
+ def ==(other)
437
+ if (self.size != other.size) then return false end
438
+ self.each_with_index do |elem,i|
439
+ if (elem != other[i]) then return false end
440
+ end
441
+ return true
442
+ end
372
443
  end
373
444
  end