This repository has been archived by the owner on Sep 10, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathpercentile.hhs
115 lines (93 loc) · 3.18 KB
/
percentile.hhs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/**
* @Author Jianan Lin (林家南)
* @param input - an array, matrix, tensor to get the percentile
* @param x - percentage probability from interval [0, 100]
* @returns - 1-d array from the input[0] to input[(0.01 * probability * length)]
*
*/
function percentile(input, x = 100) {
*import math: ndim
*import math: deep_copy
*import math: flatten
let sort_array = [];
if (arguments.length === 0) {
throw new Error('Exception occurred in percentile - no argument given');
}
// quantile([1, 2, 3], 0, ???)
if (arguments.length > 2) {
throw new Error('Exception occurred in percentile - wrong argument number');
}
if (!(typeof x === 'number') || x < 0 || x > 100) {
throw new Error('Exception occurred in percentile - argument[1] must belong to interval [0, 100]');
}
if (!(Array.isArray(input)) && !(input instanceof Mat) && !(input instanceof Tensor)) {
throw new Error('Exception occurred in percentile - argument[0] must be an array, matrix or tensor');
}
let in_type = (input instanceof Mat) || (input instanceof Tensor);
let raw_in = in_type ? input.clone().val : deep_copy(input);
if (ndim(raw_in) > 1) {
raw_in = flatten(raw_in);
}
sort_array = private_quick_sort(raw_in);
x = x / 100;
let length = sort_array.length;
if (length === 0) {
throw new Error('Exception occurred in percentile - argument[0] cannot be empty');
}
let size = mathjs.round(length * x);
if (size < 1) {
return [sort_array[0]];
}
else {
let result = sort_array.slice(0, size);
return result;
}
// when we use this function, we have ensured that input is an array
function private_quick_sort(input) {
// if the length is less than 10, then use insert sort
if (input.length < 10) {
return private_insert_sort(input);
}
let borderline = (input[0] + input[input.length - 1]) / 2;
let L = [], M = [], R = [];
// divide the elements into left and right
for (let i = 0; i < input.length; i++) {
if (input[i] < borderline) {
L.push(input[i]);
}
else if (input[i] == borderline) {
M.push(input[i]);
}
else {
R.push(input[i]);
}
}
// recursion
L = private_quick_sort(L);
R = private_quick_sort(R);
let result = L.concat(M).concat(R);
return result;
}
// when we use this function, we have ensured that input is an array
function private_insert_sort(input) {
// if the length is 0 or 1
if (input.length <= 1) {
return input;
}
// insert part
for (let i = 1; i < input.length; i++) {
// find the position to insert
let j = 0;
while (input[j] <= input[i] && j < i) {
j++;
}
// move the element
let temp = input[i];
for (let k = i; k > j; k--) {
input[k] = input[k - 1];
}
input[j] = temp;
}
return input;
}
}