spliner 1.0.5 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|