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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 58cae049ef922fead26f20dff3714c2f9c1bcccd95fe38228add9d7f6d57e787
4
- data.tar.gz: 3529205f8a822cc3c418d54d36d4651708384cc885f990517e03fc0f1c8edb15
3
+ metadata.gz: b99d6ace1e36cdd53315356b8c4de080289a46bc307b41bc1979de4cbaff2e42
4
+ data.tar.gz: 5b8c3498b2a3014313b0b249eb87350e7f07e5a22237de4ea9e95f67096572c7
5
5
  SHA512:
6
- metadata.gz: fe760b4680dbf1d11685404718589c7d24c659d086c422977ee3e8c1223073331dfb125c83275a9254ce7fa161b33b388cd66008f6de429417c0ba92acedad87
7
- data.tar.gz: 768f2745a827ffa45fe34a89ff7eb4cc1f4d444bfa6c99f2c4bcd75058131b25cfc17f93ee58599511f8e6a265335af7480dc7890988c8e10e5aa318f4d4514c
6
+ metadata.gz: c837f3f6f7e2a8d47291d1e289d09e48de81c5216bca319e1be24aca7a821f0ba8e1acd3548ccfbe83a50b92752af5dc281a9a69dc052e58cee1f5e49b05e06d
7
+ data.tar.gz: 3c8e3629ffe57bccdbdeaa8b792d593aa89bdce401e034a2a0d08fdf62fb1ad0841229cc60c222aaa37fe0895c2fdee83109176ec553e0c1529c33814868fa4e
@@ -27,7 +27,7 @@ jobs:
27
27
  uses: actions/checkout@master
28
28
 
29
29
  - name: Install Bundler
30
- run: gem install bundler -v 2.1.2
30
+ run: gem install bundler --version 2.1.2 --no-document
31
31
 
32
32
  - name: Install gems
33
33
  run: bundle
@@ -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 CircleCI 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
+ 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(:benchmark) do |t|
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,3 +1,7 @@
1
+ # Version 0.9.0
2
+
3
+ - Add median function
4
+
1
5
  # Version 0.8.2
2
6
 
3
7
  - Bug fix for build process
@@ -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
+ }
@@ -1,4 +1,5 @@
1
1
  VALUE MathematicsModule = Qnil;
2
2
  VALUE rb_mean(VALUE self);
3
+ VALUE rb_median(VALUE self);
3
4
  double calculate_mean(VALUE array, unsigned long array_length);
4
5
  double calculate_total_distance_from_mean(VALUE array, unsigned long array_length);
@@ -1,3 +1,3 @@
1
1
  module RubyNativeStatistics
2
- VERSION = "0.8.2"
2
+ VERSION = "0.9.0"
3
3
  end
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.8.2
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 00:00:00.000000000 Z
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