flash_math 0.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.
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