standard_deviation 1.0.0 → 1.0.1

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/.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