ruby_native_statistics 0.8.2 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +1 -1
- data/.vscode/c_cpp_properties.json +21 -0
- data/README.md +6 -2
- data/Rakefile +1 -1
- data/changelog.md +4 -0
- data/ext/mathematics/mathematics.c +84 -7
- data/ext/mathematics/mathematics.h +1 -0
- data/lib/ruby_native_statistics/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b99d6ace1e36cdd53315356b8c4de080289a46bc307b41bc1979de4cbaff2e42
|
4
|
+
data.tar.gz: 5b8c3498b2a3014313b0b249eb87350e7f07e5a22237de4ea9e95f67096572c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c837f3f6f7e2a8d47291d1e289d09e48de81c5216bca319e1be24aca7a821f0ba8e1acd3548ccfbe83a50b92752af5dc281a9a69dc052e58cee1f5e49b05e06d
|
7
|
+
data.tar.gz: 3c8e3629ffe57bccdbdeaa8b792d593aa89bdce401e034a2a0d08fdf62fb1ad0841229cc60c222aaa37fe0895c2fdee83109176ec553e0c1529c33814868fa4e
|
data/.github/workflows/main.yml
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
{
|
2
|
+
"configurations": [
|
3
|
+
{
|
4
|
+
"name": "Mac",
|
5
|
+
"includePath": [
|
6
|
+
"${workspaceFolder}/**",
|
7
|
+
"/Users/corybuecker/.asdf/installs/ruby/2.7.0/include/ruby-2.7.0",
|
8
|
+
"/Users/corybuecker/.asdf/installs/ruby/2.7.0/include/ruby-2.7.0/x86_64-darwin19"
|
9
|
+
],
|
10
|
+
"defines": [],
|
11
|
+
"macFrameworkPath": [
|
12
|
+
"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks"
|
13
|
+
],
|
14
|
+
"compilerPath": "/usr/bin/clang",
|
15
|
+
"cStandard": "c11",
|
16
|
+
"cppStandard": "c++17",
|
17
|
+
"intelliSenseMode": "clang-x64"
|
18
|
+
}
|
19
|
+
],
|
20
|
+
"version": 4
|
21
|
+
}
|
data/README.md
CHANGED
@@ -6,11 +6,12 @@ This is a native extension to Ruby that adds native (C) statistical functions to
|
|
6
6
|
- [Population Standard Deviation](https://en.wikipedia.org/wiki/Standard_deviation#Uncorrected_sample_standard_deviation) (stdevp)
|
7
7
|
- [Sample Variance](https://en.wikipedia.org/wiki/Variance#Population_variance_and_sample_variance) (var)
|
8
8
|
- [Population Variance](https://en.wikipedia.org/wiki/Variance#Population_variance_and_sample_variance) (varp)
|
9
|
+
- [Median](https://en.wikipedia.org/wiki/Median) (median)
|
9
10
|
- [Mean](https://en.wikipedia.org/wiki/Arithmetic_mean) (mean)
|
10
11
|
|
11
|
-
Check the
|
12
|
+
Check the Github Actions build to see the currently supported versions of Ruby. This list will match whatever stable versions are specified at https://www.ruby-lang.org/en/downloads/.
|
12
13
|
|
13
|
-
It is much more performant than calculating the standard deviation with pure Ruby. For a comparison, run the benchmarks with rake
|
14
|
+
It is much more performant than calculating the standard deviation with pure Ruby. For a comparison, run the benchmarks with `rake benchmark`.
|
14
15
|
|
15
16
|
bench_native_dispersion 0.000425 0.000341 0.000420 0.000324 0.000319
|
16
17
|
bench_ruby_dispersion 0.002168 0.002156 0.002148 0.002149 0.002151
|
@@ -29,6 +30,9 @@ It is much more performant than calculating the standard deviation with pure Rub
|
|
29
30
|
# calculate mean
|
30
31
|
p r.mean
|
31
32
|
|
33
|
+
# calculate median
|
34
|
+
p r.median
|
35
|
+
|
32
36
|
## Links
|
33
37
|
|
34
38
|
This is the third version of this gem, and it is a total rewrite of a SWIG-based design. Lots of thanks to the following resources:
|
data/Rakefile
CHANGED
@@ -15,7 +15,7 @@ Rake::TestTask.new(:test) do |t|
|
|
15
15
|
t.test_files = FileList["test/**/*_test.rb"]
|
16
16
|
end
|
17
17
|
|
18
|
-
Rake::TestTask.new(:
|
18
|
+
Rake::TestTask.new(benchmark: :compile) do |t|
|
19
19
|
t.libs << "test"
|
20
20
|
t.libs << "lib"
|
21
21
|
t.test_files = FileList["test/**/*_benchmark.rb"]
|
data/changelog.md
CHANGED
@@ -1,17 +1,22 @@
|
|
1
|
+
#include "stdbool.h"
|
1
2
|
#include "ruby.h"
|
2
3
|
#include "mathematics.h"
|
3
4
|
|
4
|
-
void Init_mathematics()
|
5
|
+
void Init_mathematics()
|
6
|
+
{
|
5
7
|
MathematicsModule = rb_define_module("Mathematics");
|
6
8
|
rb_define_method(MathematicsModule, "mean", rb_mean, 0);
|
9
|
+
rb_define_method(MathematicsModule, "median", rb_median, 0);
|
7
10
|
}
|
8
11
|
|
9
|
-
double calculate_mean(VALUE array, unsigned long array_length)
|
12
|
+
double calculate_mean(VALUE array, unsigned long array_length)
|
13
|
+
{
|
10
14
|
unsigned long i;
|
11
15
|
double total = 0;
|
12
16
|
double mean = 0;
|
13
17
|
|
14
|
-
for(i = 0; i < array_length; i++)
|
18
|
+
for (i = 0; i < array_length; i++)
|
19
|
+
{
|
15
20
|
total += rb_num2dbl(rb_ary_entry(array, i));
|
16
21
|
}
|
17
22
|
|
@@ -20,31 +25,103 @@ double calculate_mean(VALUE array, unsigned long array_length){
|
|
20
25
|
return mean;
|
21
26
|
}
|
22
27
|
|
23
|
-
double calculate_total_distance_from_mean(VALUE array, unsigned long array_length)
|
28
|
+
double calculate_total_distance_from_mean(VALUE array, unsigned long array_length)
|
29
|
+
{
|
24
30
|
unsigned long i;
|
25
31
|
double mean = 0;
|
26
32
|
double total_distance_from_mean = 0;
|
27
33
|
|
28
34
|
mean = calculate_mean(array, array_length);
|
29
35
|
|
30
|
-
for(i = 0; i < array_length; i++)
|
36
|
+
for (i = 0; i < array_length; i++)
|
37
|
+
{
|
31
38
|
total_distance_from_mean += pow((rb_num2dbl(rb_ary_entry(array, i)) - mean), 2);
|
32
39
|
}
|
33
40
|
|
34
41
|
return total_distance_from_mean;
|
35
42
|
}
|
36
43
|
|
37
|
-
VALUE rb_mean(VALUE self)
|
44
|
+
VALUE rb_mean(VALUE self)
|
45
|
+
{
|
38
46
|
unsigned int array_length;
|
39
47
|
|
40
48
|
Check_Type(self, T_ARRAY);
|
41
49
|
|
42
50
|
array_length = rb_long2int(RARRAY_LEN(self));
|
43
51
|
|
44
|
-
if (array_length <= 0)
|
52
|
+
if (array_length <= 0)
|
53
|
+
{
|
45
54
|
rb_raise(rb_eRangeError, "array must have at least one element");
|
46
55
|
}
|
47
56
|
|
48
57
|
return DBL2NUM(calculate_mean(self, array_length));
|
49
58
|
}
|
50
59
|
|
60
|
+
int compare_doubles(const void *a, const void *b)
|
61
|
+
{
|
62
|
+
double *dbl_a = (double *)a;
|
63
|
+
double *dbl_b = (double *)b;
|
64
|
+
|
65
|
+
double cmp_a = *dbl_a;
|
66
|
+
double cmp_b = *dbl_b;
|
67
|
+
|
68
|
+
return (cmp_a - cmp_b);
|
69
|
+
}
|
70
|
+
|
71
|
+
VALUE rb_median(VALUE self)
|
72
|
+
{
|
73
|
+
unsigned long array_length;
|
74
|
+
unsigned long i;
|
75
|
+
double *working_array;
|
76
|
+
VALUE result;
|
77
|
+
|
78
|
+
Check_Type(self, T_ARRAY);
|
79
|
+
|
80
|
+
array_length = RARRAY_LEN(self);
|
81
|
+
|
82
|
+
if (array_length <= 0)
|
83
|
+
{
|
84
|
+
rb_raise(rb_eRangeError, "array must have at least one element");
|
85
|
+
}
|
86
|
+
|
87
|
+
bool array_even_size = (array_length % 2) == 0;
|
88
|
+
unsigned long middle = (long)floor(array_length / 2.0);
|
89
|
+
|
90
|
+
working_array = malloc(array_length * sizeof(double));
|
91
|
+
|
92
|
+
if (working_array == NULL)
|
93
|
+
{
|
94
|
+
rb_raise(rb_eStandardError, "unknown problem calculating median (possibly array is too large)");
|
95
|
+
}
|
96
|
+
|
97
|
+
for (i = 0; i < array_length; i++)
|
98
|
+
{
|
99
|
+
VALUE item = rb_ary_entry(self, i);
|
100
|
+
|
101
|
+
if (!RB_INTEGER_TYPE_P(item) && !RB_FLOAT_TYPE_P(item))
|
102
|
+
{
|
103
|
+
free(working_array);
|
104
|
+
rb_raise(rb_eTypeError, "element is not a number");
|
105
|
+
}
|
106
|
+
|
107
|
+
working_array[i] = NUM2DBL(item);
|
108
|
+
}
|
109
|
+
|
110
|
+
// Reminder to myself as I'm learning C. Using an array as a function parameter decays that reference
|
111
|
+
// to a pointer to the first element in the array.
|
112
|
+
// https://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#Function-Parameters
|
113
|
+
qsort(working_array, array_length, sizeof(double), compare_doubles);
|
114
|
+
|
115
|
+
if (!array_even_size)
|
116
|
+
{
|
117
|
+
result = DBL2NUM(working_array[middle]);
|
118
|
+
}
|
119
|
+
else
|
120
|
+
{
|
121
|
+
result = DBL2NUM((working_array[middle - 1] + working_array[middle]) / 2);
|
122
|
+
}
|
123
|
+
|
124
|
+
free(working_array);
|
125
|
+
|
126
|
+
return result;
|
127
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_native_statistics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cory Buecker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-01-
|
11
|
+
date: 2020-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -21,6 +21,7 @@ extra_rdoc_files: []
|
|
21
21
|
files:
|
22
22
|
- ".github/workflows/main.yml"
|
23
23
|
- ".gitignore"
|
24
|
+
- ".vscode/c_cpp_properties.json"
|
24
25
|
- ".vscode/settings.json"
|
25
26
|
- Gemfile
|
26
27
|
- Gemfile.lock
|