flash_math 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +17 -0
  4. data/.rspec +4 -0
  5. data/.travis.yml +13 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +187 -0
  9. data/Rakefile +6 -0
  10. data/flash_math.gemspec +27 -0
  11. data/lib/flash_math.rb +3 -0
  12. data/lib/flash_math/modules/geometry.rb +10 -0
  13. data/lib/flash_math/modules/geometry/geometric_bounding_box.rb +16 -0
  14. data/lib/flash_math/modules/geometry/geometric_distance.rb +20 -0
  15. data/lib/flash_math/modules/geometry/geometric_line.rb +87 -0
  16. data/lib/flash_math/modules/geometry/geometric_point.rb +19 -0
  17. data/lib/flash_math/modules/geometry/geometric_point_in_polygon.rb +63 -0
  18. data/lib/flash_math/modules/geometry/geometric_polygon.rb +36 -0
  19. data/lib/flash_math/modules/geometry/geometric_segment.rb +128 -0
  20. data/lib/flash_math/modules/geometry/geometric_vector.rb +46 -0
  21. data/lib/flash_math/modules/statistics.rb +1 -0
  22. data/lib/flash_math/modules/statistics/statistical_spread.rb +129 -0
  23. data/lib/flash_math/version.rb +3 -0
  24. data/spec/lib/geometry/geometric_bounding_box_spec.rb +67 -0
  25. data/spec/lib/geometry/geometric_distance_spec.rb +55 -0
  26. data/spec/lib/geometry/geometric_line_spec.rb +287 -0
  27. data/spec/lib/geometry/geometric_point_spec.rb +53 -0
  28. data/spec/lib/geometry/geometric_polygon_spec.rb +148 -0
  29. data/spec/lib/geometry/geometric_segment_spec.rb +231 -0
  30. data/spec/lib/geometry/geometric_vector_spec.rb +110 -0
  31. data/spec/lib/statistics/statistics_spread_spec.rb +219 -0
  32. data/spec/spec_helper.rb +4 -0
  33. metadata +168 -0
@@ -0,0 +1,231 @@
1
+ require 'spec_helper'
2
+
3
+ describe GeometricSegment do
4
+
5
+ describe '#initialize_by_points' do
6
+ point1 = GeometricPoint.new(1, 2)
7
+ point2 = GeometricPoint.new(3, 4)
8
+ segment = GeometricSegment.new(point1, point2)
9
+
10
+ it 'to be equal' do
11
+ expect(segment.point1).to eq(point1)
12
+ expect(segment.point2).to eq(point2)
13
+ end
14
+
15
+ it 'to be not equal' do
16
+ expect(segment.point1).not_to eq(point2)
17
+ expect(segment.point2).not_to eq(point1)
18
+ end
19
+ end
20
+
21
+ describe '#initialize_by_arrays' do
22
+ point1 = GeometricPoint.new(1, 2)
23
+ point2 = GeometricPoint.new(3, 4)
24
+ segment = GeometricSegment.new_by_arrays([1, 2], [3, 4])
25
+
26
+ it 'to be equal' do
27
+ expect(segment.point1).to eq(point1)
28
+ expect(segment.point2).to eq(point2)
29
+ end
30
+
31
+ it 'to be not equal' do
32
+ expect(segment.point1).not_to eq(point2)
33
+ expect(segment.point2).not_to eq(point1)
34
+ end
35
+ end
36
+
37
+ describe '#bounds' do
38
+ point1 = GeometricPoint.new(1, 1)
39
+ point2 = GeometricPoint.new(2, 2)
40
+ segment = GeometricSegment.new(point1, point2)
41
+
42
+ it 'to be the bottommost point' do
43
+ expect(segment.bottommost_endpoint).to eq(point1)
44
+ end
45
+
46
+ it 'to be the leftmost point' do
47
+ expect(segment.leftmost_endpoint).to eq(point1)
48
+ end
49
+
50
+ it 'to be the rightmost point' do
51
+ expect(segment.rightmost_endpoint).to eq(point2)
52
+ end
53
+
54
+ it 'to be the topmost point' do
55
+ expect(segment.topmost_endpoint).to eq(point2)
56
+ end
57
+ end
58
+
59
+ describe '#contains_point?' do
60
+ it 'to be belongs to horizontal segment' do
61
+ expect(GeometricSegment.new_by_arrays([2, 1], [4, 1]).contains_point?(GeometricPoint.new(3, 1))).to eq(true)
62
+ end
63
+
64
+ it 'to be belongs to inclined segment' do
65
+ expect(GeometricSegment.new_by_arrays([2, 2], [4, 4]).contains_point?(GeometricPoint.new(3, 3))).to eq(true)
66
+ end
67
+
68
+ it 'to be is segment endpoint' do
69
+ expect(GeometricSegment.new_by_arrays([2, 1], [4, 1]).contains_point?(GeometricPoint.new(2, 1))).to eq(true)
70
+ end
71
+
72
+ it 'to be not belonging to segment' do
73
+ expect(GeometricSegment.new_by_arrays([2, 1], [4, 1]).contains_point?(GeometricPoint.new(2, 3))).to eq(false)
74
+ end
75
+
76
+ it 'to be on same horizontal line' do
77
+ expect(GeometricSegment.new_by_arrays([2, 1], [4, 1]).contains_point?(GeometricPoint.new(1, 1))).to eq(false)
78
+ end
79
+
80
+ it 'to be on same inclined line' do
81
+ expect(GeometricSegment.new_by_arrays([2, 2], [4, 4]).contains_point?(GeometricPoint.new(1, 1))).to eq(false)
82
+ end
83
+ end
84
+
85
+ describe '#distance_to' do
86
+ it 'to be distance to point on segment' do
87
+ expect(GeometricSegment.new_by_arrays([0, 2], [2, 0]).distance_to(GeometricPoint.new(1, 1))).to eq(0)
88
+ end
89
+
90
+ it 'to be distance to flat segment' do
91
+ expect(GeometricSegment.new_by_arrays([0, 1], [2, 1]).distance_to(GeometricPoint.new(1, 2))).to eq(1)
92
+ end
93
+
94
+ it 'to be distance to segment start' do
95
+ expect(GeometricSegment.new_by_arrays([1, 1], [2, 1]).distance_to(GeometricPoint.new(0, 1))).to eq(1)
96
+ end
97
+
98
+ it 'to be distance to segment end' do
99
+ expect(GeometricSegment.new_by_arrays([0, 1], [0, 2]).distance_to(GeometricPoint.new(0, 3))).to eq(1)
100
+ end
101
+ end
102
+
103
+ describe '#intersection_point_with' do
104
+ it 'to be regular case' do
105
+ expect(GeometricSegment.new_by_arrays([0, 0], [2, 2]).intersection_point_with(GeometricSegment.new_by_arrays([0, 2], [2, 0]))).to eq(GeometricPoint.new(1, 1))
106
+ end
107
+
108
+ it 'to be intersected at the endpoint' do
109
+ expect(GeometricSegment.new_by_arrays([0, 0], [2, 2]).intersection_point_with(GeometricSegment.new_by_arrays([0, 2], [2, 2]))).to eq(GeometricPoint.new(2, 2))
110
+ end
111
+ end
112
+
113
+ describe '#intersects_with?' do
114
+ it 'to be segments intersect' do
115
+ expect(GeometricSegment.new_by_arrays([0, 0], [2, 0]).intersects_with?(GeometricSegment.new_by_arrays([1, 1], [1, -1]))).to eq(true)
116
+ end
117
+
118
+ it 'to be segments does not intersect but lay on intersecting lines' do
119
+ expect(GeometricSegment.new_by_arrays([0, 0], [0, 2]).intersects_with?(GeometricSegment.new_by_arrays([1, 1], [3, 1]))).to eq(false)
120
+ end
121
+
122
+ it 'to be segments does not intersect but line contains end point' do
123
+ expect(GeometricSegment.new_by_arrays([0, 0], [0, 2]).intersects_with?(GeometricSegment.new_by_arrays([1, 0], [3, 0]))).to eq(false)
124
+ end
125
+
126
+ it 'to be segment contains endpoint' do
127
+ expect(GeometricSegment.new_by_arrays([0, 0], [2, 2]).intersects_with?(GeometricSegment.new_by_arrays([0, 0], [2, 0]))).to eq(true)
128
+ end
129
+
130
+ it 'to be segments parralel' do
131
+ expect(GeometricSegment.new_by_arrays([0, 1], [2, 1]).intersects_with?(GeometricSegment.new_by_arrays([0, 0], [2, 0]))).to eq(false)
132
+ end
133
+
134
+ it 'to be segments parallel and have common endpoint' do
135
+ expect(GeometricSegment.new_by_arrays([0, 0], [1, 0]).intersects_with?(GeometricSegment.new_by_arrays([1, 0], [2, 0]))).to eq(true)
136
+ end
137
+
138
+ it 'to be segments overlap' do
139
+ expect(GeometricSegment.new_by_arrays([0, 0], [2, 0]).intersects_with?(GeometricSegment.new_by_arrays([1, 0], [3, 0]))).to eq(true)
140
+ end
141
+
142
+ it 'to be segments overlap on vertical line' do
143
+ expect(GeometricSegment.new_by_arrays([0, 0], [0, 2]).intersects_with?(GeometricSegment.new_by_arrays([0, 1], [0, 3]))).to eq(true)
144
+ end
145
+
146
+ it 'to be segments lie on one line' do
147
+ expect(GeometricSegment.new_by_arrays([0, 0], [1, 0]).intersects_with?(GeometricSegment.new_by_arrays([2, 0], [3, 0]))).to eq(false)
148
+ end
149
+
150
+ it 'to be segments lie on one vertical line' do
151
+ expect(GeometricSegment.new_by_arrays([0, 0], [0, 1]).intersects_with?(GeometricSegment.new_by_arrays([0, 2], [0, 3]))).to eq(false)
152
+ end
153
+ end
154
+
155
+ describe '#length' do
156
+ it 'to be parallel to axis' do
157
+ expect(GeometricSegment.new_by_arrays([1, 1], [1, 2]).length).to eq(1)
158
+ expect(GeometricSegment.new_by_arrays([1, 1], [2, 1]).length).to eq(1)
159
+ end
160
+
161
+ it 'to be inclined' do
162
+ expect(GeometricSegment.new_by_arrays([1, 1], [2, 2]).length).to eq(Math.sqrt(2))
163
+ end
164
+ end
165
+
166
+ describe '#lies_on_one_line_with?' do
167
+ it 'to be parralel but on different lines' do
168
+ expect(GeometricSegment.new_by_arrays([0, 1], [2, 1]).lies_on_one_line_with?(GeometricSegment.new_by_arrays([0, 0], [2, 0]))).to eq(false)
169
+ end
170
+
171
+ it 'to be not parralel' do
172
+ expect(GeometricSegment.new_by_arrays([0, 0], [2, 0]).lies_on_one_line_with?(GeometricSegment.new_by_arrays([0, 1], [2, 2]))).to eq(false)
173
+ end
174
+
175
+ it 'to be segment that lies on one horizontal line' do
176
+ expect(GeometricSegment.new_by_arrays([0, 0], [1, 0]).lies_on_one_line_with?(GeometricSegment.new_by_arrays([2, 0], [3, 0]))).to eq(true)
177
+ end
178
+
179
+ it 'to be segment that lies on one vertical line' do
180
+ expect(GeometricSegment.new_by_arrays([0, 0], [0, 1]).lies_on_one_line_with?(GeometricSegment.new_by_arrays([0, 2], [0, 3]))).to eq(true)
181
+ end
182
+ end
183
+
184
+ describe '#overlaps?' do
185
+ it 'to be overlaped' do
186
+ expect(GeometricSegment.new_by_arrays([0, 0], [2, 0]).overlaps?(GeometricSegment.new_by_arrays([1, 0], [3, 0]))).to eq(true)
187
+ end
188
+
189
+ it 'to be overlapes same segment' do
190
+ expect(GeometricSegment.new_by_arrays([0, 0], [2, 0]).overlaps?(GeometricSegment.new_by_arrays([0, 0], [2, 0]))).to eq(true)
191
+ end
192
+
193
+ it 'to be overlap intersects on one point' do
194
+ expect(GeometricSegment.new_by_arrays([0, 0], [1, 0]).overlaps?(GeometricSegment.new_by_arrays([1, 0], [1, 1]))).to eq(false)
195
+ end
196
+
197
+ it 'to be overlap lies on one horizontal line' do
198
+ expect(GeometricSegment.new_by_arrays([0, 0], [2, 0]).overlaps?(GeometricSegment.new_by_arrays([4, 0], [6, 0]))).to eq(false)
199
+ end
200
+
201
+ it 'to be overlap lies on one vertical line' do
202
+ expect(GeometricSegment.new_by_arrays([0, 0], [0, 1]).overlaps?(GeometricSegment.new_by_arrays([0, 2], [0, 3]))).to eq(false)
203
+ end
204
+ end
205
+
206
+ describe '#parallel_to?' do
207
+ it 'to be parallel' do
208
+ expect(GeometricSegment.new_by_arrays([0, 0], [2, 1]).parallel_to?(GeometricSegment.new_by_arrays([1, 1], [5, 3]))).to eq(true)
209
+ end
210
+
211
+ it 'to be not parallel' do
212
+ expect(GeometricSegment.new_by_arrays([0, 0], [2, 1]).parallel_to?(GeometricSegment.new_by_arrays([1, 1], [2, 2]))).to eq(false)
213
+ end
214
+
215
+ it 'to be lays on the same line' do
216
+ expect(GeometricSegment.new_by_arrays([0, 0], [1, 1]).parallel_to?(GeometricSegment.new_by_arrays([2, 2], [3, 3]))).to eq(true)
217
+ end
218
+ end
219
+
220
+ describe '#to_vector' do
221
+ it 'to be parallel' do
222
+ expect(GeometricSegment.new_by_arrays([1, 1], [3, 2]).to_vector).to eq(GeometricVector.new(2, 1))
223
+ end
224
+
225
+ it 'to be not parallel' do
226
+ expect(GeometricSegment.new_by_arrays([1, 1], [2, 2]).to_vector).to eq(GeometricVector.new(1, 1))
227
+ expect(GeometricSegment.new_by_arrays([2, 2], [1, 1]).to_vector).to eq(GeometricVector.new(-1, -1))
228
+ end
229
+ end
230
+
231
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+
3
+ describe GeometricVector do
4
+ describe '#initialize_by_numbers' do
5
+ vector = GeometricVector.new(1, 2)
6
+
7
+ it 'to be equal' do
8
+ expect(vector.x).to eq(1)
9
+ expect(vector.y).to eq(2)
10
+ end
11
+
12
+ it 'to be not equal' do
13
+ expect(vector.x).not_to eq(3)
14
+ expect(vector.y).not_to eq(3)
15
+ end
16
+ end
17
+
18
+ describe '#initialize_by_array' do
19
+ vector = GeometricVector.new_by_array([1, 2])
20
+
21
+ it 'to be equal' do
22
+ expect(vector.x).to eq(1)
23
+ expect(vector.y).to eq(2)
24
+ end
25
+
26
+ it 'to be not equal' do
27
+ expect(vector.x).not_to eq(3)
28
+ expect(vector.y).not_to eq(3)
29
+ end
30
+ end
31
+
32
+ describe '#+' do
33
+ it 'to be the addition of two vectors' do
34
+ expect(GeometricVector.new(1, 2) + GeometricVector.new(3, 4)).to eq(GeometricVector.new(4, 6))
35
+ end
36
+ end
37
+
38
+ describe '#-' do
39
+ it 'to be subtraction of two vectors' do
40
+ expect(GeometricVector.new(1, 0) - GeometricVector.new(3, 4)).to eq(GeometricVector.new(-2, -4))
41
+ end
42
+ end
43
+
44
+ describe '#*' do
45
+ it 'to be multipal of a point by scalar' do
46
+ expect(GeometricVector.new(1, 2) * -2).to eq(GeometricVector.new(-2, -4))
47
+ end
48
+
49
+ it 'to be multipal of a point by vector' do
50
+ expect(-2 * GeometricVector.new(1, 2)).to eq(GeometricVector.new(-2, -4))
51
+ end
52
+ end
53
+
54
+ describe '#collinear_with?' do
55
+ it 'to be collinear' do
56
+ expect(GeometricVector.new(1, 2).collinear_with?GeometricVector.new(2, 4)).to eq(true)
57
+ end
58
+
59
+ it 'to be not collinear' do
60
+ expect(GeometricVector.new(1, 2).collinear_with?GeometricVector.new(1, 1)).to eq(false)
61
+ end
62
+
63
+ it 'to be oppositely directed' do
64
+ expect(GeometricVector.new(2, 2).collinear_with?GeometricVector.new(-2, -2)).to eq(true)
65
+ end
66
+ end
67
+
68
+ describe '#cross_product' do
69
+ it 'to be positive' do
70
+ expect(GeometricVector.new(1, 0).cross_product(GeometricVector.new(0, 1))).to eq(1)
71
+ end
72
+
73
+ it 'to be negative' do
74
+ expect(GeometricVector.new(0, 1).cross_product(GeometricVector.new(1, 0))).to eq(-1)
75
+ end
76
+
77
+ it 'to be zero' do
78
+ expect(GeometricVector.new(1, 1).cross_product(GeometricVector.new(-2, -2))).to eq(0)
79
+ end
80
+
81
+ it 'to be unnormalized' do
82
+ expect(GeometricVector.new(1, 1).cross_product(GeometricVector.new(-2, 2))).to eq(4)
83
+ end
84
+ end
85
+
86
+ describe '#scalar_product' do
87
+ it 'to be perpendicular' do
88
+ expect(GeometricVector.new(1, 1).scalar_product(GeometricVector.new(-1, 1))).to eq(0)
89
+ end
90
+
91
+ it 'to be collinear' do
92
+ expect(GeometricVector.new(1, 1).scalar_product(GeometricVector.new(-2, -2))).to eq(-4)
93
+ end
94
+
95
+ it 'to be inclined' do
96
+ expect(GeometricVector.new(1, 1).scalar_product(GeometricVector.new(0, 1))).to eq(1)
97
+ end
98
+ end
99
+
100
+ describe '#modulus' do
101
+ it 'to be parallel to axis' do
102
+ expect(GeometricVector.new(0, 1).modulus).to eq(1)
103
+ expect(GeometricVector.new(1, 0).modulus).to eq(1)
104
+ end
105
+
106
+ it 'to be inclined' do
107
+ expect(GeometricVector.new(1, 1).modulus).to eq(1.4142135623730951)
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,219 @@
1
+ require 'spec_helper'
2
+
3
+ describe StatisticalSpread do
4
+ describe '#sum' do
5
+ it 'to be the sum of array values' do
6
+ expect(StatisticalSpread.new([1,2,6]).sum).to eq(9)
7
+ end
8
+
9
+ it 'to be a block passed' do
10
+ expect(StatisticalSpread.new([1,2,6]).sum{ |x| x * 2 }).to eq(18)
11
+ end
12
+
13
+ it 'to be 0 if empty' do
14
+ expect(StatisticalSpread.new([]).sum).to eq(0)
15
+ end
16
+ end
17
+
18
+ describe "#mean" do
19
+ it "to be the sum of array values divided by number of array values" do
20
+ expect(StatisticalSpread.new([1,2,6]).mean).to eq(3)
21
+ end
22
+
23
+ it "to be nil if empty" do
24
+ expect(StatisticalSpread.new([]).mean).to be_nil
25
+ end
26
+ end
27
+
28
+ describe '#median' do
29
+ it 'to be the value lying at the midpoint of the array' do
30
+ expect(StatisticalSpread.new([1,2,6]).median).to eq(2)
31
+ end
32
+
33
+ it 'to be the mean of the two midpoint values if the array length is even' do
34
+ expect(StatisticalSpread.new([1,2,3,6]).median).to eq(2.5)
35
+ end
36
+
37
+ it 'to be nil if empty' do
38
+ expect(StatisticalSpread.new([]).median).to be_nil
39
+ end
40
+ end
41
+
42
+ describe '#mode' do
43
+ it 'to be the most frequent value' do
44
+ expect(StatisticalSpread.new([1,1,2,46]).mode).to eq(1)
45
+ end
46
+
47
+ it 'to be the first value if there is only one' do
48
+ expect(StatisticalSpread.new([3.5]).mode).to eq(3.5)
49
+ end
50
+
51
+ it 'to be nil if nil if there is no most frequent value' do
52
+ expect(StatisticalSpread.new([1,2,3]).mode).to be_nil
53
+ end
54
+
55
+ it 'to be nil if empty' do
56
+ expect(StatisticalSpread.new([]).mode).to be_nil
57
+ end
58
+ end
59
+
60
+ describe '#range' do
61
+ it 'to be the mean squared deviation of the sample (n - 1 denominator)' do
62
+ expect(StatisticalSpread.new([1,2,6]).range).to eq(5)
63
+ end
64
+
65
+ it 'to be nil if empty' do
66
+ expect(StatisticalSpread.new([]).range).to be_nil
67
+ end
68
+ end
69
+
70
+ describe '#max' do
71
+ it 'to be the highest value' do
72
+ expect(StatisticalSpread.new([1,2,6]).max).to eq(6)
73
+ end
74
+
75
+ it 'to be nil if empty' do
76
+ expect(StatisticalSpread.new([]).max).to be_nil
77
+ end
78
+ end
79
+
80
+ describe '#min' do
81
+ it 'to be the lowest value' do
82
+ expect(StatisticalSpread.new([1,2,6]).min).to eq(1)
83
+ end
84
+
85
+ it 'to be nil if empty' do
86
+ expect(StatisticalSpread.new([]).min).to be_nil
87
+ end
88
+ end
89
+
90
+ describe '#percentile_from_value' do
91
+ it 'to be the precise percentile of each value' do
92
+ data = [95.1772, 95.1567, 95.1937, 95.1959, 95.1442, 95.061, 95.1591, 95.1195,95.1065, 95.0925, 95.199, 95.1682]
93
+ percentiles = [0,9,17,25,34,42,50,59,67,75,84,92]
94
+ stats = StatisticalSpread.new(data)
95
+ data.sort.each_with_index do |datum, i|
96
+ expect(stats.percentile_from_value(datum)).to eq(percentiles[i])
97
+ end
98
+ end
99
+
100
+ it 'to be nil if empty' do
101
+ expect(StatisticalSpread.new([]).percentile_from_value(1)).to be_nil
102
+ end
103
+ end
104
+
105
+ describe '#value_from_percentile' do
106
+ it 'to be the precise percentile of each value' do
107
+ data = [95.1772, 95.1567, 95.1937, 95.1959, 95.1442, 95.061, 95.1591, 95.1195,95.1065, 95.0925, 95.199, 95.1682]
108
+ percentiles = [0,10,20,30,40,50,60,70,80,90]
109
+ values = [95.061,95.1065,95.1195,95.1442,95.1567,95.1591,95.1772,95.1937,95.1959,95.199]
110
+ stats = StatisticalSpread.new(data)
111
+ percentiles.sort.each_with_index do |percentile, i|
112
+ expect(stats.value_from_percentile(percentile)).to eq(values[i])
113
+ end
114
+ end
115
+
116
+ it 'to be nil if empty' do
117
+ expect(StatisticalSpread.new([]).value_from_percentile(1)).to be_nil
118
+ end
119
+ end
120
+
121
+ describe '#variance' do
122
+ it 'to be the mean squared deviation of the sample (n - 1 denominator)' do
123
+ expect(StatisticalSpread.new([1,2,6]).variance).to eq(7)
124
+ end
125
+
126
+ it 'to be nil if empty' do
127
+ expect(StatisticalSpread.new([]).variance).to be_nil
128
+ end
129
+ end
130
+
131
+ describe '#population_variance' do
132
+ it 'to be the mean squared deviation of the sample' do
133
+ expect(StatisticalSpread.new([1,2,3,4]).population_variance).to eq(1.25)
134
+ end
135
+
136
+ it 'to be nil if empty' do
137
+ expect(StatisticalSpread.new([]).population_variance).to be_nil
138
+ end
139
+ end
140
+
141
+ describe '#standard_deviation' do
142
+ it 'to be the square root of the #variance' do
143
+ expect(StatisticalSpread.new([1,2,6]).standard_deviation).to eq(2.6457513110645907)
144
+ end
145
+
146
+ it 'to be nil for single element arrays' do
147
+ expect(StatisticalSpread.new([1]).standard_deviation).to be_nil
148
+ end
149
+
150
+ it 'to be nil if empty' do
151
+ expect(StatisticalSpread.new([]).standard_deviation).to be_nil
152
+ end
153
+ end
154
+
155
+ describe '#relative_standard_deviation' do
156
+ it 'to be 0 for constant values' do
157
+ expect(StatisticalSpread.new([100,100,100]).relative_standard_deviation).to eq(0)
158
+ end
159
+
160
+ it 'to be the #population_standard_deviation divided by the mean * 100' do
161
+ expect(StatisticalSpread.new([90,100,110]).relative_standard_deviation).to be_within(0.01).of(8.16)
162
+ expect(StatisticalSpread.new([1,5,6,8,10,40,65,88]).relative_standard_deviation).to be_within(0.01).of(110.41)
163
+ end
164
+
165
+ it 'to be nil if empty' do
166
+ expect(StatisticalSpread.new([]).relative_standard_deviation).to be_nil
167
+ end
168
+ end
169
+
170
+ describe '#population_standard_deviation' do
171
+ it 'to be the square root of the #population_variance' do
172
+ expect(StatisticalSpread.new([1,2,6]).population_standard_deviation).to eq(2.160246899469287)
173
+ end
174
+
175
+ it 'to be 0 for single element arrays' do
176
+ expect(StatisticalSpread.new([1]).population_standard_deviation).to eq(0)
177
+ end
178
+
179
+ it 'to be nil if empty' do
180
+ expect(StatisticalSpread.new([]).population_standard_deviation).to be_nil
181
+ end
182
+ end
183
+
184
+ describe '#skewness' do
185
+ it 'to be the measure of skewness of the data as close to 0 when not skewed' do
186
+ expect(StatisticalSpread.new([1,3,5,3,1]).skewness).to eq(0.30734449954312965)
187
+ end
188
+
189
+ it 'to be the measure of skewness of the data as high when skewed' do
190
+ expect(StatisticalSpread.new([50,10,1,1,1]).skewness).to eq(1.2374536958450908)
191
+ end
192
+
193
+ it 'to be 0 if only one element' do
194
+ expect(StatisticalSpread.new([1]).skewness).to eq(0)
195
+ end
196
+
197
+ it 'to be nil if empty' do
198
+ expect(StatisticalSpread.new([]).skewness).to be_nil
199
+ end
200
+ end
201
+
202
+ describe '#kurtosis' do
203
+ it 'to be the measure of kurtosis of the data as close to 0 when not skewed' do
204
+ expect(StatisticalSpread.new([1,3,5,3,1]).kurtosis).to eq(1.477551020408163)
205
+ end
206
+
207
+ it 'to be the measure of skewness of the data as high when skewed' do
208
+ expect(StatisticalSpread.new([99,10,1,1,1]).kurtosis).to eq(2.56586117539186)
209
+ end
210
+
211
+ it 'to be 0 if only one element' do
212
+ expect(StatisticalSpread.new([1]).kurtosis).to eq(0)
213
+ end
214
+
215
+ it 'to be nil if empty' do
216
+ expect(StatisticalSpread.new([]).kurtosis).to be_nil
217
+ end
218
+ end
219
+ end