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.
- data/History.txt +21 -0
- data/Manifest +9 -0
- data/Rakefile +9 -5
- data/ext/extconf.rb +2 -2
- data/ext/gslng_extensions.cpp +141 -36
- data/lib/gslng.rb +9 -8
- data/lib/gslng/backend.rb +5 -3
- data/lib/gslng/backend_components/error_handling.rb +11 -11
- data/lib/gslng/backend_components/matrix.rb +66 -75
- data/lib/gslng/backend_components/rng.rb +22 -0
- data/lib/gslng/backend_components/special.rb +7 -0
- data/lib/gslng/backend_components/vector.rb +63 -75
- data/lib/gslng/finalizer.rb +6 -2
- data/lib/gslng/matrix.rb +199 -134
- data/lib/gslng/matrix_view.rb +3 -2
- data/lib/gslng/rng/gaussian.rb +34 -0
- data/lib/gslng/rng/rng.rb +27 -0
- data/lib/gslng/rng/uniform.rb +23 -0
- data/lib/gslng/special.rb +22 -0
- data/lib/gslng/vector.rb +196 -125
- data/lib/gslng/vector_view.rb +5 -3
- data/ruby-gsl-ng.gemspec +6 -6
- data/test/benchmark.rb +61 -14
- data/test/benchmark_results +80 -0
- data/test/matrix_test.rb +11 -8
- data/test/rng_test.rb +27 -0
- data/test/test_special.rb +21 -0
- data/test/vector_test.rb +18 -4
- metadata +21 -4
data/lib/gslng/matrix_view.rb
CHANGED
@@ -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
|
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.
|
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
|
-
|
6
|
-
|
7
|
-
# *
|
8
|
-
# so they use
|
9
|
-
|
10
|
-
|
11
|
-
# * Operator
|
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 :
|
18
|
-
attr_reader :
|
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
|
-
|
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.
|
29
|
-
|
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.
|
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
|
-
|
43
|
-
|
42
|
+
# Same as Vector.new(n, true)
|
43
|
+
def Vector.zero(n); Vector.new(n, true) end
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
52
|
-
#
|
53
|
-
#
|
54
|
-
|
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
|
-
|
57
|
-
|
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
|
-
|
66
|
+
Vector.new(n).map!{|x| Kernel::rand}
|
63
67
|
end
|
64
|
-
|
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
|
-
|
71
|
-
|
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
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
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
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
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
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
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
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
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
|
-
|
145
|
-
|
146
|
-
|
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
|
-
|
184
|
-
|
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
|
-
|
192
|
-
|
193
|
-
|
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
|
-
|
233
|
+
GSLng.backend::gsl_vector_get(self.ptr, (index < 0 ? @size + index : index))
|
196
234
|
end
|
197
235
|
|
198
|
-
|
199
|
-
|
200
|
-
|
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
|
-
|
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
|
-
|
229
|
-
def
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
284
|
-
|
285
|
-
|
286
|
-
|
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
|
-
|
294
|
-
|
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
|
-
|
298
|
-
|
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
|
-
|
301
|
-
|
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
|
-
|
304
|
-
|
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
|
-
|
307
|
-
|
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
|
-
#
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
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.
|
319
|
-
#
|
320
|
-
|
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
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
#
|
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
|
-
|
334
|
-
|
335
|
-
|
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
|
-
#
|
342
|
-
|
343
|
-
|
344
|
-
|
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
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
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
|