cheap-stats 0.1.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 +7 -0
- data/.gitignore +50 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +35 -0
- data/Rakefile +2 -0
- data/cheap-stats.gemspec +40 -0
- data/ext/cheap_stats/cheap_stats.c +605 -0
- data/ext/cheap_stats/cheap_stats.h +37 -0
- data/ext/cheap_stats/extconf.rb +4 -0
- data/ext/cheap_stats/rb_cheap_stats.c +513 -0
- data/lib/cheap_stats.rb +11 -0
- data/lib/cheap_stats/version.rb +3 -0
- metadata +99 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0e5a30b7e09b21f08359019f9a4a33bb8bc8b4e1e103bea1eed739f12de818f0
|
4
|
+
data.tar.gz: dc3146cd65e34779373ffe61b5f32c90ac1cfb89218e5fefd81804bf6d40ac59
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5860b61e54bc57a8ade4724d4f5e5ac62811079b75869177e774c0eb281341fa0a2c7ee7f41f59fbb409355b4a2e5757ccf14a7179d6912d0919d240928759fe
|
7
|
+
data.tar.gz: a9b091cfcb393b1236dd5eca02eaf2d5742c51ce0ea94da38827171c6752c0a6140856c50679b97d363eceabffbdd2876ffb5795aa99c0e365ffe81ad7f85ffd
|
data/.gitignore
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
## Specific to RubyMotion:
|
17
|
+
.dat*
|
18
|
+
.repl_history
|
19
|
+
build/
|
20
|
+
*.bridgesupport
|
21
|
+
build-iPhoneOS/
|
22
|
+
build-iPhoneSimulator/
|
23
|
+
|
24
|
+
## Specific to RubyMotion (use of CocoaPods):
|
25
|
+
#
|
26
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
27
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
28
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
29
|
+
#
|
30
|
+
# vendor/Pods/
|
31
|
+
|
32
|
+
## Documentation cache and generated files:
|
33
|
+
/.yardoc/
|
34
|
+
/_yardoc/
|
35
|
+
/doc/
|
36
|
+
/rdoc/
|
37
|
+
|
38
|
+
## Environment normalization:
|
39
|
+
/.bundle/
|
40
|
+
/vendor/bundle
|
41
|
+
/lib/bundler/man/
|
42
|
+
|
43
|
+
# for a library or gem, you might want to ignore these files since the code is
|
44
|
+
# intended to run in multiple environments; otherwise, check them in:
|
45
|
+
# Gemfile.lock
|
46
|
+
# .ruby-version
|
47
|
+
# .ruby-gemset
|
48
|
+
|
49
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
50
|
+
.rvmrc
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2019 Hiroshi Kuwagata
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# cheap-stats
|
2
|
+
A cheap statistics library for Ruby
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
gem 'cheap-stats'
|
8
|
+
```
|
9
|
+
|
10
|
+
And then execute:
|
11
|
+
|
12
|
+
$ bundle
|
13
|
+
|
14
|
+
Or install it yourself as:
|
15
|
+
|
16
|
+
$ gem install cheap-stats
|
17
|
+
|
18
|
+
## Examplw
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
require 'chaep_stats'
|
22
|
+
|
23
|
+
SAMPLES = [7.0, 4.0, 1.0, 5.0, 3.0, 10.0, 6.0, 2.0, 8.0, 9.0]
|
24
|
+
|
25
|
+
stats = CheapStats.new(SMAPLES)
|
26
|
+
|
27
|
+
p stats.mean
|
28
|
+
p stats.std
|
29
|
+
p stats.skewness
|
30
|
+
|
31
|
+
```
|
32
|
+
|
33
|
+
## License
|
34
|
+
|
35
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/cheap-stats.gemspec
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "cheap_stats/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "cheap-stats"
|
8
|
+
spec.version = CheapStats::VERSION
|
9
|
+
spec.authors = ["Hiroshi Kuwagata"]
|
10
|
+
spec.email = ["kgt9221@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{A cheaper statistics library.}
|
13
|
+
spec.description = %q{A cheaper statistics library.}
|
14
|
+
spec.homepage = "https://github.com/kwgt/cheap-stats"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
if spec.respond_to?(:metadata)
|
18
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
19
|
+
else
|
20
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
21
|
+
"public gem pushes."
|
22
|
+
end
|
23
|
+
|
24
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
25
|
+
`git ls-files -z`.split("\x0").reject { |f|
|
26
|
+
f.match(%r{^(test|spec|features)/})
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
spec.bindir = "bin"
|
31
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
|
+
spec.extensions = ["ext/cheap_stats/extconf.rb"]
|
33
|
+
spec.require_paths = ["lib"]
|
34
|
+
|
35
|
+
spec.required_ruby_version = ">= 2.4.0"
|
36
|
+
|
37
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
38
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
39
|
+
spec.add_development_dependency "rake-compiler"
|
40
|
+
end
|
@@ -0,0 +1,605 @@
|
|
1
|
+
/*
|
2
|
+
* Small statics library
|
3
|
+
*
|
4
|
+
* Copyright (C) 2019 Hiroshi Kuwagata <kgt9221@gmail.com>
|
5
|
+
*/
|
6
|
+
|
7
|
+
#include <stdio.h>
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include <string.h>
|
10
|
+
#include <math.h>
|
11
|
+
|
12
|
+
#include "cheap_stats.h"
|
13
|
+
|
14
|
+
#define DEFAULT_ERROR __LINE__
|
15
|
+
#define MIN_SAMPLES 10
|
16
|
+
|
17
|
+
#define ALLOC(t) ((t*)malloc(sizeof(t)))
|
18
|
+
#define NALLOC(t,n) ((t*)malloc(sizeof(t) * (n)))
|
19
|
+
#define FREE(var) do {free(var);var = NULL;} while (0)
|
20
|
+
#define SHRINK(n) ((n * 10) / 13)
|
21
|
+
#define SWAP(a,b) do {double t; t = b; b = a; a = t;} while(0)
|
22
|
+
|
23
|
+
static void
|
24
|
+
combsort11(double* a, size_t n)
|
25
|
+
{
|
26
|
+
int h;
|
27
|
+
int f;
|
28
|
+
int i;
|
29
|
+
|
30
|
+
/*
|
31
|
+
* sort by ascending order
|
32
|
+
*/
|
33
|
+
|
34
|
+
h = n;
|
35
|
+
|
36
|
+
while (h > 1 || f) {
|
37
|
+
f = 0;
|
38
|
+
h = SHRINK(h);
|
39
|
+
|
40
|
+
if (h == 9 || h == 10) h = 11;
|
41
|
+
|
42
|
+
for (i = 0; i < ((int)n - h); i++) {
|
43
|
+
if (a[i] > a[i + h]) {
|
44
|
+
SWAP(a[i], a[i + h]);
|
45
|
+
f = !0;
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
static int
|
52
|
+
binsearch(double* a, size_t n, double v)
|
53
|
+
{
|
54
|
+
int l;
|
55
|
+
int r;
|
56
|
+
int ret;
|
57
|
+
|
58
|
+
l = 0;
|
59
|
+
r = n - 1;
|
60
|
+
|
61
|
+
while (1) {
|
62
|
+
ret = (l + r) / 2;
|
63
|
+
|
64
|
+
if (r <= l) break;
|
65
|
+
|
66
|
+
if (a[ret] < v) {
|
67
|
+
l = ret + 1;
|
68
|
+
continue;
|
69
|
+
}
|
70
|
+
|
71
|
+
if (a[ret] > v) {
|
72
|
+
r = ret - 1;
|
73
|
+
continue;
|
74
|
+
}
|
75
|
+
|
76
|
+
break;
|
77
|
+
}
|
78
|
+
|
79
|
+
return ret;
|
80
|
+
}
|
81
|
+
|
82
|
+
static double
|
83
|
+
calc_sum(double* a, size_t n)
|
84
|
+
{
|
85
|
+
int i;
|
86
|
+
double s;
|
87
|
+
|
88
|
+
s = 0;
|
89
|
+
|
90
|
+
for (i = 0; i < (int)n; i++) {
|
91
|
+
s += a[i];
|
92
|
+
}
|
93
|
+
|
94
|
+
return s;
|
95
|
+
}
|
96
|
+
|
97
|
+
static double
|
98
|
+
calc_variance(double* a, size_t n, double mean)
|
99
|
+
{
|
100
|
+
int i;
|
101
|
+
|
102
|
+
double d;
|
103
|
+
double s;
|
104
|
+
|
105
|
+
s = 0;
|
106
|
+
|
107
|
+
for (i = 0; i < (int)n; i++) {
|
108
|
+
d = a[i] - mean;
|
109
|
+
s += (d * d);
|
110
|
+
}
|
111
|
+
|
112
|
+
return s / n;
|
113
|
+
}
|
114
|
+
|
115
|
+
static double
|
116
|
+
calc_cdf(double* a, size_t n, double v)
|
117
|
+
{
|
118
|
+
int idx;
|
119
|
+
|
120
|
+
if (v > a[n - 1]) {
|
121
|
+
idx = n;
|
122
|
+
} else {
|
123
|
+
idx = binsearch(a, n, v);
|
124
|
+
}
|
125
|
+
|
126
|
+
return (double)idx / n;
|
127
|
+
}
|
128
|
+
|
129
|
+
static double
|
130
|
+
calc_moment(double* a, size_t n, double k)
|
131
|
+
{
|
132
|
+
double s;
|
133
|
+
int i;
|
134
|
+
|
135
|
+
for (i = 0; i < (int)n; i++) {
|
136
|
+
s += pow(a[i], k);
|
137
|
+
}
|
138
|
+
|
139
|
+
return s / n;
|
140
|
+
}
|
141
|
+
|
142
|
+
static double
|
143
|
+
calc_central_moment(double* a, size_t n, double k, double mean)
|
144
|
+
{
|
145
|
+
double s;
|
146
|
+
int i;
|
147
|
+
|
148
|
+
for (i = 0; i < (int)n; i++) {
|
149
|
+
s += pow(a[i] - mean, k);
|
150
|
+
}
|
151
|
+
|
152
|
+
return s / n;
|
153
|
+
}
|
154
|
+
|
155
|
+
static double
|
156
|
+
calc_std_moment(double* a, size_t n, double k, double mean, double std)
|
157
|
+
{
|
158
|
+
return calc_central_moment(a, n, k, mean) / pow(std, k);
|
159
|
+
}
|
160
|
+
|
161
|
+
static double
|
162
|
+
calc_normal_pdf(double* a, size_t n,
|
163
|
+
double mean, double std, double total, double v)
|
164
|
+
{
|
165
|
+
double t;
|
166
|
+
|
167
|
+
t = (v - mean) / std;
|
168
|
+
|
169
|
+
// 2.50662827463 == sqrt(2.0 * M_PI)
|
170
|
+
return (exp(-0.5 * (t * t)) / (std * 2.50662827463)) / total;
|
171
|
+
}
|
172
|
+
|
173
|
+
static double
|
174
|
+
kernel_gaussian(double x)
|
175
|
+
{
|
176
|
+
// 2.50662827463 == sqrt(2.0 * M_PI)
|
177
|
+
return exp(-(x * x) / 2.0) / 2.50662827463;
|
178
|
+
}
|
179
|
+
|
180
|
+
static double
|
181
|
+
calc_kde(double* a, size_t n, double sig, double v)
|
182
|
+
{
|
183
|
+
double h;
|
184
|
+
double s;
|
185
|
+
int i;
|
186
|
+
|
187
|
+
h = (0.9 * sig) / pow(n, 1.0 / 5.0);
|
188
|
+
s = 0.0;
|
189
|
+
|
190
|
+
for (i = 0; i < (int)n; i++) {
|
191
|
+
s += kernel_gaussian((v - a[i]) / h);
|
192
|
+
}
|
193
|
+
|
194
|
+
return (s / (n * h));
|
195
|
+
}
|
196
|
+
|
197
|
+
int
|
198
|
+
cheap_stats_new(double* src, size_t n, cheap_stats_t** dst)
|
199
|
+
{
|
200
|
+
int ret;
|
201
|
+
double* a0;
|
202
|
+
double* a1;
|
203
|
+
cheap_stats_t* ptr;
|
204
|
+
|
205
|
+
/*
|
206
|
+
* initialize
|
207
|
+
*/
|
208
|
+
ret = 0;
|
209
|
+
ptr = NULL;
|
210
|
+
a0 = NULL;
|
211
|
+
a1 = NULL;
|
212
|
+
|
213
|
+
/*
|
214
|
+
* argument check
|
215
|
+
*/
|
216
|
+
do {
|
217
|
+
if (src == NULL) {
|
218
|
+
ret = DEFAULT_ERROR;
|
219
|
+
break;
|
220
|
+
}
|
221
|
+
|
222
|
+
if (n < MIN_SAMPLES) {
|
223
|
+
ret = DEFAULT_ERROR;
|
224
|
+
break;
|
225
|
+
}
|
226
|
+
|
227
|
+
if (dst == NULL) {
|
228
|
+
ret = DEFAULT_ERROR;
|
229
|
+
break;
|
230
|
+
}
|
231
|
+
} while (0);
|
232
|
+
|
233
|
+
/*
|
234
|
+
* alloc memory
|
235
|
+
*/
|
236
|
+
if (!ret) do {
|
237
|
+
a0 = NALLOC(double, n);
|
238
|
+
if (a0 == NULL) {
|
239
|
+
ret = DEFAULT_ERROR;
|
240
|
+
break;
|
241
|
+
}
|
242
|
+
|
243
|
+
a1 = NALLOC(double, n);
|
244
|
+
if (a1 == NULL) {
|
245
|
+
ret = DEFAULT_ERROR;
|
246
|
+
break;
|
247
|
+
}
|
248
|
+
|
249
|
+
ptr = ALLOC(cheap_stats_t);
|
250
|
+
if (ptr == NULL) {
|
251
|
+
ret = DEFAULT_ERROR;
|
252
|
+
break;
|
253
|
+
}
|
254
|
+
} while (0);
|
255
|
+
|
256
|
+
/*
|
257
|
+
* put return parameter
|
258
|
+
*/
|
259
|
+
if (!ret) {
|
260
|
+
memcpy(a0, src, sizeof(double) * n);
|
261
|
+
memcpy(a1, src, sizeof(double) * n);
|
262
|
+
combsort11(a1, n);
|
263
|
+
|
264
|
+
ptr->a0 = a0;
|
265
|
+
ptr->a1 = a1;
|
266
|
+
ptr->n = n;
|
267
|
+
ptr->total = calc_sum(a0, n);
|
268
|
+
ptr->mean = ptr->total / n;
|
269
|
+
ptr->min = ptr->a1[0];
|
270
|
+
ptr->max = ptr->a1[n - 1];
|
271
|
+
ptr->q1 = ptr->a1[n / 4];
|
272
|
+
ptr->q3 = ptr->a1[(3 * n) / 4];
|
273
|
+
ptr->median = ptr->a1[n / 2];
|
274
|
+
ptr->variance = calc_variance(a0, n, ptr->mean);
|
275
|
+
ptr->std = sqrt(ptr->variance);
|
276
|
+
|
277
|
+
*dst = ptr;
|
278
|
+
}
|
279
|
+
|
280
|
+
/*
|
281
|
+
* post process
|
282
|
+
*/
|
283
|
+
if (ret) {
|
284
|
+
if (ptr) free(ptr);
|
285
|
+
if (a0) free(a0);
|
286
|
+
if (a1) free(a1);
|
287
|
+
}
|
288
|
+
|
289
|
+
return ret;
|
290
|
+
}
|
291
|
+
|
292
|
+
int
|
293
|
+
cheap_stats_destroy(cheap_stats_t* ptr)
|
294
|
+
{
|
295
|
+
int ret;
|
296
|
+
|
297
|
+
/*
|
298
|
+
* initialize
|
299
|
+
*/
|
300
|
+
ret = 0;
|
301
|
+
|
302
|
+
/*
|
303
|
+
* argument check
|
304
|
+
*/
|
305
|
+
if (ptr == NULL) {
|
306
|
+
ret = DEFAULT_ERROR;
|
307
|
+
}
|
308
|
+
|
309
|
+
/*
|
310
|
+
* release memory
|
311
|
+
*/
|
312
|
+
if (!ret) {
|
313
|
+
if (ptr->a0) free(ptr->a0);
|
314
|
+
if (ptr->a1) free(ptr->a1);
|
315
|
+
free(ptr);
|
316
|
+
}
|
317
|
+
|
318
|
+
return ret;
|
319
|
+
}
|
320
|
+
|
321
|
+
int
|
322
|
+
cheap_stats_cdf(cheap_stats_t* ptr, double v, double* dst)
|
323
|
+
{
|
324
|
+
int ret;
|
325
|
+
|
326
|
+
/*
|
327
|
+
* initialize
|
328
|
+
*/
|
329
|
+
ret = 0;
|
330
|
+
|
331
|
+
/*
|
332
|
+
* argument check
|
333
|
+
*/
|
334
|
+
do {
|
335
|
+
if (ptr == NULL) {
|
336
|
+
ret = DEFAULT_ERROR;
|
337
|
+
break;
|
338
|
+
}
|
339
|
+
|
340
|
+
if (dst == NULL) {
|
341
|
+
ret = DEFAULT_ERROR;
|
342
|
+
break;
|
343
|
+
}
|
344
|
+
} while (0);
|
345
|
+
|
346
|
+
/*
|
347
|
+
* calc CDF
|
348
|
+
*/
|
349
|
+
if (!ret) {
|
350
|
+
*dst = calc_cdf(ptr->a1, ptr->n, v);
|
351
|
+
}
|
352
|
+
|
353
|
+
return ret;
|
354
|
+
}
|
355
|
+
|
356
|
+
int
|
357
|
+
cheap_stats_normal_pdf(cheap_stats_t* ptr, double v, double* dst)
|
358
|
+
{
|
359
|
+
int ret;
|
360
|
+
|
361
|
+
/*
|
362
|
+
* initialize
|
363
|
+
*/
|
364
|
+
ret = 0;
|
365
|
+
|
366
|
+
/*
|
367
|
+
* argument check
|
368
|
+
*/
|
369
|
+
do {
|
370
|
+
if (ptr == NULL) {
|
371
|
+
ret = DEFAULT_ERROR;
|
372
|
+
break;
|
373
|
+
}
|
374
|
+
|
375
|
+
if (dst == NULL) {
|
376
|
+
ret = DEFAULT_ERROR;
|
377
|
+
break;
|
378
|
+
}
|
379
|
+
} while (0);
|
380
|
+
|
381
|
+
/*
|
382
|
+
* calc CDF
|
383
|
+
*/
|
384
|
+
if (!ret) {
|
385
|
+
*dst = calc_normal_pdf(ptr->a1, ptr->n, ptr->mean, ptr->std, ptr->total, v);
|
386
|
+
}
|
387
|
+
|
388
|
+
return ret;
|
389
|
+
}
|
390
|
+
|
391
|
+
int
|
392
|
+
cheap_stats_estimated_pdf(cheap_stats_t* ptr, double v, double* dst)
|
393
|
+
{
|
394
|
+
int ret;
|
395
|
+
double sig;
|
396
|
+
|
397
|
+
/*
|
398
|
+
* initialize
|
399
|
+
*/
|
400
|
+
ret = 0;
|
401
|
+
|
402
|
+
/*
|
403
|
+
* argument check
|
404
|
+
*/
|
405
|
+
do {
|
406
|
+
if (ptr == NULL) {
|
407
|
+
ret = DEFAULT_ERROR;
|
408
|
+
break;
|
409
|
+
}
|
410
|
+
|
411
|
+
if (dst == NULL) {
|
412
|
+
ret = DEFAULT_ERROR;
|
413
|
+
break;
|
414
|
+
}
|
415
|
+
} while (0);
|
416
|
+
|
417
|
+
/*
|
418
|
+
* calc CDF
|
419
|
+
*/
|
420
|
+
if (!ret) {
|
421
|
+
sig = ptr->q3 - ptr->q1;
|
422
|
+
if (sig > ptr->std) sig = ptr->std;
|
423
|
+
|
424
|
+
*dst = calc_kde(ptr->a1, ptr->n, sig, v);
|
425
|
+
}
|
426
|
+
|
427
|
+
return ret;
|
428
|
+
}
|
429
|
+
|
430
|
+
|
431
|
+
int
|
432
|
+
cheap_stats_moment(cheap_stats_t* ptr, double k, double* dst)
|
433
|
+
{
|
434
|
+
int ret;
|
435
|
+
|
436
|
+
/*
|
437
|
+
* initialize
|
438
|
+
*/
|
439
|
+
ret = 0;
|
440
|
+
|
441
|
+
/*
|
442
|
+
* argument check
|
443
|
+
*/
|
444
|
+
do {
|
445
|
+
if (ptr == NULL) {
|
446
|
+
ret = DEFAULT_ERROR;
|
447
|
+
break;
|
448
|
+
}
|
449
|
+
|
450
|
+
if (dst == NULL) {
|
451
|
+
ret = DEFAULT_ERROR;
|
452
|
+
break;
|
453
|
+
}
|
454
|
+
} while (0);
|
455
|
+
|
456
|
+
/*
|
457
|
+
* calc raw moment
|
458
|
+
*/
|
459
|
+
if (!ret) {
|
460
|
+
*dst = calc_moment(ptr->a1, ptr->n, k);
|
461
|
+
}
|
462
|
+
|
463
|
+
return ret;
|
464
|
+
}
|
465
|
+
|
466
|
+
int
|
467
|
+
cheap_stats_central_moment(cheap_stats_t* ptr, double k, double* dst)
|
468
|
+
{
|
469
|
+
int ret;
|
470
|
+
|
471
|
+
/*
|
472
|
+
* initialize
|
473
|
+
*/
|
474
|
+
ret = 0;
|
475
|
+
|
476
|
+
/*
|
477
|
+
* argument check
|
478
|
+
*/
|
479
|
+
do {
|
480
|
+
if (ptr == NULL) {
|
481
|
+
ret = DEFAULT_ERROR;
|
482
|
+
break;
|
483
|
+
}
|
484
|
+
|
485
|
+
if (dst == NULL) {
|
486
|
+
ret = DEFAULT_ERROR;
|
487
|
+
break;
|
488
|
+
}
|
489
|
+
} while (0);
|
490
|
+
|
491
|
+
/*
|
492
|
+
* calc raw moment
|
493
|
+
*/
|
494
|
+
if (!ret) {
|
495
|
+
*dst = calc_central_moment(ptr->a1, ptr->n, k, ptr->mean);
|
496
|
+
}
|
497
|
+
|
498
|
+
return ret;
|
499
|
+
}
|
500
|
+
|
501
|
+
int
|
502
|
+
cheap_stats_std_moment(cheap_stats_t* ptr, double k, double* dst)
|
503
|
+
{
|
504
|
+
int ret;
|
505
|
+
|
506
|
+
/*
|
507
|
+
* initialize
|
508
|
+
*/
|
509
|
+
ret = 0;
|
510
|
+
|
511
|
+
/*
|
512
|
+
* argument check
|
513
|
+
*/
|
514
|
+
do {
|
515
|
+
if (ptr == NULL) {
|
516
|
+
ret = DEFAULT_ERROR;
|
517
|
+
break;
|
518
|
+
}
|
519
|
+
|
520
|
+
if (dst == NULL) {
|
521
|
+
ret = DEFAULT_ERROR;
|
522
|
+
break;
|
523
|
+
}
|
524
|
+
} while (0);
|
525
|
+
|
526
|
+
/*
|
527
|
+
* calc raw moment
|
528
|
+
*/
|
529
|
+
if (!ret) {
|
530
|
+
*dst = calc_std_moment(ptr->a1, ptr->n, k, ptr->mean, ptr->std);
|
531
|
+
}
|
532
|
+
|
533
|
+
return ret;
|
534
|
+
}
|
535
|
+
|
536
|
+
int
|
537
|
+
cheap_stats_skewness(cheap_stats_t* ptr, double* dst)
|
538
|
+
{
|
539
|
+
int ret;
|
540
|
+
|
541
|
+
/*
|
542
|
+
* initialize
|
543
|
+
*/
|
544
|
+
ret = 0;
|
545
|
+
|
546
|
+
/*
|
547
|
+
* argument check
|
548
|
+
*/
|
549
|
+
do {
|
550
|
+
if (ptr == NULL) {
|
551
|
+
ret = DEFAULT_ERROR;
|
552
|
+
break;
|
553
|
+
}
|
554
|
+
|
555
|
+
if (dst == NULL) {
|
556
|
+
ret = DEFAULT_ERROR;
|
557
|
+
break;
|
558
|
+
}
|
559
|
+
} while (0);
|
560
|
+
|
561
|
+
/*
|
562
|
+
* calc raw moment
|
563
|
+
*/
|
564
|
+
if (!ret) {
|
565
|
+
*dst = calc_std_moment(ptr->a1, ptr->n, 3.0, ptr->mean, ptr->std);
|
566
|
+
}
|
567
|
+
|
568
|
+
return ret;
|
569
|
+
}
|
570
|
+
|
571
|
+
int
|
572
|
+
cheap_stats_pearson_skewness(cheap_stats_t* ptr, double* dst)
|
573
|
+
{
|
574
|
+
int ret;
|
575
|
+
|
576
|
+
/*
|
577
|
+
* initialize
|
578
|
+
*/
|
579
|
+
ret = 0;
|
580
|
+
|
581
|
+
/*
|
582
|
+
* argument check
|
583
|
+
*/
|
584
|
+
do {
|
585
|
+
if (ptr == NULL) {
|
586
|
+
ret = DEFAULT_ERROR;
|
587
|
+
break;
|
588
|
+
}
|
589
|
+
|
590
|
+
if (dst == NULL) {
|
591
|
+
ret = DEFAULT_ERROR;
|
592
|
+
break;
|
593
|
+
}
|
594
|
+
} while (0);
|
595
|
+
|
596
|
+
/*
|
597
|
+
* calc raw moment
|
598
|
+
*/
|
599
|
+
if (!ret) {
|
600
|
+
*dst = (3.0 * (ptr->mean - ptr->median)) / (ptr->std + 1e-15);
|
601
|
+
}
|
602
|
+
|
603
|
+
return ret;
|
604
|
+
}
|
605
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
/*
|
2
|
+
* Small statics library
|
3
|
+
*
|
4
|
+
* Copyright (C) 2019 Hiroshi Kuwagata <kgt9221@gmail.com>
|
5
|
+
*/
|
6
|
+
|
7
|
+
#ifndef __SMALL_STATS_H__
|
8
|
+
#define __SMALL_STATS_H__
|
9
|
+
|
10
|
+
#include <stdlib.h>
|
11
|
+
|
12
|
+
typedef struct {
|
13
|
+
double* a0;
|
14
|
+
double* a1; // sorted
|
15
|
+
size_t n;
|
16
|
+
|
17
|
+
double total;
|
18
|
+
double mean;
|
19
|
+
double min;
|
20
|
+
double max;
|
21
|
+
double q1;
|
22
|
+
double q3;
|
23
|
+
double median;
|
24
|
+
double variance;
|
25
|
+
double std;
|
26
|
+
} cheap_stats_t;
|
27
|
+
|
28
|
+
int cheap_stats_new(double* samples, size_t size, cheap_stats_t** obj);
|
29
|
+
int cheap_stats_destroy(cheap_stats_t* obj);
|
30
|
+
int cheap_stats_cdf(cheap_stats_t* obj, double v, double* dst);
|
31
|
+
int cheap_stats_moment(cheap_stats_t* obj, double k, double* dst);
|
32
|
+
int cheap_stats_central_moment(cheap_stats_t* obj, double k, double* dst);
|
33
|
+
int cheap_stats_std_moment(cheap_stats_t* obj, double k, double* dst);
|
34
|
+
int cheap_stats_skewness(cheap_stats_t* obj, double* dst);
|
35
|
+
int cheap_stats_pearson_skewness(cheap_stats_t* obj, double* dst);
|
36
|
+
|
37
|
+
#endif /* !defined(__SMALL_STATS_H__) */
|
@@ -0,0 +1,513 @@
|
|
1
|
+
/*
|
2
|
+
* cheap statistics library for ruby
|
3
|
+
*
|
4
|
+
* Copyright (C) 2019 Hiroshi Kuwagata <kgt9221@gmail.com>
|
5
|
+
*/
|
6
|
+
|
7
|
+
#include <stdio.h>
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include <stdint.h>
|
10
|
+
#include <string.h>
|
11
|
+
#include "ruby.h"
|
12
|
+
|
13
|
+
#include "cheap_stats.h"
|
14
|
+
|
15
|
+
#define N(x) (sizeof(x)/sizeof(*x))
|
16
|
+
|
17
|
+
#define RUNTIME_ERROR(msg, ...) rb_raise(rb_eRuntimeError, (msg), __VA_ARGS__)
|
18
|
+
#define ARGUMENT_ERROR(msg, ...) rb_raise(rb_eArgError, (msg), __VA_ARGS__)
|
19
|
+
#define TYPE_ERROR(msg, ...) rb_raise(rb_eTypeError, (msg), __VA_ARGS__)
|
20
|
+
#define NOMEMORY_ERROR(msg, ...) rb_raise(rb_eNoMemError, (msg), __VA_ARGS__)
|
21
|
+
|
22
|
+
#define API_SIMPLIFIED 1
|
23
|
+
#define API_CLASSIC 2
|
24
|
+
|
25
|
+
#define EQ_STR(val,str) (rb_to_id(val) == rb_intern(str))
|
26
|
+
#define EQ_INT(val,n) (FIX2INT(val) == n)
|
27
|
+
#define IS_NUMERIC(t) \
|
28
|
+
((t) == T_FLOAT || (t) == T_FIXNUM || (t) == T_BIGNUM)
|
29
|
+
|
30
|
+
typedef struct {
|
31
|
+
cheap_stats_t* stats;
|
32
|
+
} rb_cheap_stats_t;
|
33
|
+
|
34
|
+
VALUE klass;
|
35
|
+
|
36
|
+
static size_t
|
37
|
+
rb_cheap_stats_size(const void* _ptr)
|
38
|
+
{
|
39
|
+
rb_cheap_stats_t* ptr;
|
40
|
+
|
41
|
+
ptr = (rb_cheap_stats_t*)_ptr;
|
42
|
+
|
43
|
+
return sizeof(*ptr) + ((sizeof(double) * ptr->stats->n) * 2);
|
44
|
+
}
|
45
|
+
|
46
|
+
static void
|
47
|
+
rb_cheap_stats_free(void* _ptr)
|
48
|
+
{
|
49
|
+
rb_cheap_stats_t* ptr;
|
50
|
+
|
51
|
+
ptr = (rb_cheap_stats_t*)_ptr;
|
52
|
+
|
53
|
+
if (ptr->stats != NULL) {
|
54
|
+
cheap_stats_destroy(ptr->stats);
|
55
|
+
ptr->stats = NULL;
|
56
|
+
}
|
57
|
+
|
58
|
+
xfree(ptr);
|
59
|
+
}
|
60
|
+
|
61
|
+
static const struct rb_data_type_struct rb_cheap_stats_data_type = {
|
62
|
+
"A Cheap satatics library",
|
63
|
+
{
|
64
|
+
NULL,
|
65
|
+
rb_cheap_stats_free,
|
66
|
+
rb_cheap_stats_size,
|
67
|
+
{NULL, NULL}
|
68
|
+
},
|
69
|
+
NULL,
|
70
|
+
NULL,
|
71
|
+
};
|
72
|
+
|
73
|
+
static VALUE
|
74
|
+
rb_cheap_stats_alloc(VALUE self)
|
75
|
+
{
|
76
|
+
rb_cheap_stats_t* ptr;
|
77
|
+
|
78
|
+
ptr = ALLOC(rb_cheap_stats_t);
|
79
|
+
memset(ptr, 0, sizeof(*ptr));
|
80
|
+
|
81
|
+
return TypedData_Wrap_Struct(klass, &rb_cheap_stats_data_type, ptr);
|
82
|
+
}
|
83
|
+
|
84
|
+
/**
|
85
|
+
* initialize object
|
86
|
+
*
|
87
|
+
* @params [Array<Numeric>] samples sample vaules.
|
88
|
+
*/
|
89
|
+
static VALUE
|
90
|
+
rb_cheap_stats_initialize(VALUE self, VALUE samples)
|
91
|
+
{
|
92
|
+
rb_cheap_stats_t* ptr;
|
93
|
+
VALUE exp;
|
94
|
+
const char* msg;
|
95
|
+
int err;
|
96
|
+
double *a;
|
97
|
+
int i;
|
98
|
+
int n;
|
99
|
+
VALUE v;
|
100
|
+
int t;
|
101
|
+
char str[64];
|
102
|
+
|
103
|
+
/*
|
104
|
+
* strip context data
|
105
|
+
*/
|
106
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
107
|
+
|
108
|
+
/*
|
109
|
+
* check argument
|
110
|
+
*/
|
111
|
+
Check_Type(samples, T_ARRAY);
|
112
|
+
|
113
|
+
do {
|
114
|
+
exp = Qnil;
|
115
|
+
a = NULL;
|
116
|
+
|
117
|
+
/*
|
118
|
+
* allocate work buffer
|
119
|
+
*/
|
120
|
+
n = RARRAY_LEN(samples);
|
121
|
+
a = malloc(sizeof(double) * n);
|
122
|
+
|
123
|
+
if (a == NULL) {
|
124
|
+
exp = rb_eNoMemError;
|
125
|
+
msg = "Memory allocation failed";
|
126
|
+
break;
|
127
|
+
}
|
128
|
+
|
129
|
+
/*
|
130
|
+
* copy source value
|
131
|
+
*/
|
132
|
+
for (i = 0; i < n; i++) {
|
133
|
+
v = RARRAY_AREF(samples, i);
|
134
|
+
t = TYPE(v);
|
135
|
+
|
136
|
+
if (!IS_NUMERIC(t)) break;
|
137
|
+
|
138
|
+
a[i] = NUM2DBL(v);
|
139
|
+
}
|
140
|
+
|
141
|
+
if (i != n) {
|
142
|
+
exp = rb_eTypeError;
|
143
|
+
msg = "the value that not numeric was included";
|
144
|
+
}
|
145
|
+
|
146
|
+
/*
|
147
|
+
* create statistic context
|
148
|
+
*/
|
149
|
+
err = cheap_stats_new(a, n, &ptr->stats);
|
150
|
+
if (err) {
|
151
|
+
sprintf(str, "cheap_stats_new() failed [err=%d]", err);
|
152
|
+
|
153
|
+
exp = rb_eRuntimeError;
|
154
|
+
msg = str;
|
155
|
+
break;
|
156
|
+
}
|
157
|
+
} while (0);
|
158
|
+
|
159
|
+
/*
|
160
|
+
* post porcess
|
161
|
+
*/
|
162
|
+
if (a != NULL) free(a);
|
163
|
+
|
164
|
+
if (exp != Qnil) {
|
165
|
+
if (ptr->stats != NULL) {
|
166
|
+
cheap_stats_destroy(ptr->stats);
|
167
|
+
ptr->stats = NULL;
|
168
|
+
}
|
169
|
+
|
170
|
+
rb_raise(exp, msg);
|
171
|
+
}
|
172
|
+
|
173
|
+
return self;
|
174
|
+
}
|
175
|
+
|
176
|
+
/**
|
177
|
+
* get total value of samples
|
178
|
+
*
|
179
|
+
* @return [Float] total value
|
180
|
+
*/
|
181
|
+
static VALUE
|
182
|
+
rb_cheap_stats_total(VALUE self)
|
183
|
+
{
|
184
|
+
rb_cheap_stats_t* ptr;
|
185
|
+
|
186
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
187
|
+
|
188
|
+
return DBL2NUM(ptr->stats->total);
|
189
|
+
}
|
190
|
+
|
191
|
+
/**
|
192
|
+
* get mean of samples
|
193
|
+
*
|
194
|
+
* @return [Float] mean
|
195
|
+
*/
|
196
|
+
static VALUE
|
197
|
+
rb_cheap_stats_mean(VALUE self)
|
198
|
+
{
|
199
|
+
rb_cheap_stats_t* ptr;
|
200
|
+
|
201
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
202
|
+
|
203
|
+
return DBL2NUM(ptr->stats->mean);
|
204
|
+
}
|
205
|
+
|
206
|
+
/**
|
207
|
+
* get min value of samples
|
208
|
+
*
|
209
|
+
* @return [Float] min value
|
210
|
+
*/
|
211
|
+
static VALUE
|
212
|
+
rb_cheap_stats_min(VALUE self)
|
213
|
+
{
|
214
|
+
rb_cheap_stats_t* ptr;
|
215
|
+
|
216
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
217
|
+
|
218
|
+
return DBL2NUM(ptr->stats->min);
|
219
|
+
}
|
220
|
+
|
221
|
+
/**
|
222
|
+
* get max value of samples
|
223
|
+
*
|
224
|
+
* @return [Float] max value
|
225
|
+
*/
|
226
|
+
static VALUE
|
227
|
+
rb_cheap_stats_max(VALUE self)
|
228
|
+
{
|
229
|
+
rb_cheap_stats_t* ptr;
|
230
|
+
|
231
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
232
|
+
|
233
|
+
return DBL2NUM(ptr->stats->max);
|
234
|
+
}
|
235
|
+
|
236
|
+
/**
|
237
|
+
* get 1/4 quartile value of samples
|
238
|
+
*
|
239
|
+
* @return [Float] 1/4 quartile value
|
240
|
+
*/
|
241
|
+
static VALUE
|
242
|
+
rb_cheap_stats_q1(VALUE self)
|
243
|
+
{
|
244
|
+
rb_cheap_stats_t* ptr;
|
245
|
+
|
246
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
247
|
+
|
248
|
+
return DBL2NUM(ptr->stats->q1);
|
249
|
+
}
|
250
|
+
|
251
|
+
/**
|
252
|
+
* get 3/4 quartile value of samples
|
253
|
+
*
|
254
|
+
* @return [Float] 3/4 quartile value
|
255
|
+
*/
|
256
|
+
static VALUE
|
257
|
+
rb_cheap_stats_q3(VALUE self)
|
258
|
+
{
|
259
|
+
rb_cheap_stats_t* ptr;
|
260
|
+
|
261
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
262
|
+
|
263
|
+
return DBL2NUM(ptr->stats->q3);
|
264
|
+
}
|
265
|
+
|
266
|
+
/**
|
267
|
+
* get median of samples
|
268
|
+
*
|
269
|
+
* @return [Float] median
|
270
|
+
*/
|
271
|
+
static VALUE
|
272
|
+
rb_cheap_stats_median(VALUE self)
|
273
|
+
{
|
274
|
+
rb_cheap_stats_t* ptr;
|
275
|
+
|
276
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
277
|
+
|
278
|
+
return DBL2NUM(ptr->stats->median);
|
279
|
+
}
|
280
|
+
|
281
|
+
/**
|
282
|
+
* get standard division of samples
|
283
|
+
*
|
284
|
+
* @return [Float] standard division
|
285
|
+
*/
|
286
|
+
static VALUE
|
287
|
+
rb_cheap_stats_std(VALUE self)
|
288
|
+
{
|
289
|
+
rb_cheap_stats_t* ptr;
|
290
|
+
|
291
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
292
|
+
|
293
|
+
return DBL2NUM(ptr->stats->std);
|
294
|
+
}
|
295
|
+
|
296
|
+
/**
|
297
|
+
* get variance of samples
|
298
|
+
*
|
299
|
+
* @return [Float] variance
|
300
|
+
*/
|
301
|
+
static VALUE
|
302
|
+
rb_cheap_stats_variance(VALUE self)
|
303
|
+
{
|
304
|
+
rb_cheap_stats_t* ptr;
|
305
|
+
|
306
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
307
|
+
|
308
|
+
return DBL2NUM(ptr->stats->variance);
|
309
|
+
}
|
310
|
+
|
311
|
+
/**
|
312
|
+
* calc CDF
|
313
|
+
*
|
314
|
+
* @param [Numeric] x taregt value
|
315
|
+
*
|
316
|
+
* @return [Float] CDF value that coresspoinding to target.
|
317
|
+
*/
|
318
|
+
static VALUE
|
319
|
+
rb_cheap_stats_cdf(VALUE self, VALUE x)
|
320
|
+
{
|
321
|
+
rb_cheap_stats_t* ptr;
|
322
|
+
int err;
|
323
|
+
double ret;
|
324
|
+
|
325
|
+
/*
|
326
|
+
* strip context data
|
327
|
+
*/
|
328
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
329
|
+
|
330
|
+
/*
|
331
|
+
* check argument
|
332
|
+
*/
|
333
|
+
err = cheap_stats_cdf(ptr->stats, rb_num2dbl(x), &ret);
|
334
|
+
if (err) {
|
335
|
+
RUNTIME_ERROR("cheap_stats_cdf() failed [err=%d]", err);
|
336
|
+
}
|
337
|
+
|
338
|
+
return DBL2NUM(ret);
|
339
|
+
}
|
340
|
+
|
341
|
+
/**
|
342
|
+
* calc moment
|
343
|
+
*
|
344
|
+
* @param [Numeric] k order number
|
345
|
+
*
|
346
|
+
* @return [Float] moment value
|
347
|
+
*/
|
348
|
+
static VALUE
|
349
|
+
rb_cheap_stats_moment(VALUE self, VALUE k)
|
350
|
+
{
|
351
|
+
rb_cheap_stats_t* ptr;
|
352
|
+
int err;
|
353
|
+
double ret;
|
354
|
+
|
355
|
+
/*
|
356
|
+
* strip context data
|
357
|
+
*/
|
358
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
359
|
+
|
360
|
+
/*
|
361
|
+
* check argument
|
362
|
+
*/
|
363
|
+
err = cheap_stats_moment(ptr->stats, rb_num2dbl(k), &ret);
|
364
|
+
if (err) {
|
365
|
+
RUNTIME_ERROR("cheap_stats_moment() failed [err=%d]", err);
|
366
|
+
}
|
367
|
+
|
368
|
+
return DBL2NUM(ret);
|
369
|
+
}
|
370
|
+
|
371
|
+
/**
|
372
|
+
* calc central moment
|
373
|
+
*
|
374
|
+
* @param [Numeric] k order number
|
375
|
+
*
|
376
|
+
* @return [Float] moment value
|
377
|
+
*/
|
378
|
+
static VALUE
|
379
|
+
rb_cheap_stats_central_moment(VALUE self, VALUE k)
|
380
|
+
{
|
381
|
+
rb_cheap_stats_t* ptr;
|
382
|
+
int err;
|
383
|
+
double ret;
|
384
|
+
|
385
|
+
/*
|
386
|
+
* strip context data
|
387
|
+
*/
|
388
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
389
|
+
|
390
|
+
/*
|
391
|
+
* check argument
|
392
|
+
*/
|
393
|
+
err = cheap_stats_central_moment(ptr->stats, rb_num2dbl(k), &ret);
|
394
|
+
if (err) {
|
395
|
+
RUNTIME_ERROR("cheap_stats_central_moment() failed [err=%d]", err);
|
396
|
+
}
|
397
|
+
|
398
|
+
return DBL2NUM(ret);
|
399
|
+
}
|
400
|
+
|
401
|
+
/**
|
402
|
+
* calc std (standard division) moment
|
403
|
+
*
|
404
|
+
* @param [Numeric] k order number
|
405
|
+
*
|
406
|
+
* @return [Float] moment value
|
407
|
+
*/
|
408
|
+
static VALUE
|
409
|
+
rb_cheap_stats_std_moment(VALUE self, VALUE k)
|
410
|
+
{
|
411
|
+
rb_cheap_stats_t* ptr;
|
412
|
+
int err;
|
413
|
+
double ret;
|
414
|
+
|
415
|
+
/*
|
416
|
+
* strip context data
|
417
|
+
*/
|
418
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
419
|
+
|
420
|
+
/*
|
421
|
+
* check argument
|
422
|
+
*/
|
423
|
+
err = cheap_stats_std_moment(ptr->stats, rb_num2dbl(k), &ret);
|
424
|
+
if (err) {
|
425
|
+
RUNTIME_ERROR("cheap_stats_std_moment() failed [err=%d]", err);
|
426
|
+
}
|
427
|
+
|
428
|
+
return DBL2NUM(ret);
|
429
|
+
}
|
430
|
+
|
431
|
+
/**
|
432
|
+
* calc skewness value
|
433
|
+
*
|
434
|
+
* @return [Float] skewness value
|
435
|
+
*/
|
436
|
+
static VALUE
|
437
|
+
rb_cheap_stats_skewness(VALUE self)
|
438
|
+
{
|
439
|
+
rb_cheap_stats_t* ptr;
|
440
|
+
int err;
|
441
|
+
double ret;
|
442
|
+
|
443
|
+
/*
|
444
|
+
* strip context data
|
445
|
+
*/
|
446
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
447
|
+
|
448
|
+
/*
|
449
|
+
* check argument
|
450
|
+
*/
|
451
|
+
err = cheap_stats_skewness(ptr->stats, &ret);
|
452
|
+
if (err) {
|
453
|
+
RUNTIME_ERROR("cheap_stats_skewness() failed [err=%d]", err);
|
454
|
+
}
|
455
|
+
|
456
|
+
return DBL2NUM(ret);
|
457
|
+
}
|
458
|
+
|
459
|
+
/**
|
460
|
+
* calc pearson median skewness value
|
461
|
+
*
|
462
|
+
* @return [Float] skewness value
|
463
|
+
*/
|
464
|
+
static VALUE
|
465
|
+
rb_cheap_stats_pearson_skewness(VALUE self)
|
466
|
+
{
|
467
|
+
rb_cheap_stats_t* ptr;
|
468
|
+
int err;
|
469
|
+
double ret;
|
470
|
+
|
471
|
+
/*
|
472
|
+
* strip context data
|
473
|
+
*/
|
474
|
+
TypedData_Get_Struct(self, rb_cheap_stats_t, &rb_cheap_stats_data_type, ptr);
|
475
|
+
|
476
|
+
/*
|
477
|
+
* check argument
|
478
|
+
*/
|
479
|
+
err = cheap_stats_pearson_skewness(ptr->stats, &ret);
|
480
|
+
if (err) {
|
481
|
+
RUNTIME_ERROR("cheap_stats_pearson_skewness() failed [err=%d]", err);
|
482
|
+
}
|
483
|
+
|
484
|
+
return DBL2NUM(ret);
|
485
|
+
}
|
486
|
+
|
487
|
+
void
|
488
|
+
Init_cheap_stats()
|
489
|
+
{
|
490
|
+
klass = rb_define_class("CheapStats", rb_cObject);
|
491
|
+
|
492
|
+
rb_define_alloc_func(klass, rb_cheap_stats_alloc);
|
493
|
+
|
494
|
+
rb_define_method(klass, "initialize", rb_cheap_stats_initialize, 1);
|
495
|
+
rb_define_method(klass, "total", rb_cheap_stats_total, 0);
|
496
|
+
rb_define_method(klass, "min", rb_cheap_stats_min, 0);
|
497
|
+
rb_define_method(klass, "max", rb_cheap_stats_max, 0);
|
498
|
+
rb_define_method(klass, "q1", rb_cheap_stats_q1, 0);
|
499
|
+
rb_define_method(klass, "q3", rb_cheap_stats_q3, 0);
|
500
|
+
rb_define_method(klass, "mean", rb_cheap_stats_mean, 0);
|
501
|
+
rb_define_method(klass, "median", rb_cheap_stats_median, 0);
|
502
|
+
rb_define_method(klass, "variance", rb_cheap_stats_variance, 0);
|
503
|
+
rb_define_method(klass, "std", rb_cheap_stats_std, 0);
|
504
|
+
rb_define_method(klass, "cdf", rb_cheap_stats_cdf, 1);
|
505
|
+
rb_define_method(klass, "moment", rb_cheap_stats_moment, 1);
|
506
|
+
rb_define_method(klass, "central_moment", rb_cheap_stats_central_moment, 1);
|
507
|
+
rb_define_method(klass, "std_moment", rb_cheap_stats_std_moment, 1);
|
508
|
+
rb_define_method(klass, "skewness", rb_cheap_stats_skewness, 0);
|
509
|
+
rb_define_method(klass, "pearson_skewness",rb_cheap_stats_pearson_skewness,0);
|
510
|
+
|
511
|
+
rb_alias(klass, rb_intern("average"), rb_intern("mean"));
|
512
|
+
rb_alias(klass, rb_intern("sigma"), rb_intern("std"));
|
513
|
+
}
|
data/lib/cheap_stats.rb
ADDED
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cheap-stats
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Hiroshi Kuwagata
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-04-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake-compiler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A cheaper statistics library.
|
56
|
+
email:
|
57
|
+
- kgt9221@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions:
|
60
|
+
- ext/cheap_stats/extconf.rb
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- Gemfile
|
65
|
+
- LICENSE
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- cheap-stats.gemspec
|
69
|
+
- ext/cheap_stats/cheap_stats.c
|
70
|
+
- ext/cheap_stats/cheap_stats.h
|
71
|
+
- ext/cheap_stats/extconf.rb
|
72
|
+
- ext/cheap_stats/rb_cheap_stats.c
|
73
|
+
- lib/cheap_stats.rb
|
74
|
+
- lib/cheap_stats/version.rb
|
75
|
+
homepage: https://github.com/kwgt/cheap-stats
|
76
|
+
licenses:
|
77
|
+
- MIT
|
78
|
+
metadata:
|
79
|
+
homepage_uri: https://github.com/kwgt/cheap-stats
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 2.4.0
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
requirements: []
|
95
|
+
rubygems_version: 3.0.1
|
96
|
+
signing_key:
|
97
|
+
specification_version: 4
|
98
|
+
summary: A cheaper statistics library.
|
99
|
+
test_files: []
|