nmatrix 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.txt +102 -10
- data/README.rdoc +24 -32
- data/Rakefile +1 -1
- data/ext/nmatrix/data/complex.h +9 -0
- data/ext/nmatrix/data/data.cpp +78 -4
- data/ext/nmatrix/data/data.h +86 -54
- data/ext/nmatrix/data/rational.h +2 -0
- data/ext/nmatrix/data/ruby_object.h +38 -8
- data/ext/nmatrix/extconf.rb +13 -7
- data/ext/nmatrix/nmatrix.cpp +262 -139
- data/ext/nmatrix/nmatrix.h +11 -4
- data/ext/nmatrix/storage/common.cpp +20 -13
- data/ext/nmatrix/storage/common.h +18 -12
- data/ext/nmatrix/storage/dense.cpp +122 -192
- data/ext/nmatrix/storage/dense.h +4 -2
- data/ext/nmatrix/storage/list.cpp +467 -636
- data/ext/nmatrix/storage/list.h +6 -3
- data/ext/nmatrix/storage/storage.cpp +83 -46
- data/ext/nmatrix/storage/storage.h +7 -7
- data/ext/nmatrix/storage/yale.cpp +621 -361
- data/ext/nmatrix/storage/yale.h +21 -9
- data/ext/nmatrix/ttable_helper.rb +27 -31
- data/ext/nmatrix/types.h +1 -1
- data/ext/nmatrix/util/math.cpp +9 -10
- data/ext/nmatrix/util/sl_list.cpp +1 -7
- data/ext/nmatrix/util/sl_list.h +0 -118
- data/lib/nmatrix/blas.rb +59 -18
- data/lib/nmatrix/monkeys.rb +0 -52
- data/lib/nmatrix/nmatrix.rb +136 -9
- data/lib/nmatrix/nvector.rb +33 -0
- data/lib/nmatrix/shortcuts.rb +95 -16
- data/lib/nmatrix/version.rb +1 -1
- data/lib/nmatrix/yale_functions.rb +25 -19
- data/spec/blas_spec.rb +1 -19
- data/spec/elementwise_spec.rb +132 -17
- data/spec/lapack_spec.rb +0 -3
- data/spec/nmatrix_list_spec.rb +18 -0
- data/spec/nmatrix_spec.rb +44 -18
- data/spec/nmatrix_yale_spec.rb +1 -3
- data/spec/shortcuts_spec.rb +26 -36
- data/spec/slice_spec.rb +2 -4
- metadata +2 -2
data/lib/nmatrix/monkeys.rb
CHANGED
@@ -52,18 +52,6 @@ class Array
|
|
52
52
|
|
53
53
|
if stype != :dense then matrix.cast(stype, dtype) else matrix end
|
54
54
|
end
|
55
|
-
|
56
|
-
unless method_defined?(:max)
|
57
|
-
def max #:nodoc:
|
58
|
-
self.inject(self.first) { |m, n| if n > m then n else m end }
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
unless method_defined?(:min)
|
63
|
-
def min #:nodoc:
|
64
|
-
self.inject(self.first) { |m, n| if n < m then n else m end }
|
65
|
-
end
|
66
|
-
end
|
67
55
|
end
|
68
56
|
|
69
57
|
class Object #:nodoc:
|
@@ -72,43 +60,3 @@ class Object #:nodoc:
|
|
72
60
|
value
|
73
61
|
end
|
74
62
|
end
|
75
|
-
|
76
|
-
class String #:nodoc:
|
77
|
-
unless method_defined?(:constantize)
|
78
|
-
# Based on constantize from ActiveSupport::Inflector
|
79
|
-
def constantize
|
80
|
-
names = self.split('::')
|
81
|
-
names.shift if names.empty? || names.first.empty?
|
82
|
-
|
83
|
-
constant = Object
|
84
|
-
names.each do |name|
|
85
|
-
constant = constant.const_defined?(name, false) ? constant.const_get(name) : constant.const_missing(name)
|
86
|
-
end
|
87
|
-
constant
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
unless method_defined?(:camelize)
|
92
|
-
# Adapted from camelize from ActiveSupport::Inflector
|
93
|
-
def camelize first_letter_in_uppercase = true
|
94
|
-
if first_letter_in_uppercase
|
95
|
-
self.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
96
|
-
else
|
97
|
-
self.to_s[0].chr.downcase + self[1..-1].camelize
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
unless method_defined?(:underscore)
|
103
|
-
# Adapted from underscore from ActiveSupport::Inflector
|
104
|
-
def underscore
|
105
|
-
word = self.dup
|
106
|
-
word.gsub!(/::/, '/')
|
107
|
-
word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
108
|
-
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
109
|
-
word.tr!("-", "_")
|
110
|
-
word.downcase!
|
111
|
-
word
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
data/lib/nmatrix/nmatrix.rb
CHANGED
@@ -82,6 +82,48 @@ class NMatrix
|
|
82
82
|
end
|
83
83
|
alias :pp :pretty_print
|
84
84
|
|
85
|
+
|
86
|
+
#
|
87
|
+
# call-seq:
|
88
|
+
# cast(stype, dtype, default) -> NMatrix
|
89
|
+
# cast(stype, dtype) -> NMatrix
|
90
|
+
# cast(stype) -> NMatrix
|
91
|
+
# cast(options) -> NMatrix
|
92
|
+
#
|
93
|
+
# This is a user-friendly helper for calling #cast_full. The easiest way to call this function is using an
|
94
|
+
# options hash, e.g.,
|
95
|
+
#
|
96
|
+
# n.cast(:stype => :yale, :dtype => :int64, :default => false)
|
97
|
+
#
|
98
|
+
# For list and yale, :default sets the "default value" or "init" of the matrix. List allows a bit more freedom
|
99
|
+
# since non-zeros are permitted. For yale, unpredictable behavior may result if the value is not false, nil, or
|
100
|
+
# some version of 0. Dense discards :default.
|
101
|
+
#
|
102
|
+
# dtype and stype are inferred from the matrix upon which #cast is called -- so you only really need to provide
|
103
|
+
# one. You can actually call this function with no arguments, in which case it functions like #clone.
|
104
|
+
#
|
105
|
+
# If your dtype is :object and you are converting from :dense to a sparse type, it is recommended that you
|
106
|
+
# provide a :default, as 0 may behave differently from its Float, Rational, or Complex equivalent. If no option
|
107
|
+
# is given, Fixnum 0 will be used.
|
108
|
+
def cast(*params)
|
109
|
+
if (params.size > 0 && params[0].is_a?(Hash))
|
110
|
+
opts = {
|
111
|
+
:stype => self.stype,
|
112
|
+
:dtype => self.dtype,
|
113
|
+
:default => self.stype == :dense ? 0 : self.default_value
|
114
|
+
}.merge(params[0])
|
115
|
+
|
116
|
+
self.cast_full(opts[:stype], opts[:dtype], opts[:default])
|
117
|
+
else
|
118
|
+
params << self.stype if params.size == 0
|
119
|
+
params << self.dtype if params.size == 1
|
120
|
+
params << (self.stype == :dense ? 0 : self.default_value) if params.size == 2
|
121
|
+
|
122
|
+
self.cast_full(*params)
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
85
127
|
#
|
86
128
|
# call-seq:
|
87
129
|
# rows -> Integer
|
@@ -122,8 +164,10 @@ class NMatrix
|
|
122
164
|
end
|
123
165
|
end
|
124
166
|
h
|
125
|
-
else # dense and list should use a C internal
|
126
|
-
|
167
|
+
else # dense and list should use a C internal function.
|
168
|
+
# FIXME: Write a C internal to_h function.
|
169
|
+
m = stype == :dense ? self.cast(:list, self.dtype) : self
|
170
|
+
m.__list_to_hash__
|
127
171
|
end
|
128
172
|
end
|
129
173
|
alias :to_h :to_hash
|
@@ -293,6 +337,7 @@ class NMatrix
|
|
293
337
|
'[' + ary.collect { |a| a ? a : 'nil'}.join(',') + ']'
|
294
338
|
end
|
295
339
|
|
340
|
+
|
296
341
|
##
|
297
342
|
# call-seq:
|
298
343
|
# each_along_dim() -> Enumerator
|
@@ -317,6 +362,7 @@ class NMatrix
|
|
317
362
|
end
|
318
363
|
end
|
319
364
|
|
365
|
+
|
320
366
|
##
|
321
367
|
# call-seq:
|
322
368
|
# reduce_along_dim() -> Enumerator
|
@@ -441,7 +487,7 @@ class NMatrix
|
|
441
487
|
def min(dimen=0)
|
442
488
|
reduce_along_dim(dimen) do |min, sub_mat|
|
443
489
|
if min.is_a? NMatrix then
|
444
|
-
min * (min <= sub_mat) + ((min)*0.0 + (min > sub_mat)) * sub_mat
|
490
|
+
min * (min <= sub_mat).cast(self.stype, self.dtype) + ((min)*0.0 + (min > sub_mat).cast(self.stype, self.dtype)) * sub_mat
|
445
491
|
else
|
446
492
|
min <= sub_mat ? min : sub_mat
|
447
493
|
end
|
@@ -460,7 +506,7 @@ class NMatrix
|
|
460
506
|
def max(dimen=0)
|
461
507
|
reduce_along_dim(dimen) do |max, sub_mat|
|
462
508
|
if max.is_a? NMatrix then
|
463
|
-
max * (max >= sub_mat) + ((max)*0.0 + (max < sub_mat)) * sub_mat
|
509
|
+
max * (max >= sub_mat).cast(self.stype, self.dtype) + ((max)*0.0 + (max < sub_mat).cast(self.stype, self.dtype)) * sub_mat
|
464
510
|
else
|
465
511
|
max >= sub_mat ? max : sub_mat
|
466
512
|
end
|
@@ -508,7 +554,7 @@ class NMatrix
|
|
508
554
|
|
509
555
|
##
|
510
556
|
# call-seq:
|
511
|
-
# to_f
|
557
|
+
# to_f -> Float
|
512
558
|
#
|
513
559
|
# Converts an nmatrix with a single element (but any number of dimensions)
|
514
560
|
# to a float.
|
@@ -523,8 +569,24 @@ class NMatrix
|
|
523
569
|
|
524
570
|
##
|
525
571
|
# call-seq:
|
526
|
-
#
|
527
|
-
#
|
572
|
+
# each -> Enumerator
|
573
|
+
#
|
574
|
+
# Enumerate through the matrix. @see Enumerable#each
|
575
|
+
#
|
576
|
+
# For dense, this actually calls a specialized each iterator (in C). For yale and list, it relies upon
|
577
|
+
# #each_with_indices (which is about as fast as reasonably possible for C code).
|
578
|
+
def each &block
|
579
|
+
if self.stype == :dense
|
580
|
+
self.__dense_each__(&block)
|
581
|
+
else
|
582
|
+
self.each_with_indices(&block)
|
583
|
+
end
|
584
|
+
end
|
585
|
+
|
586
|
+
##
|
587
|
+
# call-seq:
|
588
|
+
# map -> Enumerator
|
589
|
+
# map { |elem| block } -> NMatrix
|
528
590
|
#
|
529
591
|
# @see Enumerable#map
|
530
592
|
#
|
@@ -537,8 +599,8 @@ class NMatrix
|
|
537
599
|
|
538
600
|
##
|
539
601
|
# call-seq:
|
540
|
-
# map!
|
541
|
-
# map!
|
602
|
+
# map! -> Enumerator
|
603
|
+
# map! { |elem| block } -> NMatrix
|
542
604
|
#
|
543
605
|
# Maps in place.
|
544
606
|
# @see #map
|
@@ -620,7 +682,70 @@ class NMatrix
|
|
620
682
|
end
|
621
683
|
end
|
622
684
|
|
685
|
+
|
686
|
+
def method_missing name, *args, &block #:nodoc:
|
687
|
+
if name.to_s =~ /^__list_elementwise_.*__$/
|
688
|
+
raise NotImplementedError, "requested undefined list matrix element-wise operation"
|
689
|
+
elsif name.to_s =~ /^__yale_scalar_.*__$/
|
690
|
+
raise NotImplementedError, "requested undefined yale scalar element-wise operation"
|
691
|
+
else
|
692
|
+
super(name, *args, &block)
|
693
|
+
end
|
694
|
+
end
|
695
|
+
|
623
696
|
protected
|
697
|
+
# Define the element-wise operations for lists. Note that the __list_map_merged_stored__ iterator returns a Ruby Object
|
698
|
+
# matrix, which we then cast back to the appropriate type. If you don't want that, you can redefine these functions in
|
699
|
+
# your own code.
|
700
|
+
{add: :+, sub: :-, mul: :*, div: :/, pow: :**, mod: :%}.each_pair do |ewop, op|
|
701
|
+
define_method("__list_elementwise_#{ewop}__") do |rhs|
|
702
|
+
self.__list_map_merged_stored__(rhs, nil) { |l,r| l.send(op,r) }.cast(stype, NMatrix.upcast(dtype, rhs.dtype))
|
703
|
+
end
|
704
|
+
define_method("__dense_elementwise_#{ewop}__") do |rhs|
|
705
|
+
self.__dense_map_pair__(rhs) { |l,r| l.send(op,r) }.cast(stype, NMatrix.upcast(dtype, rhs.dtype))
|
706
|
+
end
|
707
|
+
define_method("__yale_elementwise_#{ewop}__") do |rhs|
|
708
|
+
self.__yale_map_merged_stored__(rhs, nil) { |l,r| l.send(op,r) }.cast(stype, NMatrix.upcast(dtype, rhs.dtype))
|
709
|
+
end
|
710
|
+
define_method("__list_scalar_#{ewop}__") do |rhs|
|
711
|
+
self.__list_map_merged_stored__(rhs, nil) { |l,r| l.send(op,r) }.cast(stype, NMatrix.upcast(dtype, NMatrix.min_dtype(rhs)))
|
712
|
+
end
|
713
|
+
define_method("__yale_scalar_#{ewop}__") do |rhs|
|
714
|
+
self.__yale_map_stored__ { |l| l.send(op,rhs) }.cast(stype, NMatrix.upcast(dtype, NMatrix.min_dtype(rhs)))
|
715
|
+
end
|
716
|
+
define_method("__dense_scalar_#{ewop}__") do |rhs|
|
717
|
+
self.__dense_map__ { |l| l.send(op,rhs) }.cast(stype, NMatrix.upcast(dtype, NMatrix.min_dtype(rhs)))
|
718
|
+
end
|
719
|
+
end
|
720
|
+
|
721
|
+
# Equality operators do not involve a cast. We want to get back matrices of TrueClass and FalseClass.
|
722
|
+
{eqeq: :==, neq: :!=, lt: :<, gt: :>, leq: :<=, geq: :>=}.each_pair do |ewop, op|
|
723
|
+
define_method("__list_elementwise_#{ewop}__") do |rhs|
|
724
|
+
self.__list_map_merged_stored__(rhs, nil) { |l,r| l.send(op,r) }
|
725
|
+
end
|
726
|
+
define_method("__dense_elementwise_#{ewop}__") do |rhs|
|
727
|
+
self.__dense_map_pair__(rhs) { |l,r| l.send(op,r) }
|
728
|
+
end
|
729
|
+
define_method("__yale_elementwise_#{ewop}__") do |rhs|
|
730
|
+
self.__yale_map_merged_stored__(rhs, nil) { |l,r| l.send(op,r) }
|
731
|
+
end
|
732
|
+
|
733
|
+
define_method("__list_scalar_#{ewop}__") do |rhs|
|
734
|
+
self.__list_map_merged_stored__(rhs, nil) { |l,r| l.send(op,r) }
|
735
|
+
end
|
736
|
+
define_method("__yale_scalar_#{ewop}__") do |rhs|
|
737
|
+
self.__yale_map_stored__ { |l| l.send(op,rhs) }
|
738
|
+
end
|
739
|
+
define_method("__dense_scalar_#{ewop}__") do |rhs|
|
740
|
+
self.__dense_map__ { |l| l.send(op,rhs) }
|
741
|
+
end
|
742
|
+
end
|
743
|
+
|
744
|
+
# This is how you write an individual element-wise operation function:
|
745
|
+
#def __list_elementwise_add__ rhs
|
746
|
+
# self.__list_map_merged_stored__(rhs){ |l,r| l+r }.cast(self.stype, NMatrix.upcast(self.dtype, rhs.dtype))
|
747
|
+
#end
|
748
|
+
|
624
749
|
def inspect_helper #:nodoc:
|
625
750
|
ary = []
|
626
751
|
ary << "shape:[#{shape.join(',')}]" << "dtype:#{dtype}" << "stype:#{stype}"
|
@@ -639,4 +764,6 @@ protected
|
|
639
764
|
|
640
765
|
ary
|
641
766
|
end
|
767
|
+
|
768
|
+
|
642
769
|
end
|
data/lib/nmatrix/nvector.rb
CHANGED
@@ -248,6 +248,39 @@ class NVector < NMatrix
|
|
248
248
|
t.shuffle!(*args)
|
249
249
|
end
|
250
250
|
|
251
|
+
#
|
252
|
+
# call-seq:
|
253
|
+
# sorted_indices -> Array
|
254
|
+
#
|
255
|
+
# Returns an array of the indices ordered by value sorted.
|
256
|
+
#
|
257
|
+
def sorted_indices
|
258
|
+
ary = self.to_a
|
259
|
+
ary.each_index.sort_by { |i| ary[i] } # from: http://stackoverflow.com/a/17841159/170300
|
260
|
+
end
|
261
|
+
|
262
|
+
#
|
263
|
+
# call-seq:
|
264
|
+
# binned_sorted_indices -> Array
|
265
|
+
#
|
266
|
+
# Returns an array of arrays of indices ordered by value sorted. Functions basically like +sorted_indices+, but
|
267
|
+
# groups indices together for those values that are the same.
|
268
|
+
#
|
269
|
+
def binned_sorted_indices
|
270
|
+
ary = self.to_a
|
271
|
+
ary2 = []
|
272
|
+
last_bin = ary.each_index.sort_by { |i| [ary[i]] }.inject([]) do |result, element|
|
273
|
+
if result.empty? || ary[result[-1]] == ary[element]
|
274
|
+
result << element
|
275
|
+
else
|
276
|
+
ary2 << result
|
277
|
+
[element]
|
278
|
+
end
|
279
|
+
end
|
280
|
+
ary2 << last_bin unless last_bin.empty?
|
281
|
+
ary2
|
282
|
+
end
|
283
|
+
|
251
284
|
|
252
285
|
# TODO: Make this actually pretty.
|
253
286
|
def pretty_print(q = nil) #:nodoc:
|
data/lib/nmatrix/shortcuts.rb
CHANGED
@@ -133,7 +133,7 @@ class NMatrix
|
|
133
133
|
|
134
134
|
# Fill the diagonal with 1's.
|
135
135
|
m = NMatrix.zeros(stype, dim, dtype)
|
136
|
-
(0
|
136
|
+
(0...dim).each do |i|
|
137
137
|
m[i, i] = 1
|
138
138
|
end
|
139
139
|
|
@@ -141,6 +141,49 @@ class NMatrix
|
|
141
141
|
end
|
142
142
|
alias :identity :eye
|
143
143
|
|
144
|
+
#
|
145
|
+
# call-seq:
|
146
|
+
# diagonals(array) -> NMatrix
|
147
|
+
# diagonals(stype, array, dtype) -> NMatrix
|
148
|
+
# diagonals(array, dtype) -> NMatrix
|
149
|
+
# diagonals(stype, array) -> NMatrix
|
150
|
+
#
|
151
|
+
# Creates a matrix filled with specified diagonals.
|
152
|
+
#
|
153
|
+
# * *Arguments* :
|
154
|
+
# - +stype+ -> (optional) Storage type for the matrix (default is :dense)
|
155
|
+
# - +entries+ -> Array containing input values for diagonal matrix
|
156
|
+
# - +dtype+ -> (optional) Default is based on values in supplied Array
|
157
|
+
# * *Returns* :
|
158
|
+
# - NMatrix filled with specified diagonal values.
|
159
|
+
#
|
160
|
+
# Examples:
|
161
|
+
#
|
162
|
+
# NMatrix.diagonal([1.0,2,3,4]) # => 1.0 0.0 0.0 0.0
|
163
|
+
# 0.0 2.0 0.0 0.0
|
164
|
+
# 0.0 0.0 3.0 0.0
|
165
|
+
# 0.0 0.0 0.0 4.0
|
166
|
+
#
|
167
|
+
# NMatrix.diagonal(:dense, [1,2,3,4], :int32) # => 1 0 0 0
|
168
|
+
# 0 2 0 0
|
169
|
+
# 0 0 3 0
|
170
|
+
# 0 0 0 4
|
171
|
+
#
|
172
|
+
#
|
173
|
+
def diagonal(*params)
|
174
|
+
dtype = params.last.is_a?(Symbol) ? params.pop : nil
|
175
|
+
stype = params.first.is_a?(Symbol) ? params.shift : :dense
|
176
|
+
ary = params.shift
|
177
|
+
|
178
|
+
m = NMatrix.zeros(stype, ary.length, dtype || guess_dtype(ary[0]))
|
179
|
+
ary.each_with_index do |n, i|
|
180
|
+
m[i,i] = n
|
181
|
+
end
|
182
|
+
m
|
183
|
+
end
|
184
|
+
alias :diag :diagonal
|
185
|
+
alias :diagonals :diagonal
|
186
|
+
|
144
187
|
#
|
145
188
|
# call-seq:
|
146
189
|
# random(size) -> NMatrix
|
@@ -527,33 +570,29 @@ class NVector < NMatrix
|
|
527
570
|
# Returns a NVector with +n+ values of dtype +:float64+ equally spaced from
|
528
571
|
# +a+ to +b+, inclusive.
|
529
572
|
#
|
530
|
-
#
|
531
|
-
# be 100.
|
573
|
+
# See: http://www.mathworks.com/help/matlab/ref/linspace.html
|
532
574
|
#
|
533
575
|
# * *Arguments* :
|
534
576
|
# - +a+ -> The first value in the sequence.
|
535
577
|
# - +b+ -> The last value in the sequence.
|
536
|
-
# - +n+ -> The number of elements.
|
578
|
+
# - +n+ -> The number of elements. Default is 100.
|
537
579
|
# * *Returns* :
|
538
|
-
# -
|
580
|
+
# - NVector with +n+ +:float64+ values.
|
539
581
|
#
|
540
582
|
# Example:
|
541
583
|
# x = NVector.linspace(0, Math::PI, 1000)
|
542
|
-
#
|
543
|
-
#
|
544
|
-
#
|
545
|
-
#
|
546
|
-
# [0.0031447373909807737]
|
547
|
-
# [0.006289474781961547]
|
584
|
+
# x.pretty_print
|
585
|
+
# [0.0
|
586
|
+
# 0.0031447373909807737
|
587
|
+
# 0.006289474781961547
|
548
588
|
# ...
|
549
|
-
#
|
550
|
-
#
|
551
|
-
#
|
589
|
+
# 3.135303178807831
|
590
|
+
# 3.138447916198812
|
591
|
+
# 3.141592653589793]
|
552
592
|
# => nil
|
553
593
|
#
|
554
594
|
def linspace(a, b, n = 100)
|
555
|
-
#
|
556
|
-
# Formula: seq(n) * step + a
|
595
|
+
# Formula: seq(n) * step + a
|
557
596
|
|
558
597
|
# step = ((b - a) / (n - 1))
|
559
598
|
step = (b - a) * (1.0 / (n - 1))
|
@@ -563,6 +602,46 @@ class NVector < NMatrix
|
|
563
602
|
result += NVector.new(n, a, :float64)
|
564
603
|
result
|
565
604
|
end
|
605
|
+
|
606
|
+
#
|
607
|
+
# call-seq:
|
608
|
+
# logspace(a, b) -> NVector
|
609
|
+
# logspace(a, b, n) -> NVector
|
610
|
+
#
|
611
|
+
# Returns a NVector with +n+ values of dtype +:float64+ logarithmically
|
612
|
+
# spaced from +10^a+ to +10^b+, inclusive.
|
613
|
+
#
|
614
|
+
# See: http://www.mathworks.com/help/matlab/ref/logspace.html
|
615
|
+
#
|
616
|
+
# * *Arguments* :
|
617
|
+
# - +a+ -> The first value in the sequence.
|
618
|
+
# - +b+ -> The last value in the sequence.
|
619
|
+
# - +n+ -> The number of elements. Default is 100.
|
620
|
+
# * *Returns* :
|
621
|
+
# - NVector with +n+ +:float64+ values.
|
622
|
+
#
|
623
|
+
# Example:
|
624
|
+
# x = NVector.logspace(0, Math::PI, 10)
|
625
|
+
# x.pretty_print
|
626
|
+
# [1.0
|
627
|
+
# 2.2339109164570266
|
628
|
+
# 4.990357982665873
|
629
|
+
# 11.148015174505757
|
630
|
+
# 24.903672795156997
|
631
|
+
# 55.632586516975095
|
632
|
+
# 124.27824233101062
|
633
|
+
# 277.6265222213364
|
634
|
+
# 620.1929186882427
|
635
|
+
# 1385.4557313670107]
|
636
|
+
# => nil
|
637
|
+
#
|
638
|
+
def logspace(a, b, n = 100)
|
639
|
+
# Formula: 10^a, 10^(a + step), ..., 10^b, where step = ((b-a) / (n-1)).
|
640
|
+
|
641
|
+
result = NVector.linspace(a, b, n)
|
642
|
+
result.each_stored_with_index { |element, i| result[i] = 10 ** element }
|
643
|
+
result
|
644
|
+
end
|
566
645
|
end
|
567
646
|
end
|
568
647
|
|