ruby_native_statistics 0.8.2 → 0.9.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.
- 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
|