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
@@ -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
|
@@ -1,75 +1,63 @@
|
|
1
|
-
module GSLng
|
2
|
-
|
3
|
-
|
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
|
-
#
|
56
|
-
attach_function :
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
data/lib/gslng/finalizer.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
module GSLng
|
2
|
-
def GSLng.
|
3
|
-
ObjectSpace.define_finalizer(obj,
|
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
|
7
|
-
# multiplication use the
|
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
|
-
|
11
|
+
attr_reader :m, :n
|
12
|
+
attr_reader :ptr # @private
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
alias_method :height, :m
|
15
|
+
alias_method :width, :n
|
16
|
+
alias_method :rows, :m
|
17
|
+
alias_method :columns, :n
|
17
18
|
|
18
|
-
|
19
|
-
|
19
|
+
# Shorthand for [{#rows},{#columns}]
|
20
|
+
def size; [ @m, @n ] end
|
20
21
|
|
21
22
|
#--------------------- constructors -------------------------#
|
22
23
|
|
23
|
-
|
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
|
-
|
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.
|
29
|
+
GSLng.define_finalizer(self, :gsl_matrix_free, @ptr)
|
29
30
|
|
30
31
|
@m,@n = m,n
|
31
|
-
|
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.
|
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
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
#
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
-
|
63
|
+
end
|
59
64
|
|
60
|
-
|
61
|
-
#
|
62
|
-
# Matrix[1,2,3]
|
63
|
-
# Matrix[
|
64
|
-
|
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
|
-
|
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
|
-
|
78
|
+
Matrix.new(m, n).map!{|x| Kernel::rand}
|
72
79
|
end
|
73
|
-
|
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
|
-
|
91
|
-
|
92
|
-
|
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
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
#
|
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
|
-
|
113
|
-
|
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
|
-
|
119
|
-
|
132
|
+
elsif (Symbol === i)
|
133
|
+
col = Vector.new(@m)
|
120
134
|
x,y = col.coerce(value)
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
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
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
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
|
-
|
133
|
-
|
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
|
-
#
|
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
|
-
|
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
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
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
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
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
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
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
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
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
|
241
|
-
#
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
347
|
-
|
348
|
-
|
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
|
-
#
|
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
|
-
|
364
|
-
|
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
|
-
|
367
|
-
|
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
|
-
|
370
|
-
|
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
|
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
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
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
|
-
|
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
|
-
|
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
|