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.
- 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
|