standard_deviation 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - rbx-18mode
7
+ - rbx-19mode
8
+ - ree
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  An implementation of the standard deviation calculation in C, with much better performance (50x-100x) than using pure ruby.
4
4
 
5
+ [![Build Status](https://secure.travis-ci.org/reu/fonte.png)](http://travis-ci.org/reu/standard_deviation)
6
+
5
7
  ## Installation
6
8
 
7
9
  Add this line to your application's Gemfile:
@@ -32,6 +34,7 @@ For population standard deviation, call `stdevp`:
32
34
  ```
33
35
 
34
36
  Also, the API exposes the `sample_variance` and `population_variance` calculations:
37
+
35
38
  ``` ruby
36
39
  [1, 2, 3, 4, 5].sample_variance => 2.5
37
40
  [1, 2, 3, 4, 5].population_variance => 2.0
@@ -0,0 +1,26 @@
1
+ require "standard_deviation"
2
+ require "benchmark"
3
+ require 'bigdecimal'
4
+
5
+ class Array
6
+ def stdev_ruby
7
+ total = inject :+
8
+ mean = total.to_f / size
9
+ variance = inject(0) { |variance, value| variance + (value - mean) ** 2 } / (size - 1)
10
+
11
+ Math.sqrt(variance)
12
+ end
13
+ end
14
+
15
+ n = 50
16
+ values = (1..10_000).map { |value| BigDecimal.new [value, (rand * 10000000000).to_i].join(".") }
17
+
18
+ Benchmark.bm do |b|
19
+ b.report do
20
+ n.times { values.stdev }
21
+ end
22
+
23
+ b.report do
24
+ n.times { values.stdev_ruby }
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ require "standard_deviation"
2
+ require "benchmark"
3
+
4
+ class Array
5
+ def stdev_ruby
6
+ total = inject :+
7
+ mean = total.to_f / size
8
+ variance = inject(0) { |variance, value| variance + (value - mean) ** 2 } / (size - 1)
9
+
10
+ Math.sqrt(variance)
11
+ end
12
+ end
13
+
14
+ n = 1000
15
+ values = (1..10_000).map(&:to_f)
16
+
17
+ Benchmark.bm do |b|
18
+ b.report do
19
+ n.times { values.stdev }
20
+ end
21
+
22
+ b.report do
23
+ n.times { values.stdev_ruby }
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ require "standard_deviation"
2
+ require "bigdecimal"
3
+ require "benchmark"
4
+
5
+ n = 100
6
+ range = (1..10_000)
7
+
8
+ integers = range.to_a
9
+ floats = range.map(&:to_f)
10
+ decimals = range.map { |value| BigDecimal.new [value, (rand * 10000000000).to_i].join(".") }
11
+
12
+ Benchmark.bm do |b|
13
+ b.report do
14
+ n.times { integers.stdev }
15
+ end
16
+
17
+ b.report do
18
+ n.times { floats.stdev }
19
+ end
20
+
21
+ b.report do
22
+ n.times { decimals.stdev }
23
+ end
24
+ end
@@ -1,7 +1,7 @@
1
1
  #include <ruby.h>
2
2
  #include <math.h>
3
3
 
4
- static double sum(VALUE *array, int size) {
4
+ static double sum(VALUE *array, long size) {
5
5
  int i;
6
6
  double total = 0;
7
7
 
@@ -12,7 +12,7 @@ static double sum(VALUE *array, int size) {
12
12
  return total;
13
13
  }
14
14
 
15
- static double distance_from_mean(VALUE *array, int size) {
15
+ static double distance_from_mean(VALUE *array, long size) {
16
16
  int i;
17
17
  double mean, distance;
18
18
 
@@ -25,39 +25,51 @@ static double distance_from_mean(VALUE *array, int size) {
25
25
  return distance;
26
26
  }
27
27
 
28
- static double compute_sample_variance(VALUE *array, int size) {
28
+ static double compute_sample_variance(VALUE *array, long size) {
29
29
  return distance_from_mean(array, size) / (size - 1);
30
30
  }
31
31
 
32
- static double compute_population_variance(VALUE *array, int size) {
32
+ static double compute_population_variance(VALUE *array, long size) {
33
33
  return distance_from_mean(array, size) / size;
34
34
  }
35
35
 
36
+ static void raise_not_enough_elements() {
37
+ rb_raise(rb_eZeroDivError, "not enough elements");
38
+ }
39
+
36
40
  static VALUE sample_variance(VALUE self) {
37
- int size = RARRAY_LEN(self);
41
+ long size = RARRAY_LEN(self);
38
42
  VALUE *array = RARRAY_PTR(self);
39
43
 
44
+ if (size < 2) raise_not_enough_elements();
45
+
40
46
  return rb_float_new(compute_sample_variance(array, size));
41
47
  }
42
48
 
43
49
  static VALUE population_variance(VALUE self) {
44
- int size = RARRAY_LEN(self);
50
+ long size = RARRAY_LEN(self);
45
51
  VALUE *array = RARRAY_PTR(self);
46
52
 
53
+ if (size < 2) raise_not_enough_elements();
54
+
47
55
  return rb_float_new(compute_population_variance(array, size));
48
56
  }
49
57
 
50
58
  static VALUE stdev(VALUE self) {
51
- int size = RARRAY_LEN(self);
59
+ long size = RARRAY_LEN(self);
52
60
  VALUE *array = RARRAY_PTR(self);
53
61
 
62
+ if (size < 2) raise_not_enough_elements();
63
+
54
64
  return rb_float_new(sqrt(compute_sample_variance(array, size)));
55
65
  }
56
66
 
57
67
  static VALUE stdevp(VALUE self) {
58
- int size = RARRAY_LEN(self);
68
+ long size = RARRAY_LEN(self);
59
69
  VALUE *array = RARRAY_PTR(self);
60
70
 
71
+ if (size < 2) raise_not_enough_elements();
72
+
61
73
  return rb_float_new(sqrt(compute_population_variance(array, size)));
62
74
  }
63
75
 
@@ -1,3 +1,3 @@
1
1
  module StandardDeviation
2
- VERSION = "1.0.0"
2
+ VERSION = "1.0.1"
3
3
  end
data/spec/spec_helper.rb CHANGED
@@ -1,2 +1,8 @@
1
1
  require "standard_deviation"
2
2
  require "bigdecimal"
3
+
4
+ RSpec::Matchers.define :be_close_to do |expected|
5
+ match do |actual|
6
+ BigDecimal.new(actual.to_s).round(10) == BigDecimal.new(expected.to_s).round(10)
7
+ end
8
+ end
@@ -1,79 +1,103 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Array do
4
- describe "#stdev" do
5
- subject { values.stdev }
6
-
7
- context "with integer values" do
8
- let(:values) { [1, 2, 6, 3, -4, 23] }
9
- it { should == 9.32559202767667 }
4
+ shared_examples_for "a serie calculation" do
5
+ context "when called on a empty array" do
6
+ let(:values) { [] }
7
+ it { lambda { subject }.should raise_exception ZeroDivisionError, "not enough elements" }
10
8
  end
11
9
 
12
- context "with float values" do
13
- let(:values) { [1.0, 2.0, 6.0, 3.0, -4.0, 23.0] }
14
- it { should == 9.32559202767667 }
10
+ context "when called on a array with only one element" do
11
+ let(:values) { [1] }
12
+ it { lambda { subject }.should raise_exception ZeroDivisionError, "not enough elements" }
15
13
  end
14
+ end
16
15
 
17
- context "with bigdecimal values" do
18
- let(:values) { [BigDecimal("1.0"), BigDecimal("2.0"), BigDecimal("6.0"), BigDecimal("3.0"), BigDecimal("-4.0"), BigDecimal("23.0")] }
19
- it { should == 9.32559202767667 }
16
+ %w(stdev standard_deviation).each do |method|
17
+ describe "##{method}" do
18
+ subject { values.send method }
19
+
20
+ it_should_behave_like "a serie calculation"
21
+
22
+ context "with integer values" do
23
+ let(:values) { [1, 2, 6, 3, -4, 23] }
24
+ it { should be_close_to 9.32559202767667 }
25
+ end
26
+
27
+ context "with float values" do
28
+ let(:values) { [1.0, 2.0, 6.0, 3.0, -4.0, 23.0] }
29
+ it { should be_close_to 9.32559202767667 }
30
+ end
31
+
32
+ context "with bigdecimal values" do
33
+ let(:values) { [BigDecimal("1.0"), BigDecimal("2.0"), BigDecimal("6.0"), BigDecimal("3.0"), BigDecimal("-4.0"), BigDecimal("23.0")] }
34
+ it { should be_close_to 9.32559202767667 }
35
+ end
20
36
  end
21
37
  end
22
38
 
23
39
  describe "#stdevp" do
24
40
  subject { values.stdevp }
25
41
 
42
+ it_should_behave_like "a serie calculation"
43
+
26
44
  context "with integer values" do
27
45
  let(:values) { [1, 2, 6, 3, -4, 23] }
28
- it { should == 8.513061859414755 }
46
+ it { should be_close_to 8.513061859414755 }
29
47
  end
30
48
 
31
49
  context "with float values" do
32
50
  let(:values) { [1.0, 2.0, 6.0, 3.0, -4.0, 23.0] }
33
- it { should == 8.513061859414755 }
51
+ it { should be_close_to 8.513061859414755 }
34
52
  end
35
53
 
36
54
  context "with bigdecimal values" do
37
55
  let(:values) { [BigDecimal("1.0"), BigDecimal("2.0"), BigDecimal("6.0"), BigDecimal("3.0"), BigDecimal("-4.0"), BigDecimal("23.0")] }
38
- it { should == 8.513061859414755 }
56
+ it { should be_close_to 8.513061859414755 }
39
57
  end
40
58
  end
41
59
 
42
- describe "#sample_variance" do
43
- subject { values.sample_variance }
60
+ %w(variance sample_variance).each do |method|
61
+ describe "##{method}" do
62
+ subject { values.send method }
44
63
 
45
- context "with integer values" do
46
- let(:values) { [1, 2, 6, 3, -4, 23] }
47
- it { should == 86.96666666666665 }
48
- end
64
+ it_should_behave_like "a serie calculation"
49
65
 
50
- context "with float values" do
51
- let(:values) { [1.0, 2.0, 6.0, 3.0, -4.0, 23.0] }
52
- it { should == 86.96666666666665 }
53
- end
66
+ context "with integer values" do
67
+ let(:values) { [1, 2, 6, 3, -4, 23] }
68
+ it { should be_close_to 86.96666666666665 }
69
+ end
54
70
 
55
- context "with bigdecimal values" do
56
- let(:values) { [BigDecimal("1.0"), BigDecimal("2.0"), BigDecimal("6.0"), BigDecimal("3.0"), BigDecimal("-4.0"), BigDecimal("23.0")] }
57
- it { should == 86.96666666666665 }
71
+ context "with float values" do
72
+ let(:values) { [1.0, 2.0, 6.0, 3.0, -4.0, 23.0] }
73
+ it { should be_close_to 86.96666666666665 }
74
+ end
75
+
76
+ context "with bigdecimal values" do
77
+ let(:values) { [BigDecimal("1.0"), BigDecimal("2.0"), BigDecimal("6.0"), BigDecimal("3.0"), BigDecimal("-4.0"), BigDecimal("23.0")] }
78
+ it { should be_close_to 86.96666666666665 }
79
+ end
58
80
  end
59
81
  end
60
82
 
61
83
  describe "#population_variance" do
62
84
  subject { values.population_variance }
63
85
 
86
+ it_should_behave_like "a serie calculation"
87
+
64
88
  context "with integer values" do
65
89
  let(:values) { [1, 2, 6, 3, -4, 23] }
66
- it { should == 72.47222222222221 }
90
+ it { should be_close_to 72.47222222222221 }
67
91
  end
68
92
 
69
93
  context "with float values" do
70
94
  let(:values) { [1.0, 2.0, 6.0, 3.0, -4.0, 23.0] }
71
- it { should == 72.47222222222221 }
95
+ it { should be_close_to 72.47222222222221 }
72
96
  end
73
97
 
74
98
  context "with bigdecimal values" do
75
99
  let(:values) { [BigDecimal("1.0"), BigDecimal("2.0"), BigDecimal("6.0"), BigDecimal("3.0"), BigDecimal("-4.0"), BigDecimal("23.0")] }
76
- it { should == 72.47222222222221 }
100
+ it { should be_close_to 72.47222222222221 }
77
101
  end
78
102
  end
79
103
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: standard_deviation
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-13 00:00:00.000000000Z
12
+ date: 2012-04-14 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake-compiler
16
- requirement: &2161598240 !ruby/object:Gem::Requirement
16
+ requirement: &2156134040 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2161598240
24
+ version_requirements: *2156134040
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &2161597660 !ruby/object:Gem::Requirement
27
+ requirement: &2156133440 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2161597660
35
+ version_requirements: *2156133440
36
36
  description: ! "An implementation of the standard deviation calculation in C,\n with
37
37
  much better performance (50x-100x) than using pure ruby."
38
38
  email:
@@ -43,10 +43,14 @@ extensions:
43
43
  extra_rdoc_files: []
44
44
  files:
45
45
  - .gitignore
46
+ - .travis.yml
46
47
  - Gemfile
47
48
  - LICENSE
48
49
  - README.md
49
50
  - Rakefile
51
+ - benchmark/bigdecimal.rb
52
+ - benchmark/ruby_version.rb
53
+ - benchmark/types.rb
50
54
  - ext/standard_deviation/extconf.rb
51
55
  - ext/standard_deviation/standard_deviation.c
52
56
  - lib/standard_deviation.rb
@@ -69,7 +73,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
69
73
  version: '0'
70
74
  segments:
71
75
  - 0
72
- hash: 2357727006440476187
76
+ hash: -569388018503389721
73
77
  required_rubygems_version: !ruby/object:Gem::Requirement
74
78
  none: false
75
79
  requirements:
@@ -78,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
82
  version: '0'
79
83
  segments:
80
84
  - 0
81
- hash: 2357727006440476187
85
+ hash: -569388018503389721
82
86
  requirements: []
83
87
  rubyforge_project:
84
88
  rubygems_version: 1.8.10