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 CHANGED
@@ -1,2 +1,3 @@
1
1
  *.gem
2
2
  Gemfile.lock
3
+ .idea
@@ -1,4 +1,5 @@
1
1
  rvm:
2
+ - 2.0.0
2
3
  - 1.9.2
3
4
  - 1.9.3
4
5
  - jruby
data/Gemfile CHANGED
File without changes
File without changes
data/Rakefile CHANGED
File without changes
@@ -1,5 +1,5 @@
1
1
  require 'spliner/spliner'
2
2
 
3
3
  module Spliner
4
- VERSION = '1.0.5'
4
+ VERSION = '1.0.6'
5
5
  end
@@ -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.member? v }
173
+ i = @sections.find_index {|section| section.range.cover? v }
174
174
  if i
175
175
  @sections[i].get v
176
- elsif range.member? v
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
- 3.0 * (y2 - y1) / (x2 - x1) ** 2.0
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
- @k = a.inv * b
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.member? v }
62
+ i = @x_pairs.find_index {|pair| pair.cover? v }
58
63
  if i
59
- dx = @x[i + 1] - @x[i]
60
- dy = @y[i + 1] - @y[i]
61
- t = (v - @x[i]) / dx
62
- a = @k[i] * dx - dy
63
- b = -(@k[i + 1] * dx - dy)
64
- (1 - t) * @y[i] + t * @y[i + 1] + t * (1 - t) * (a * (1 - t) + b * t)
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
@@ -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(0.0001).of(0.0)
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(0.0001).of(0.0)
21
- expect(s2.get 0.5).to be_within(0.0001).of(0.0)
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(0.0001).of(0.5)
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(0.0001).of(0.5)
30
- expect(s2.range.first).to be_within(0.0001).of(-1.0)
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(0.0001).of(0.5)
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(0.0001).of(0.5)
39
- expect(s2.range.first).to be_within(0.0001).of(-1.0)
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(0.0001).of(0.5)
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(0.0001).of(0.5260)
61
- expect(s.get(0.8)).to be_within(0.0001).of(0.9080)
62
- expect(s.get(1.2)).to be_within(0.0001).of(1.0080)
63
- expect(s.get(1.6)).to be_within(0.0001).of(0.8260)
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(0.0001).of(30.0)
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(0.0001).of(0.0)
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(0.0001).of(-150)
81
- expect(s.get 150).to be_within(0.0001).of(150)
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(0.0001).of(0)
87
- expect(s.get 150).to be_within(0.0001).of(100)
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(0.0001).of(-10.0)
93
- expect(s1.range.last).to be_within(0.0001).of(110.0)
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(0.0001).of(-10.0)
97
- expect(s2.range.last).to be_within(0.0001).of(110.0)
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(0.0001).of(-10.0)
101
- expect(s3.range.last).to be_within(0.0001).of(110.0)
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(0.0001).of(-10.0)
105
- expect(s3.range.last).to be_within(0.0001).of(110.0)
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(0.0001).of(0.0)
113
- expect(s[1.5]).to be_within(0.0001).of(1.0)
114
- expect(s[2.5]).to be_within(0.0001).of(2.0)
115
- expect(s[3.5]).to be_within(0.0001).of(2.0)
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
 
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.5
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: 2012-11-12 00:00:00.000000000 Z
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.24
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
- has_rdoc:
88
+ test_files:
89
+ - spec/spliner_spec.rb