accumulators 0.2.0 → 0.3.0

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/Gemfile.lock CHANGED
@@ -2,7 +2,7 @@ GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
4
  diff-lcs (1.1.2)
5
- ffi (1.0.8)
5
+ ffi (1.0.9)
6
6
  git (1.2.5)
7
7
  growl (1.0.3)
8
8
  guard (0.3.4)
@@ -13,8 +13,8 @@ GEM
13
13
  bundler (~> 1.0.0)
14
14
  git (>= 1.2.5)
15
15
  rake
16
- libnotify (0.3.0)
17
- ffi (>= 0.6.2)
16
+ libnotify (0.5.2)
17
+ ffi (~> 1.0)
18
18
  rake (0.9.0)
19
19
  rb-fsevent (0.4.0)
20
20
  rb-inotify (0.8.4)
@@ -24,7 +24,7 @@ GEM
24
24
  rspec-core (~> 2.6.0)
25
25
  rspec-expectations (~> 2.6.0)
26
26
  rspec-mocks (~> 2.6.0)
27
- rspec-core (2.6.1)
27
+ rspec-core (2.6.2)
28
28
  rspec-expectations (2.6.0)
29
29
  diff-lcs (~> 1.1.2)
30
30
  rspec-mocks (2.6.0)
data/Guardfile CHANGED
@@ -6,9 +6,4 @@ guard 'rspec', :version => 2 do
6
6
  watch(%r{^lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
7
  watch('spec/spec_helper.rb') { "spec" }
8
8
 
9
- # Rails example
10
- watch(%r{^spec/.+_spec\.rb})
11
- watch(%r{^app/(.+)\.rb}) { |m| "spec/#{m[1]}_spec.rb" }
12
- watch(%r{^lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
13
- watch(%r{^app/controllers/(.+)_(controller)\.rb}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
14
9
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
data/accumulators.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{accumulators}
8
- s.version = "0.2.0"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Gavin Heavyside"]
@@ -27,16 +27,13 @@ Gem::Specification.new do |s|
27
27
  "Rakefile",
28
28
  "VERSION",
29
29
  "accumulators.gemspec",
30
- "features/accumulators.feature",
31
- "features/step_definitions/accumulators_steps.rb",
32
- "features/support/env.rb",
33
30
  "lib/accumulators.rb",
34
31
  "lib/accumulators/count.rb",
35
32
  "lib/accumulators/mean.rb",
36
- "lib/accumulators/meanvariance.rb",
37
- "spec/accumulators/count_spec.rb",
38
- "spec/accumulators/mean_spec.rb",
39
- "spec/accumulators/meanvariance_spec.rb",
33
+ "lib/accumulators/mean_variance.rb",
34
+ "spec/lib/accumulators/count_spec.rb",
35
+ "spec/lib/accumulators/mean_spec.rb",
36
+ "spec/lib/accumulators/mean_variance_spec.rb",
40
37
  "spec/spec_helper.rb"
41
38
  ]
42
39
  s.homepage = %q{http://github.com/hgavin/accumulators}
data/lib/accumulators.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Accumulators
2
2
  autoload :Count, "accumulators/count"
3
3
  autoload :Mean, "accumulators/mean"
4
- autoload :MeanVariance, "accumulators/meanvariance"
4
+ autoload :MeanVariance, "accumulators/mean_variance"
5
5
  end
6
6
 
@@ -19,7 +19,7 @@ module Accumulators
19
19
  @count = @count + rhs.count
20
20
  @mean = (sum + rhs_sum) / @count
21
21
  else
22
- raise ArgumentError.new("Can only add numbers to a Mean Accumulator")
22
+ raise ArgumentError.new("You may not add #{rhs.class} to #{self.class}")
23
23
  end
24
24
  end
25
25
  end
@@ -28,16 +28,24 @@ module Accumulators
28
28
  @sumsq = newSumsq
29
29
  end
30
30
  else
31
- raise ArgumentError
31
+ raise ArgumentError.new("You may not add #{rhs.class} to #{self.class}")
32
32
  end
33
33
  end
34
34
 
35
- def variance
36
- @count > 1 ? (@sumsq / (@count)) : 0.0
35
+ def variance(options = {})
36
+ if options[:type] and not [:sample, :population].include? options[:type]
37
+ raise ArgumentError.new("type must be one of :sample, :population")
38
+ end
39
+
40
+ if options[:type] == :population
41
+ @count > 1 ? (@sumsq / (@count)) : 0.0
42
+ else
43
+ @count > 1 ? (@sumsq / (@count + 1)) : 0.0
44
+ end
37
45
  end
38
46
 
39
- def stddev
40
- Math.sqrt(variance)
47
+ def stddev(options = {})
48
+ Math.sqrt(variance(options))
41
49
  end
42
50
 
43
51
  end
@@ -1,60 +1,58 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "Accumulators" do
4
- describe "Count" do
5
- before :each do
6
- @count = Accumulators::Count.new
7
- end
3
+ module Accumulators
4
+ describe Count do
5
+ let(:count){Count.new}
8
6
 
9
7
  context "Creation" do
10
8
  it "can be created" do
11
- lambda{ Accumulators::Count.new }.should_not raise_error
9
+ lambda{ Count.new }.should_not raise_error
12
10
  end
13
11
 
14
12
  it "returns count of 0 before anything is added to it" do
15
- Accumulators::Count.new.count.should == 0
13
+ Count.new.count.should == 0
16
14
  end
17
15
  end
18
16
 
19
17
  context "adding numbers or distributions" do
20
18
  it "allows integers to be added" do
21
- lambda{@count.add 5}.should_not raise_error
19
+ lambda{count.add 5}.should_not raise_error
22
20
  end
23
21
 
24
22
  it "allows floats to be added" do
25
- lambda{@count.add 3.4}.should_not raise_error
23
+ lambda{count.add 3.4}.should_not raise_error
26
24
  end
27
25
 
28
26
  it "allows other Count distributions to be added" do
29
- c2 = Accumulators::Count.new
30
- lambda{@count.add c2}.should_not raise_error
27
+ c2 = Count.new
28
+ lambda{count.add c2}.should_not raise_error
31
29
  end
32
30
 
33
31
  it "allows strings to be added" do
34
- lambda{@count.add "1.5"}.should_not raise_error
32
+ lambda{count.add "1.5"}.should_not raise_error
35
33
  end
36
34
  end
37
35
 
38
36
  context "correctness of item additions" do
39
37
  it "should return a count of 1 when a single item is added" do
40
- @count.add 5
41
- @count.count.should == 1
38
+ count.add 5
39
+ count.count.should == 1
42
40
  end
43
41
 
44
42
  it "should return the count of how many items have been added" do
45
43
  1.upto(1000) do |i|
46
- @count.add i
47
- @count.count.should == i
44
+ count.add i
45
+ count.count.should == i
48
46
  end
49
47
  end
50
48
  end
51
49
 
52
50
  context "correctness of accumulator additions" do
53
51
  it "should combine two Count accumulators correctly" do
54
- c2 = Accumulators::Count.new
55
- 10.times{ c2.add 1; @count.add 1 }
56
- @count.add(c2)
57
- @count.count.should == 20
52
+ c2 = Count.new
53
+ 10.times{ c2.add 1; count.add 1 }
54
+ count.add(c2)
55
+ count.count.should == 20
58
56
  end
59
57
  end
60
58
  end
@@ -1,96 +1,96 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "Accumulators" do
4
- describe "Mean" do
5
- before :each do
6
- @mean = Accumulators::Mean.new
7
- end
3
+ module Accumulators
4
+ describe Mean do
5
+ let(:mean){Mean.new}
8
6
 
9
7
  context "Creation" do
10
8
  it "can be created" do
11
- lambda{ Accumulators::Mean.new}.should_not raise_error
9
+ lambda{ Mean.new}.should_not raise_error
12
10
  end
13
11
 
14
12
  it "returns count and mean of 0 before anything is added to it" do
15
- @mean.count.should == 0
16
- @mean.mean.should be_within(EPSILON).of(0.0)
13
+ mean.count.should == 0
14
+ mean.mean.should be_within(EPSILON).of(0.0)
17
15
  end
18
16
 
19
17
  end
20
18
 
21
19
  context "adding numbers or distributions" do
22
20
  it "allows integers to be added" do
23
- lambda{@mean.add 5}.should_not raise_error
21
+ lambda{mean.add 5}.should_not raise_error
24
22
  end
25
23
 
26
24
  it "allows floats to be added" do
27
- lambda{@mean.add 3.4}.should_not raise_error
25
+ lambda{mean.add 3.4}.should_not raise_error
28
26
  end
29
27
 
30
28
  it "allows other Mean distributions to be added" do
31
- mean2 = Accumulators::Mean.new
32
- lambda{@mean.add mean2}.should_not raise_error
29
+ mean2 = Mean.new
30
+ lambda{mean.add mean2}.should_not raise_error
33
31
  end
34
32
 
35
33
  it "raises an ArgumentError if a string is added" do
36
- lambda{@mean.add "1.5"}.should raise_error(ArgumentError)
34
+ lambda{mean.add "1.5"}.should raise_error(
35
+ ArgumentError,
36
+ "You may not add String to Accumulators::Mean")
37
37
  end
38
38
  end
39
39
 
40
40
  context "correctness of int additions" do
41
41
  it "should return count of 1 and mean of 5 when 5 is added" do
42
- @mean.add(5)
43
- @mean.count.should == 1
44
- @mean.mean.should be_within(EPSILON).of(5)
42
+ mean.add(5)
43
+ mean.count.should == 1
44
+ mean.mean.should be_within(EPSILON).of(5)
45
45
  end
46
46
 
47
47
  it "should calculate the mean correctly for a set of integers" do
48
- 1.upto(10) {|i| @mean.add i}
49
- @mean.count.should == 10
50
- @mean.mean.should be_within(EPSILON).of((1..10).reduce(:+).to_f/10)
48
+ 1.upto(10) {|i| mean.add i}
49
+ mean.count.should == 10
50
+ mean.mean.should be_within(EPSILON).of((1..10).reduce(:+).to_f/10)
51
51
  end
52
52
 
53
53
  it "should calculate the mean correctly for a random set of 1000 integers" do
54
54
  vals = []
55
55
  1000.times do
56
56
  vals << rand(100000)
57
- @mean.add(vals.last)
57
+ mean.add(vals.last)
58
58
  end
59
59
 
60
- @mean.mean.should be_within(EPSILON).of(vals.reduce(:+).to_f/vals.size)
60
+ mean.mean.should be_within(EPSILON).of(vals.reduce(:+).to_f/vals.size)
61
61
  end
62
62
  end
63
63
 
64
64
  context "correctness of float additions" do
65
65
  it "should calculate the mean correctly for a set of floats" do
66
- 1.upto(10) {|i| @mean.add i+0.1}
67
- @mean.count.should == 10
68
- @mean.mean.should be_within(EPSILON).of((1..10).map{|i| i+0.1}.reduce(:+)/10)
66
+ 1.upto(10) {|i| mean.add i+0.1}
67
+ mean.count.should == 10
68
+ mean.mean.should be_within(EPSILON).of((1..10).map{|i| i+0.1}.reduce(:+)/10)
69
69
  end
70
70
 
71
71
  it "should calculate the mean correctly for a random set of 1000 floats" do
72
72
  vals = []
73
73
  1000.times do
74
74
  vals << rand * 1000000
75
- @mean.add vals.last
75
+ mean.add vals.last
76
76
  end
77
- @mean.mean.should be_within(EPSILON).of(vals.reduce(:+)/vals.size)
77
+ mean.mean.should be_within(EPSILON).of(vals.reduce(:+)/vals.size)
78
78
  end
79
79
  end
80
80
 
81
81
  context "correctness of accumulator additions" do
82
82
  it "should combine two means correctly" do
83
- m2 = Accumulators::Mean.new
83
+ m2 = Mean.new
84
84
  vals = []
85
85
  500.times do
86
86
  vals << rand * 1000000
87
- @mean.add vals.last
87
+ mean.add vals.last
88
88
  vals << rand * 100000
89
89
  m2.add vals.last
90
90
  end
91
- @mean.add(m2)
92
- @mean.count.should == 1000
93
- @mean.mean.should be_within(EPSILON).of(vals.reduce(:+)/vals.size)
91
+ mean.add(m2)
92
+ mean.count.should == 1000
93
+ mean.mean.should be_within(EPSILON).of(vals.reduce(:+)/vals.size)
94
94
  end
95
95
  end
96
96
  end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ module Accumulators
4
+ describe MeanVariance do
5
+ let(:meanvar){MeanVariance.new}
6
+
7
+ context "When creating" do
8
+ it "can be created" do
9
+ lambda{ MeanVariance.new }.should_not raise_error
10
+ end
11
+
12
+ it "returns count,mean,var of 0,0.0,0.0 before anything is added" do
13
+ meanvar.count.should == 0
14
+ meanvar.mean.should be_within(EPSILON).of(0.0)
15
+ meanvar.variance(type: :population).should be_within(EPSILON).of(0.0)
16
+ end
17
+ end
18
+
19
+ context "When adding numbers or distributions" do
20
+ it "allows integers to be added" do
21
+ lambda{ meanvar.add 5 }.should_not raise_error
22
+ end
23
+
24
+ it "allows floats to be added" do
25
+ lambda{ meanvar.add 5.5 }.should_not raise_error
26
+ end
27
+
28
+ it "allows other MeanVar distributions to be added" do
29
+ lambda{ meanvar.add MeanVariance.new }.should_not raise_error
30
+ end
31
+
32
+ it "raises an ArgumentError if a string is added" do
33
+ lambda{ meanvar.add "1.5" }.should raise_error(
34
+ ArgumentError,
35
+ "You may not add String to Accumulators::MeanVariance")
36
+ end
37
+
38
+ it "raises an ArgumentError if a Mean accumulator is added" do
39
+ lambda{ meanvar.add Mean.new }.should raise_error(
40
+ ArgumentError,
41
+ "You may not add Accumulators::Mean to Accumulators::MeanVariance")
42
+ end
43
+
44
+ it "raises an ArgumentError if an unknown type of variance is requested" do
45
+ lambda{ meanvar.variance(type: :unknown) }.should raise_error(
46
+ ArgumentError,
47
+ "type must be one of :sample, :population")
48
+ end
49
+ end
50
+
51
+ context "When checking correctness of biased/population calculations" do
52
+ before do
53
+ @vals = []
54
+ 1000.times do
55
+ @vals << rand * 10000
56
+ meanvar.add @vals.last
57
+ end
58
+ end
59
+
60
+ it "calculates the count and mean correctly for a set of numbers" do
61
+ meanvar.count.should == @vals.size
62
+ meanvar.mean.should be_within(EPSILON).of(@vals.reduce(:+)/@vals.size)
63
+ end
64
+
65
+ it "calculates the population variance and stddev correctly" do
66
+ variance = @vals.map{|v| (v - meanvar.mean)**2}.reduce(:+) / @vals.size
67
+ meanvar.variance(type: :population).should be_within(EPSILON).of(variance)
68
+ meanvar.stddev(type: :population).should be_within(EPSILON).of(Math.sqrt(variance))
69
+ end
70
+
71
+ it "calculates the sample variance and stddev correctly" do
72
+ variance = @vals.map{|v| (v - meanvar.mean)**2}.reduce(:+) / (@vals.size + 1)
73
+ meanvar.variance(type: :sample).should be_within(EPSILON).of(variance)
74
+ meanvar.stddev(type: :sample).should be_within(EPSILON).of(Math.sqrt(variance))
75
+ end
76
+
77
+ it "defaults to sample variance" do
78
+ meanvar.variance.should be_within(EPSILON).of(meanvar.variance(type: :sample))
79
+ end
80
+ end
81
+
82
+ context "When combining MeanVariances" do
83
+ it "combines two MeanVariances correctly" do
84
+ vals = []
85
+ mv2 = MeanVariance.new
86
+ 500.times do
87
+ vals << rand * 10000
88
+ meanvar.add vals.last
89
+ vals << rand * 1000
90
+ mv2.add vals.last
91
+ end
92
+
93
+ meanvar.add(mv2)
94
+
95
+ meanvar.count.should == vals.size
96
+ meanvar.mean.should be_within(EPSILON).of(vals.reduce(:+)/vals.size)
97
+ meanvar.variance(type: :population).should be_within(EPSILON).of(vals.map{|v| (v - meanvar.mean)**2}.reduce(:+) / vals.size)
98
+ end
99
+ end
100
+
101
+ end
102
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: accumulators
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.0
5
+ version: 0.3.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Gavin Heavyside
@@ -99,16 +99,13 @@ files:
99
99
  - Rakefile
100
100
  - VERSION
101
101
  - accumulators.gemspec
102
- - features/accumulators.feature
103
- - features/step_definitions/accumulators_steps.rb
104
- - features/support/env.rb
105
102
  - lib/accumulators.rb
106
103
  - lib/accumulators/count.rb
107
104
  - lib/accumulators/mean.rb
108
- - lib/accumulators/meanvariance.rb
109
- - spec/accumulators/count_spec.rb
110
- - spec/accumulators/mean_spec.rb
111
- - spec/accumulators/meanvariance_spec.rb
105
+ - lib/accumulators/mean_variance.rb
106
+ - spec/lib/accumulators/count_spec.rb
107
+ - spec/lib/accumulators/mean_spec.rb
108
+ - spec/lib/accumulators/mean_variance_spec.rb
112
109
  - spec/spec_helper.rb
113
110
  has_rdoc: true
114
111
  homepage: http://github.com/hgavin/accumulators
@@ -124,7 +121,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
124
121
  requirements:
125
122
  - - ">="
126
123
  - !ruby/object:Gem::Version
127
- hash: -274752833993731131
124
+ hash: -417395174434128828
128
125
  segments:
129
126
  - 0
130
127
  version: "0"
@@ -1,9 +0,0 @@
1
- Feature: something something
2
- In order to something something
3
- A user something something
4
- something something something
5
-
6
- Scenario: something something
7
- Given inspiration
8
- When I create a sweet new gem
9
- Then everyone should see how awesome I am
File without changes
@@ -1,13 +0,0 @@
1
- require 'bundler'
2
- begin
3
- Bundler.setup(:default, :development)
4
- rescue Bundler::BundlerError => e
5
- $stderr.puts e.message
6
- $stderr.puts "Run `bundle install` to install missing gems"
7
- exit e.status_code
8
- end
9
-
10
- $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
11
- require 'accumulators'
12
-
13
- require 'rspec/expectations'
@@ -1,78 +0,0 @@
1
- require 'spec_helper'
2
-
3
-
4
- describe "Accumulators" do
5
- describe "MeanVariance" do
6
- before :each do
7
- @meanvar = Accumulators::MeanVariance.new
8
- end
9
-
10
- context "Creation" do
11
- it "can be created" do
12
- lambda{ Accumulators::MeanVariance.new }.should_not raise_error
13
- end
14
-
15
- it "returns count,mean,var of 0,0.0,0.0 before anything is added" do
16
- @meanvar.count.should == 0
17
- @meanvar.mean.should be_within(EPSILON).of(0.0)
18
- @meanvar.variance.should be_within(EPSILON).of(0.0)
19
- end
20
- end
21
-
22
- context "adding numbers or distributions" do
23
- it "allows integers to be added" do
24
- lambda{ @meanvar.add 5 }.should_not raise_error
25
- end
26
-
27
- it "allows floats to be added" do
28
- lambda{ @meanvar.add 5.5 }.should_not raise_error
29
- end
30
-
31
- it "allows other MeanVar distributions to be added" do
32
- lambda{ @meanvar.add Accumulators::MeanVariance.new }.should_not raise_error
33
- end
34
-
35
- it "raises an ArgumentError if a string is added" do
36
- lambda{ @meanvar.add "1.5" }.should raise_error(ArgumentError)
37
- end
38
-
39
- it "raises an ArgumentError if a Mean accumulator is added" do
40
- lambda{ @meanvar.add Accumulators::Mean.new }.should raise_error(ArgumentError)
41
- end
42
- end
43
-
44
- context "correctness of calcs when adding numbers" do
45
- it "should calculate the mean and variance correctly for a set of numbers" do
46
- vals = []
47
- 1000.times do
48
- vals << rand * 10000
49
- @meanvar.add vals.last
50
- end
51
-
52
- @meanvar.count.should == vals.size
53
- @meanvar.mean.should be_within(EPSILON).of(vals.reduce(:+)/vals.size)
54
- @meanvar.variance.should be_within(EPSILON).of(vals.map{|v| (v - @meanvar.mean)**2}.reduce(:+) / vals.size)
55
- end
56
- end
57
-
58
- context "correctness of calcs when adding MeanVariance accumulators" do
59
- it "should combine two MeanVariances correctly" do
60
- vals = []
61
- mv2 = Accumulators::MeanVariance.new
62
- 500.times do
63
- vals << rand * 10000
64
- @meanvar.add vals.last
65
- vals << rand * 1000
66
- mv2.add vals.last
67
- end
68
-
69
- @meanvar.add(mv2)
70
-
71
- @meanvar.count.should == vals.size
72
- @meanvar.mean.should be_within(EPSILON).of(vals.reduce(:+)/vals.size)
73
- @meanvar.variance.should be_within(EPSILON).of(vals.map{|v| (v - @meanvar.mean)**2}.reduce(:+) / vals.size)
74
- end
75
- end
76
-
77
- end
78
- end