spliner 1.0.5 → 1.0.6
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/.gitignore +1 -0
- data/.travis.yml +1 -0
- data/Gemfile +0 -0
- data/README.markdown +0 -0
- data/Rakefile +0 -0
- data/lib/spliner.rb +1 -1
- data/lib/spliner/spliner.rb +2 -2
- data/lib/spliner/spliner_section.rb +21 -11
- data/spec/spliner_spec.rb +43 -32
- data/spliner.gemspec +0 -0
- metadata +5 -5
data/.gitignore
CHANGED
data/Gemfile
CHANGED
File without changes
|
data/README.markdown
CHANGED
File without changes
|
data/Rakefile
CHANGED
File without changes
|
data/lib/spliner.rb
CHANGED
data/lib/spliner/spliner.rb
CHANGED
@@ -170,10 +170,10 @@ module Spliner
|
|
170
170
|
end
|
171
171
|
|
172
172
|
get_func = lambda do |v|
|
173
|
-
i = @sections.find_index {|section| section.range.
|
173
|
+
i = @sections.find_index {|section| section.range.cover? v }
|
174
174
|
if i
|
175
175
|
@sections[i].get v
|
176
|
-
elsif range.
|
176
|
+
elsif range.cover? v
|
177
177
|
extrapolate(v)
|
178
178
|
else
|
179
179
|
nil
|
@@ -24,10 +24,10 @@ module Spliner
|
|
24
24
|
|
25
25
|
def calculate_a_k
|
26
26
|
if @x.size > 1
|
27
|
-
inv_diff = @x.each_cons(2).map {|x1, x2| 1 / (x2 - x1) }
|
27
|
+
inv_diff = @x.each_cons(2).map {|x1, x2| 1.0 / (x2 - x1) }
|
28
28
|
a_diag = 2.0 * Matrix::diagonal(*vector_helper(inv_diff))
|
29
29
|
a_non_diag = Matrix::build(@x.size) do |row, col|
|
30
|
-
if row == col+ 1
|
30
|
+
if row == col + 1
|
31
31
|
inv_diff[col]
|
32
32
|
elsif col == row + 1
|
33
33
|
inv_diff[row]
|
@@ -41,11 +41,16 @@ module Spliner
|
|
41
41
|
tmp = @x.zip(@y).each_cons(2).map do |p1, p2|
|
42
42
|
x1, y1 = p1
|
43
43
|
x2, y2 = p2
|
44
|
-
|
44
|
+
delta_x = (x2 - x1)
|
45
|
+
3.0 * (y2 - y1) / (delta_x * delta_x)
|
45
46
|
end
|
46
47
|
b = vector_helper(tmp)
|
47
48
|
|
48
|
-
|
49
|
+
if RUBY_VERSION < "1.9.3"
|
50
|
+
@k = a.inv * b
|
51
|
+
else
|
52
|
+
@k = a.lup_decomposition.solve b
|
53
|
+
end
|
49
54
|
else
|
50
55
|
@k = Vector[0.0]
|
51
56
|
end
|
@@ -54,14 +59,19 @@ module Spliner
|
|
54
59
|
|
55
60
|
# returns an interpolated value
|
56
61
|
def get(v)
|
57
|
-
i = @x_pairs.find_index {|pair| pair.
|
62
|
+
i = @x_pairs.find_index {|pair| pair.cover? v }
|
58
63
|
if i
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
64
|
+
x_pair = @x_pairs[i]
|
65
|
+
x_min = x_pair.min
|
66
|
+
dx = x_pair.max - x_min
|
67
|
+
y_max = @y[i + 1]
|
68
|
+
y_min = @y[i]
|
69
|
+
dy = y_max - y_min
|
70
|
+
t = (v - x_min) / dx
|
71
|
+
a = @k[i] * dx - dy
|
72
|
+
b = -@k[i + 1] * dx + dy
|
73
|
+
one_minus_t = 1 - t
|
74
|
+
t * y_max + one_minus_t * ( y_min + t * ( a * one_minus_t + b * t ) )
|
65
75
|
elsif @x.size == 1 && @x.first == v
|
66
76
|
@y.first
|
67
77
|
else
|
data/spec/spliner_spec.rb
CHANGED
@@ -6,6 +6,17 @@ describe Spliner::Spliner do
|
|
6
6
|
DATASET_Y = [0.0, 1.0, 0.5]
|
7
7
|
KEYS_0_100 = {0.0 => 0.0, 100.0 => 100.0}
|
8
8
|
|
9
|
+
before(:all) do
|
10
|
+
epsilon = nil
|
11
|
+
e = 1
|
12
|
+
while e + 1 > 1
|
13
|
+
epsilon = e
|
14
|
+
e *= 0.5
|
15
|
+
end
|
16
|
+
|
17
|
+
@two_epsilon = 2 * epsilon
|
18
|
+
end
|
19
|
+
|
9
20
|
|
10
21
|
it 'should not accept x values that are not increasing' do
|
11
22
|
expect(lambda { Spliner::Spliner.new [0.0, -1.0], [0.0, 1.0] }).to raise_exception
|
@@ -13,33 +24,33 @@ describe Spliner::Spliner do
|
|
13
24
|
|
14
25
|
it 'should support key points with a single value' do
|
15
26
|
s1 = Spliner::Spliner.new Hash[0.0, 0.0]
|
16
|
-
expect(s1.get 0.0).to be_within(
|
27
|
+
expect(s1.get 0.0).to be_within(@two_epsilon).of(0.0)
|
17
28
|
expect(s1.get 1.5).to be_nil
|
18
29
|
|
19
30
|
s2 = Spliner::Spliner.new Hash[0.0, 0.0], :extrapolate => -1..1
|
20
|
-
expect(s2.get 0.0).to be_within(
|
21
|
-
expect(s2.get 0.5).to be_within(
|
31
|
+
expect(s2.get 0.0).to be_within(@two_epsilon).of(0.0)
|
32
|
+
expect(s2.get 0.5).to be_within(@two_epsilon).of(0.0)
|
22
33
|
end
|
23
34
|
|
24
35
|
it 'supports the Hash initializer' do
|
25
36
|
s1 = Spliner::Spliner.new Hash[0.0, 0.0, 1.0, 1.0]
|
26
|
-
expect(s1[0.5]).to be_within(
|
37
|
+
expect(s1[0.5]).to be_within(@two_epsilon).of(0.5)
|
27
38
|
|
28
39
|
s2 = Spliner::Spliner.new Hash[0.0, 0.0, 1.0, 1.0], :extrapolate => '100%'
|
29
|
-
expect(s2[0.5]).to be_within(
|
30
|
-
expect(s2.range.first).to be_within(
|
40
|
+
expect(s2[0.5]).to be_within(@two_epsilon).of(0.5)
|
41
|
+
expect(s2.range.first).to be_within(@two_epsilon).of(-1.0)
|
31
42
|
end
|
32
43
|
|
33
44
|
it 'supports the x-y array/vector initializer' do
|
34
45
|
s1 = Spliner::Spliner.new [0.0, 1.0], [0.0, 1.0]
|
35
|
-
expect(s1[0.5]).to be_within(
|
46
|
+
expect(s1[0.5]).to be_within(@two_epsilon).of(0.5)
|
36
47
|
|
37
48
|
s2= Spliner::Spliner.new [0.0, 1.0], [0.0, 1.0], :extrapolate => '100%'
|
38
|
-
expect(s2[0.5]).to be_within(
|
39
|
-
expect(s2.range.first).to be_within(
|
49
|
+
expect(s2[0.5]).to be_within(@two_epsilon).of(0.5)
|
50
|
+
expect(s2.range.first).to be_within(@two_epsilon).of(-1.0)
|
40
51
|
|
41
52
|
s3 = Spliner::Spliner.new Vector[0.0, 1.0], Vector[0.0, 1.0]
|
42
|
-
expect(s3[0.5]).to be_within(
|
53
|
+
expect(s3[0.5]).to be_within(@two_epsilon).of(0.5)
|
43
54
|
end
|
44
55
|
|
45
56
|
it 'should return the data points themselves' do
|
@@ -57,62 +68,62 @@ describe Spliner::Spliner do
|
|
57
68
|
|
58
69
|
it 'should generate a smooth curve (predefined points)' do
|
59
70
|
s = Spliner::Spliner.new DATASET
|
60
|
-
expect(s.get(0.4)).to be_within(
|
61
|
-
expect(s.get(0.8)).to be_within(
|
62
|
-
expect(s.get(1.2)).to be_within(
|
63
|
-
expect(s.get(1.6)).to be_within(
|
71
|
+
expect(s.get(0.4)).to be_within(@two_epsilon).of(0.5260)
|
72
|
+
expect(s.get(0.8)).to be_within(@two_epsilon).of(0.9080)
|
73
|
+
expect(s.get(1.2)).to be_within(@two_epsilon).of(1.0080)
|
74
|
+
expect(s.get(1.6)).to be_within(@two_epsilon).of(0.8260)
|
64
75
|
end
|
65
76
|
|
66
77
|
it 'should perform linear interpolation in the case of two data points' do
|
67
78
|
s = Spliner::Spliner.new({0 => 0, 10.0 => 100.0})
|
68
|
-
expect(s.get(3.0)).to be_within(
|
79
|
+
expect(s.get(3.0)).to be_within(@two_epsilon).of(30.0)
|
69
80
|
end
|
70
81
|
|
71
82
|
it 'supports the [] operator (indexing like)' do
|
72
83
|
s = Spliner::Spliner.new DATASET
|
73
84
|
expect(s[-1]).to be_nil
|
74
|
-
expect(s[0]).to be_within(
|
85
|
+
expect(s[0]).to be_within(@two_epsilon).of(0.0)
|
75
86
|
end
|
76
87
|
|
77
88
|
it 'performs :linear extrapolation outside the data range when such is given' do
|
78
89
|
s = Spliner::Spliner.new KEYS_0_100, :extrapolate => -200..200
|
79
90
|
expect(s.get -110).not_to be_nil
|
80
|
-
expect(s.get -150).to be_within(
|
81
|
-
expect(s.get 150).to be_within(
|
91
|
+
expect(s.get -150).to be_within(1e-13).of(-150)
|
92
|
+
expect(s.get 150).to be_within(1e-13).of(150)
|
82
93
|
end
|
83
94
|
|
84
95
|
it 'performs :hold extrapolation' do
|
85
96
|
s = Spliner::Spliner.new KEYS_0_100, :extrapolate => -200..200, :emethod => :hold
|
86
|
-
expect(s.get -150).to be_within(
|
87
|
-
expect(s.get 150).to be_within(
|
97
|
+
expect(s.get -150).to be_within(@two_epsilon).of(0)
|
98
|
+
expect(s.get 150).to be_within(@two_epsilon).of(100)
|
88
99
|
end
|
89
100
|
|
90
101
|
it 'supports data ranges given as a string like "10%"' do
|
91
102
|
s1 = Spliner::Spliner.new KEYS_0_100, :extrapolate => '10%'
|
92
|
-
expect(s1.range.first).to be_within(
|
93
|
-
expect(s1.range.last).to be_within(
|
103
|
+
expect(s1.range.first).to be_within(@two_epsilon).of(-10.0)
|
104
|
+
expect(s1.range.last).to be_within(@two_epsilon).of(110.0)
|
94
105
|
|
95
106
|
s2 = Spliner::Spliner.new KEYS_0_100, :extrapolate => '10.0%'
|
96
|
-
expect(s2.range.first).to be_within(
|
97
|
-
expect(s2.range.last).to be_within(
|
107
|
+
expect(s2.range.first).to be_within(@two_epsilon).of(-10.0)
|
108
|
+
expect(s2.range.last).to be_within(@two_epsilon).of(110.0)
|
98
109
|
|
99
110
|
s3 = Spliner::Spliner.new KEYS_0_100, :extrapolate => '10 %'
|
100
|
-
expect(s3.range.first).to be_within(
|
101
|
-
expect(s3.range.last).to be_within(
|
111
|
+
expect(s3.range.first).to be_within(@two_epsilon).of(-10.0)
|
112
|
+
expect(s3.range.last).to be_within(@two_epsilon).of(110.0)
|
102
113
|
|
103
114
|
s4 = Spliner::Spliner.new KEYS_0_100, :extrapolate => 0.1
|
104
|
-
expect(s3.range.first).to be_within(
|
105
|
-
expect(s3.range.last).to be_within(
|
115
|
+
expect(s3.range.first).to be_within(@two_epsilon).of(-10.0)
|
116
|
+
expect(s3.range.last).to be_within(@two_epsilon).of(110.0)
|
106
117
|
end
|
107
118
|
|
108
119
|
it 'splits data points with duplicate X values into separate sections' do
|
109
120
|
s = Spliner::Spliner.new [0.0, 1.0, 1.0, 2.0, 2.0, 3.0], [0.0, 0.0, 1.0, 1.0, 2.0, 2.0], :extrapolate => 3.0..4.0
|
110
121
|
expect(s.sections).to eq(3)
|
111
122
|
expect(s[-1.0]).to be_nil
|
112
|
-
expect(s[0.5]).to be_within(
|
113
|
-
expect(s[1.5]).to be_within(
|
114
|
-
expect(s[2.5]).to be_within(
|
115
|
-
expect(s[3.5]).to be_within(
|
123
|
+
expect(s[0.5]).to be_within(@two_epsilon).of(0.0)
|
124
|
+
expect(s[1.5]).to be_within(@two_epsilon).of(1.0)
|
125
|
+
expect(s[2.5]).to be_within(@two_epsilon).of(2.0)
|
126
|
+
expect(s[3.5]).to be_within(@two_epsilon).of(2.0)
|
116
127
|
expect(s[5.0]).to be_nil
|
117
128
|
end
|
118
129
|
|
data/spliner.gemspec
CHANGED
File without changes
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spliner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-06-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -81,9 +81,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
81
|
version: '0'
|
82
82
|
requirements: []
|
83
83
|
rubyforge_project: spliner
|
84
|
-
rubygems_version: 1.8.
|
84
|
+
rubygems_version: 1.8.23
|
85
85
|
signing_key:
|
86
86
|
specification_version: 3
|
87
87
|
summary: Cubic spline interpolation library
|
88
|
-
test_files:
|
89
|
-
|
88
|
+
test_files:
|
89
|
+
- spec/spliner_spec.rb
|