oakscriptjs 0.9.5 → 0.9.6
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.
- package/dist/cjs/array/index.d.ts +84 -27
- package/dist/cjs/array/index.d.ts.map +1 -1
- package/dist/cjs/array/index.js +235 -78
- package/dist/cjs/array/index.js.map +3 -3
- package/dist/cjs/callsite/index.d.ts +81 -2
- package/dist/cjs/callsite/index.d.ts.map +1 -1
- package/dist/cjs/callsite/index.js +62 -1
- package/dist/cjs/callsite/index.js.map +2 -2
- package/dist/cjs/color/index.d.ts +7 -3
- package/dist/cjs/color/index.d.ts.map +1 -1
- package/dist/cjs/color/index.js +6 -1
- package/dist/cjs/color/index.js.map +2 -2
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/label/index.d.ts.map +1 -1
- package/dist/cjs/label/index.js +2 -1
- package/dist/cjs/label/index.js.map +2 -2
- package/dist/cjs/linefill/index.d.ts.map +1 -1
- package/dist/cjs/linefill/index.js +1 -0
- package/dist/cjs/linefill/index.js.map +2 -2
- package/dist/cjs/math/index.d.ts +76 -21
- package/dist/cjs/math/index.d.ts.map +1 -1
- package/dist/cjs/math/index.js +155 -41
- package/dist/cjs/math/index.js.map +3 -3
- package/dist/cjs/matrix/index.d.ts.map +1 -1
- package/dist/cjs/matrix/index.js +42 -36
- package/dist/cjs/matrix/index.js.map +2 -2
- package/dist/cjs/runtime/series.d.ts +9 -0
- package/dist/cjs/runtime/series.d.ts.map +1 -1
- package/dist/cjs/runtime/series.js +16 -2
- package/dist/cjs/runtime/series.js.map +2 -2
- package/dist/cjs/script/index.d.ts +15 -31
- package/dist/cjs/script/index.d.ts.map +1 -1
- package/dist/cjs/script/index.js +32 -0
- package/dist/cjs/script/index.js.map +2 -2
- package/dist/cjs/session/calendar.d.ts.map +1 -1
- package/dist/cjs/session/calendar.js +15 -2
- package/dist/cjs/session/calendar.js.map +2 -2
- package/dist/cjs/str/index.d.ts +50 -38
- package/dist/cjs/str/index.d.ts.map +1 -1
- package/dist/cjs/str/index.js +43 -15
- package/dist/cjs/str/index.js.map +2 -2
- package/dist/cjs/str/messageformat.d.ts +2 -1
- package/dist/cjs/str/messageformat.d.ts.map +1 -1
- package/dist/cjs/str/messageformat.js +4 -1
- package/dist/cjs/str/messageformat.js.map +2 -2
- package/dist/cjs/str/numberformat.d.ts +4 -0
- package/dist/cjs/str/numberformat.d.ts.map +1 -1
- package/dist/cjs/str/numberformat.js +26 -4
- package/dist/cjs/str/numberformat.js.map +3 -3
- package/dist/cjs/ta/index.d.ts +86 -43
- package/dist/cjs/ta/index.d.ts.map +1 -1
- package/dist/cjs/ta/index.js +173 -267
- package/dist/cjs/ta/index.js.map +3 -3
- package/dist/cjs/ta/running-sum.d.ts +54 -2
- package/dist/cjs/ta/running-sum.d.ts.map +1 -1
- package/dist/cjs/ta/running-sum.js +132 -52
- package/dist/cjs/ta/running-sum.js.map +2 -2
- package/dist/cjs/ta-series.d.ts +4 -4
- package/dist/cjs/ta-series.d.ts.map +1 -1
- package/dist/cjs/ta-series.js +4 -3
- package/dist/cjs/ta-series.js.map +2 -2
- package/dist/cjs/time/datestring.d.ts +1 -0
- package/dist/cjs/time/datestring.d.ts.map +1 -1
- package/dist/cjs/time/datestring.js +7 -0
- package/dist/cjs/time/datestring.js.map +2 -2
- package/dist/cjs/time/index.d.ts.map +1 -1
- package/dist/cjs/time/index.js +2 -1
- package/dist/cjs/time/index.js.map +2 -2
- package/dist/cjs/time/session.d.ts +28 -9
- package/dist/cjs/time/session.d.ts.map +1 -1
- package/dist/cjs/time/session.js +74 -28
- package/dist/cjs/time/session.js.map +2 -2
- package/dist/cjs/time/timezone.d.ts +5 -0
- package/dist/cjs/time/timezone.d.ts.map +1 -1
- package/dist/cjs/time/timezone.js +15 -1
- package/dist/cjs/time/timezone.js.map +2 -2
- package/dist/esm/array/index.d.ts +84 -27
- package/dist/esm/array/index.d.ts.map +1 -1
- package/dist/esm/array/index.js +373 -111
- package/dist/esm/array/index.js.map +1 -1
- package/dist/esm/callsite/index.d.ts +81 -2
- package/dist/esm/callsite/index.d.ts.map +1 -1
- package/dist/esm/callsite/index.js +145 -3
- package/dist/esm/callsite/index.js.map +1 -1
- package/dist/esm/color/index.d.ts +7 -3
- package/dist/esm/color/index.d.ts.map +1 -1
- package/dist/esm/color/index.js +15 -3
- package/dist/esm/color/index.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/label/index.d.ts.map +1 -1
- package/dist/esm/label/index.js +2 -1
- package/dist/esm/label/index.js.map +1 -1
- package/dist/esm/linefill/index.d.ts.map +1 -1
- package/dist/esm/linefill/index.js +3 -0
- package/dist/esm/linefill/index.js.map +1 -1
- package/dist/esm/math/index.d.ts +76 -21
- package/dist/esm/math/index.d.ts.map +1 -1
- package/dist/esm/math/index.js +227 -61
- package/dist/esm/math/index.js.map +1 -1
- package/dist/esm/matrix/index.d.ts.map +1 -1
- package/dist/esm/matrix/index.js +57 -43
- package/dist/esm/matrix/index.js.map +1 -1
- package/dist/esm/runtime/series.d.ts +9 -0
- package/dist/esm/runtime/series.d.ts.map +1 -1
- package/dist/esm/runtime/series.js +18 -1
- package/dist/esm/runtime/series.js.map +1 -1
- package/dist/esm/script/index.d.ts +15 -31
- package/dist/esm/script/index.d.ts.map +1 -1
- package/dist/esm/script/index.js +44 -1
- package/dist/esm/script/index.js.map +1 -1
- package/dist/esm/session/calendar.d.ts.map +1 -1
- package/dist/esm/session/calendar.js +22 -2
- package/dist/esm/session/calendar.js.map +1 -1
- package/dist/esm/str/index.d.ts +50 -38
- package/dist/esm/str/index.d.ts.map +1 -1
- package/dist/esm/str/index.js +103 -52
- package/dist/esm/str/index.js.map +1 -1
- package/dist/esm/str/messageformat.d.ts +2 -1
- package/dist/esm/str/messageformat.d.ts.map +1 -1
- package/dist/esm/str/messageformat.js +7 -2
- package/dist/esm/str/messageformat.js.map +1 -1
- package/dist/esm/str/numberformat.d.ts +4 -0
- package/dist/esm/str/numberformat.d.ts.map +1 -1
- package/dist/esm/str/numberformat.js +38 -4
- package/dist/esm/str/numberformat.js.map +1 -1
- package/dist/esm/ta/index.d.ts +86 -43
- package/dist/esm/ta/index.d.ts.map +1 -1
- package/dist/esm/ta/index.js +296 -348
- package/dist/esm/ta/index.js.map +1 -1
- package/dist/esm/ta/running-sum.d.ts +54 -2
- package/dist/esm/ta/running-sum.d.ts.map +1 -1
- package/dist/esm/ta/running-sum.js +166 -71
- package/dist/esm/ta/running-sum.js.map +1 -1
- package/dist/esm/ta-series.d.ts +4 -4
- package/dist/esm/ta-series.d.ts.map +1 -1
- package/dist/esm/ta-series.js +5 -4
- package/dist/esm/ta-series.js.map +1 -1
- package/dist/esm/time/datestring.d.ts +1 -0
- package/dist/esm/time/datestring.d.ts.map +1 -1
- package/dist/esm/time/datestring.js +12 -0
- package/dist/esm/time/datestring.js.map +1 -1
- package/dist/esm/time/index.d.ts.map +1 -1
- package/dist/esm/time/index.js +3 -1
- package/dist/esm/time/index.js.map +1 -1
- package/dist/esm/time/session.d.ts +28 -9
- package/dist/esm/time/session.d.ts.map +1 -1
- package/dist/esm/time/session.js +113 -42
- package/dist/esm/time/session.js.map +1 -1
- package/dist/esm/time/timezone.d.ts +5 -0
- package/dist/esm/time/timezone.d.ts.map +1 -1
- package/dist/esm/time/timezone.js +21 -1
- package/dist/esm/time/timezone.js.map +1 -1
- package/package.json +1 -1
- package/src/array/index.ts +352 -127
- package/src/callsite/index.ts +147 -3
- package/src/color/index.ts +15 -5
- package/src/index.ts +1 -1
- package/src/label/index.ts +2 -1
- package/src/linefill/index.ts +2 -0
- package/src/math/index.ts +256 -74
- package/src/matrix/index.ts +52 -52
- package/src/runtime/series.ts +22 -1
- package/src/script/index.ts +53 -1
- package/src/session/calendar.ts +22 -2
- package/src/str/index.ts +95 -51
- package/src/str/messageformat.ts +7 -2
- package/src/str/numberformat.ts +39 -4
- package/src/ta/index.ts +306 -386
- package/src/ta/running-sum.ts +187 -74
- package/src/ta-series.ts +8 -7
- package/src/time/datestring.ts +10 -0
- package/src/time/index.ts +3 -1
- package/src/time/session.ts +97 -47
- package/src/time/timezone.ts +21 -1
package/dist/cjs/array/index.js
CHANGED
|
@@ -85,11 +85,27 @@ function new_array(size2 = 0, initial_value) {
|
|
|
85
85
|
function size(id) {
|
|
86
86
|
return id.length;
|
|
87
87
|
}
|
|
88
|
+
function isNa(v) {
|
|
89
|
+
return v === void 0 || v === null || typeof v === "number" && Number.isNaN(v);
|
|
90
|
+
}
|
|
91
|
+
function naOf(id) {
|
|
92
|
+
return id.length === 0 || typeof id[0] === "number" ? NaN : void 0;
|
|
93
|
+
}
|
|
94
|
+
function position(name, id, index, extra = 0) {
|
|
95
|
+
const i = Math.trunc(index);
|
|
96
|
+
const n = id.length;
|
|
97
|
+
if (i < -n || i >= n + extra) {
|
|
98
|
+
throw new Error(`array.${name}: index ${i} is out of bounds, array size is ${n}`);
|
|
99
|
+
}
|
|
100
|
+
return i < 0 ? i + n : i;
|
|
101
|
+
}
|
|
88
102
|
function get(id, index) {
|
|
89
|
-
return id
|
|
103
|
+
if (Number.isNaN(index)) return naOf(id);
|
|
104
|
+
return id[position("get", id, index)];
|
|
90
105
|
}
|
|
91
106
|
function set(id, index, value) {
|
|
92
|
-
|
|
107
|
+
if (Number.isNaN(index)) return;
|
|
108
|
+
id[position("set", id, index)] = value;
|
|
93
109
|
}
|
|
94
110
|
function push(id, value) {
|
|
95
111
|
id.push(value);
|
|
@@ -107,25 +123,46 @@ function clear(id) {
|
|
|
107
123
|
id.length = 0;
|
|
108
124
|
}
|
|
109
125
|
function insert(id, index, value) {
|
|
110
|
-
|
|
126
|
+
if (Number.isNaN(index)) {
|
|
127
|
+
id.push(value);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
id.splice(position("insert", id, index, 1), 0, value);
|
|
111
131
|
}
|
|
112
132
|
function remove(id, index) {
|
|
113
|
-
|
|
133
|
+
if (Number.isNaN(index)) return naOf(id);
|
|
134
|
+
return id.splice(position("remove", id, index), 1)[0];
|
|
135
|
+
}
|
|
136
|
+
function pineEqual(a, b) {
|
|
137
|
+
if (isNa(a) || isNa(b)) return false;
|
|
138
|
+
if (a === b) return true;
|
|
139
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
140
|
+
const d = a - b;
|
|
141
|
+
return -1e-10 <= d && d <= 1e-10;
|
|
142
|
+
}
|
|
143
|
+
return false;
|
|
114
144
|
}
|
|
115
145
|
function includes(id, value) {
|
|
116
|
-
return id
|
|
146
|
+
return indexof(id, value) >= 0;
|
|
117
147
|
}
|
|
118
148
|
function indexof(id, value) {
|
|
119
|
-
|
|
149
|
+
for (let i = 0; i < id.length; i++) {
|
|
150
|
+
if (pineEqual(id[i], value)) return i;
|
|
151
|
+
}
|
|
152
|
+
return -1;
|
|
120
153
|
}
|
|
121
154
|
function lastindexof(id, value) {
|
|
122
|
-
|
|
155
|
+
for (let i = id.length - 1; i >= 0; i--) {
|
|
156
|
+
if (pineEqual(id[i], value)) return i;
|
|
157
|
+
}
|
|
158
|
+
return -1;
|
|
123
159
|
}
|
|
124
160
|
function copy(id) {
|
|
125
161
|
return [...id];
|
|
126
162
|
}
|
|
127
163
|
function concat(id1, id2) {
|
|
128
|
-
|
|
164
|
+
for (const v of Array.from(id2)) id1.push(v);
|
|
165
|
+
return id1;
|
|
129
166
|
}
|
|
130
167
|
function join(id, separator = ",") {
|
|
131
168
|
return id.join(separator);
|
|
@@ -134,64 +171,162 @@ function reverse(id) {
|
|
|
134
171
|
id.reverse();
|
|
135
172
|
}
|
|
136
173
|
function slice(id, index_from, index_to) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
174
|
+
const n = id.length;
|
|
175
|
+
const start = Number.isNaN(index_from) ? 0 : Math.trunc(index_from);
|
|
176
|
+
const stop = index_to === void 0 || Number.isNaN(index_to) ? n : Math.trunc(index_to);
|
|
177
|
+
if (start < 0 || start >= n) throw new Error(`array.slice: index ${start} is out of bounds, array size is ${n}`);
|
|
178
|
+
if (stop < 0 || stop > n) throw new Error(`array.slice: index ${stop} is out of bounds, array size is ${n}`);
|
|
179
|
+
if (start > stop) throw new Error(`array.slice: index_from ${start} is greater than index_to ${stop}`);
|
|
180
|
+
return sliceView(id, start, stop - start);
|
|
181
|
+
}
|
|
182
|
+
function indexKey(p) {
|
|
183
|
+
if (typeof p !== "string") return -1;
|
|
184
|
+
const i = Number(p);
|
|
185
|
+
return Number.isInteger(i) && i >= 0 && String(i) === p ? i : -1;
|
|
186
|
+
}
|
|
187
|
+
function sliceView(parent, start, size2) {
|
|
188
|
+
const resize = (target) => {
|
|
189
|
+
if (target > size2) parent.splice(start + size2, 0, ...Array(target - size2).fill(void 0));
|
|
190
|
+
else if (target < size2) parent.splice(start + target, size2 - target);
|
|
191
|
+
size2 = target;
|
|
192
|
+
};
|
|
193
|
+
return new Proxy([], {
|
|
194
|
+
get(target, p, receiver) {
|
|
195
|
+
const i = indexKey(p);
|
|
196
|
+
if (i >= 0) return i < size2 ? parent[start + i] : void 0;
|
|
197
|
+
if (p === "length") return size2;
|
|
198
|
+
return Reflect.get(target, p, receiver);
|
|
199
|
+
},
|
|
200
|
+
set(target, p, value, receiver) {
|
|
201
|
+
const i = indexKey(p);
|
|
202
|
+
if (i >= 0) {
|
|
203
|
+
if (i >= size2) resize(i + 1);
|
|
204
|
+
parent[start + i] = value;
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
if (p === "length") {
|
|
208
|
+
resize(Number(value));
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
return Reflect.set(target, p, value, receiver);
|
|
212
|
+
},
|
|
213
|
+
has(target, p) {
|
|
214
|
+
const i = indexKey(p);
|
|
215
|
+
return i >= 0 ? i < size2 : Reflect.has(target, p);
|
|
216
|
+
},
|
|
217
|
+
// Array methods delete the slots past the new end before they set the length, which does the removal.
|
|
218
|
+
deleteProperty(target, p) {
|
|
219
|
+
return indexKey(p) >= 0 ? true : Reflect.deleteProperty(target, p);
|
|
220
|
+
},
|
|
221
|
+
ownKeys(target) {
|
|
222
|
+
return [...Array.from({ length: size2 }, (_, i) => String(i)), ...Reflect.ownKeys(target)];
|
|
223
|
+
},
|
|
224
|
+
getOwnPropertyDescriptor(target, p) {
|
|
225
|
+
const i = indexKey(p);
|
|
226
|
+
if (i >= 0) {
|
|
227
|
+
return i < size2 ? { value: parent[start + i], writable: true, enumerable: true, configurable: true } : void 0;
|
|
228
|
+
}
|
|
229
|
+
if (p === "length") return { value: size2, writable: true, enumerable: false, configurable: false };
|
|
230
|
+
return Reflect.getOwnPropertyDescriptor(target, p);
|
|
145
231
|
}
|
|
146
232
|
});
|
|
147
233
|
}
|
|
234
|
+
function sortedPositions(id, order) {
|
|
235
|
+
const values = [];
|
|
236
|
+
const nas = [];
|
|
237
|
+
for (let i = 0; i < id.length; i++) (isNa(id[i]) ? nas : values).push(i);
|
|
238
|
+
values.sort((a, b) => {
|
|
239
|
+
const x = id[a];
|
|
240
|
+
const y = id[b];
|
|
241
|
+
return x < y ? -1 : x > y ? 1 : 0;
|
|
242
|
+
});
|
|
243
|
+
const naFirst = values.length > 0 && typeof id[values[0]] === "string";
|
|
244
|
+
const positions = naFirst ? [...nas, ...values] : [...values, ...nas];
|
|
245
|
+
if (order === "desc" || order === "descending") positions.reverse();
|
|
246
|
+
return positions;
|
|
247
|
+
}
|
|
248
|
+
function sort(id, order = "asc") {
|
|
249
|
+
const sorted = sortedPositions(id, order).map((p) => id[p]);
|
|
250
|
+
for (let i = 0; i < sorted.length; i++) id[i] = sorted[i];
|
|
251
|
+
}
|
|
148
252
|
function sum(id) {
|
|
149
|
-
|
|
253
|
+
let total = 0;
|
|
254
|
+
let count = 0;
|
|
255
|
+
for (const v of id) {
|
|
256
|
+
if (Number.isNaN(v)) continue;
|
|
257
|
+
count++;
|
|
258
|
+
total += v;
|
|
259
|
+
if (Math.abs(total) <= 1e-10) total = 0;
|
|
260
|
+
}
|
|
261
|
+
return count ? total : NaN;
|
|
150
262
|
}
|
|
151
263
|
function avg(id) {
|
|
152
264
|
const values = id.filter((v) => !Number.isNaN(v));
|
|
153
265
|
return values.length ? values.reduce((a, b) => a + b, 0) / values.length : NaN;
|
|
154
266
|
}
|
|
267
|
+
function nthValue(name, id, nth, compare) {
|
|
268
|
+
const rank = Number.isNaN(nth) ? 0 : Math.trunc(nth);
|
|
269
|
+
const values = id.filter((v) => !Number.isNaN(v));
|
|
270
|
+
if (!values.length) return NaN;
|
|
271
|
+
if (rank < 0 || rank >= id.length) {
|
|
272
|
+
throw new Error(`array.${name}: nth ${rank} is out of bounds, array size is ${id.length}`);
|
|
273
|
+
}
|
|
274
|
+
values.sort(compare);
|
|
275
|
+
return values[Math.min(rank, values.length - 1)];
|
|
276
|
+
}
|
|
155
277
|
function min(id, nth = 0) {
|
|
156
|
-
|
|
157
|
-
return values.length ? values[Math.min(nth, values.length - 1)] : NaN;
|
|
278
|
+
return nthValue("min", id, nth, (a, b) => a - b);
|
|
158
279
|
}
|
|
159
280
|
function max(id, nth = 0) {
|
|
160
|
-
|
|
161
|
-
return values.length ? values[Math.min(nth, values.length - 1)] : NaN;
|
|
281
|
+
return nthValue("max", id, nth, (a, b) => b - a);
|
|
162
282
|
}
|
|
163
283
|
function median(id) {
|
|
164
|
-
const sorted =
|
|
284
|
+
const sorted = id.filter((v) => !Number.isNaN(v)).sort((a, b) => a - b);
|
|
285
|
+
if (!sorted.length) return NaN;
|
|
165
286
|
const mid = Math.floor(sorted.length / 2);
|
|
166
287
|
return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
|
|
167
288
|
}
|
|
168
289
|
function mode(id) {
|
|
169
290
|
const frequency = /* @__PURE__ */ new Map();
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
291
|
+
for (const v of id) {
|
|
292
|
+
if (!Number.isNaN(v)) frequency.set(v, (frequency.get(v) ?? 0) + 1);
|
|
293
|
+
}
|
|
294
|
+
let best = NaN;
|
|
295
|
+
let bestCount = 0;
|
|
296
|
+
for (const [v, count] of frequency) {
|
|
297
|
+
if (count > bestCount || count === bestCount && v < best) {
|
|
298
|
+
best = v;
|
|
299
|
+
bestCount = count;
|
|
178
300
|
}
|
|
179
301
|
}
|
|
180
|
-
return
|
|
302
|
+
return best;
|
|
181
303
|
}
|
|
182
304
|
function stdev(id, biased = true) {
|
|
183
305
|
return Math.sqrt(variance(id, biased));
|
|
184
306
|
}
|
|
307
|
+
function moments(values) {
|
|
308
|
+
let p = 0;
|
|
309
|
+
let q = 0;
|
|
310
|
+
for (const v of values) p += v;
|
|
311
|
+
for (const v of values) q += v * v;
|
|
312
|
+
return [p, q];
|
|
313
|
+
}
|
|
185
314
|
function variance(id, biased = true) {
|
|
186
315
|
const values = id.filter((v) => !Number.isNaN(v));
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
316
|
+
const n = values.length;
|
|
317
|
+
if (!n) return NaN;
|
|
318
|
+
if (n < 2) return biased ? 0 : NaN;
|
|
319
|
+
const [p, q] = moments(values);
|
|
320
|
+
const mean = p / n;
|
|
321
|
+
return biased ? Math.max(0, q / n - mean * mean) : Math.max(0, q / (n - 1) - p / (n - 1) * mean);
|
|
191
322
|
}
|
|
192
323
|
function fill(id, value, index_from = 0, index_to) {
|
|
193
|
-
const
|
|
194
|
-
|
|
324
|
+
const start = index_from === void 0 || index_from === null || Number.isNaN(index_from) ? 0 : index_from;
|
|
325
|
+
const end = index_to === void 0 || index_to === null || Number.isNaN(index_to) ? id.length : index_to;
|
|
326
|
+
for (const i of [start, end]) {
|
|
327
|
+
if (i < 0 || i > id.length) throw new Error(`array.fill: index ${i} is out of bounds, array size is ${id.length}`);
|
|
328
|
+
}
|
|
329
|
+
for (let i = start; i < end; i++) {
|
|
195
330
|
id[i] = value;
|
|
196
331
|
}
|
|
197
332
|
}
|
|
@@ -199,9 +334,11 @@ function from(...values) {
|
|
|
199
334
|
return [...values];
|
|
200
335
|
}
|
|
201
336
|
function first(id) {
|
|
337
|
+
if (id.length === 0) throw new Error("Cannot call array.first() if array is empty");
|
|
202
338
|
return id[0];
|
|
203
339
|
}
|
|
204
340
|
function last(id) {
|
|
341
|
+
if (id.length === 0) throw new Error("Cannot call array.last() if array is empty");
|
|
205
342
|
return id[id.length - 1];
|
|
206
343
|
}
|
|
207
344
|
function some(id) {
|
|
@@ -290,85 +427,105 @@ function binary_search_rightmost(id, val) {
|
|
|
290
427
|
return at > 0 && compareSorted(id[at - 1], val) === 0 ? at - 1 : at;
|
|
291
428
|
}
|
|
292
429
|
function covariance(id1, id2, biased = true) {
|
|
293
|
-
if (id1.length === 0 || id2.length === 0) {
|
|
294
|
-
return NaN;
|
|
295
|
-
}
|
|
296
430
|
if (id1.length !== id2.length) {
|
|
297
431
|
return NaN;
|
|
298
432
|
}
|
|
299
|
-
const
|
|
300
|
-
const
|
|
301
|
-
|
|
433
|
+
const xs = [];
|
|
434
|
+
const ys = [];
|
|
435
|
+
for (let i = 0; i < id1.length; i++) {
|
|
436
|
+
if (Number.isNaN(id1[i]) || Number.isNaN(id2[i])) continue;
|
|
437
|
+
xs.push(id1[i]);
|
|
438
|
+
ys.push(id2[i]);
|
|
439
|
+
}
|
|
440
|
+
const n = xs.length;
|
|
441
|
+
if (!n || !biased && n < 2) return NaN;
|
|
442
|
+
let mean1 = 0;
|
|
443
|
+
let mean2 = 0;
|
|
444
|
+
for (let i = 0; i < n; i++) {
|
|
445
|
+
mean1 += xs[i];
|
|
446
|
+
mean2 += ys[i];
|
|
447
|
+
}
|
|
448
|
+
mean1 /= n;
|
|
449
|
+
mean2 /= n;
|
|
302
450
|
let sum2 = 0;
|
|
303
451
|
for (let i = 0; i < n; i++) {
|
|
304
|
-
sum2 += (
|
|
452
|
+
sum2 += (xs[i] - mean1) * (ys[i] - mean2);
|
|
305
453
|
}
|
|
306
|
-
|
|
307
|
-
return sum2 / divisor;
|
|
454
|
+
return sum2 / (biased ? n : n - 1);
|
|
308
455
|
}
|
|
309
456
|
function percentile_linear_interpolation(id, percentage) {
|
|
310
|
-
if (id.length === 0) {
|
|
457
|
+
if (id.length === 0 || Number.isNaN(percentage)) {
|
|
311
458
|
return NaN;
|
|
312
459
|
}
|
|
460
|
+
checkPercentage("percentile_linear_interpolation", percentage);
|
|
313
461
|
const s = sortedNaLast(id);
|
|
314
462
|
const n = s.length;
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if (pos
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
463
|
+
let pos = n * percentage / 100 + 0.5;
|
|
464
|
+
const nearest = Math.round(pos);
|
|
465
|
+
if (Math.abs(pos - nearest) < 1e-9) pos = nearest;
|
|
466
|
+
if (pos <= 1) return s[0];
|
|
467
|
+
if (pos >= n) return s[n - 1];
|
|
468
|
+
const lower = Math.floor(pos);
|
|
469
|
+
const frac = pos - lower;
|
|
470
|
+
if (frac === 0) return s[lower - 1];
|
|
471
|
+
if (Number.isNaN(s[n - 1])) return NaN;
|
|
472
|
+
return s[lower - 1] * (1 - frac) + s[lower] * frac;
|
|
322
473
|
}
|
|
323
474
|
function sortedNaLast(id) {
|
|
324
475
|
const numbers = id.filter((v) => !Number.isNaN(v)).sort((a, b) => a - b);
|
|
325
476
|
return [...numbers, ...Array(id.length - numbers.length).fill(NaN)];
|
|
326
477
|
}
|
|
478
|
+
function checkPercentage(name, percentage) {
|
|
479
|
+
if (!(percentage >= 0 && percentage <= 100)) {
|
|
480
|
+
throw new Error(`array.${name}: percentage ${percentage} must be between 0 and 100`);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
327
483
|
function percentile_nearest_rank(id, percentage) {
|
|
328
484
|
if (id.length === 0) {
|
|
329
485
|
return NaN;
|
|
330
486
|
}
|
|
487
|
+
const pct = Number.isNaN(percentage) ? 0 : percentage;
|
|
488
|
+
checkPercentage("percentile_nearest_rank", pct);
|
|
331
489
|
const s = sortedNaLast(id);
|
|
332
|
-
const rank = Math.min(s.length, Math.max(1, Math.ceil(
|
|
490
|
+
const rank = Math.min(s.length, Math.max(1, Math.ceil(pct * s.length / 100)));
|
|
333
491
|
return s[rank - 1];
|
|
334
492
|
}
|
|
335
493
|
function percentrank(id, index) {
|
|
336
|
-
|
|
494
|
+
const i = Number.isNaN(index) ? 0 : Math.trunc(index);
|
|
495
|
+
if (id.length === 0) {
|
|
337
496
|
return NaN;
|
|
338
497
|
}
|
|
339
|
-
|
|
340
|
-
|
|
498
|
+
if (i < 0 || i >= id.length) {
|
|
499
|
+
throw new Error(`array.percentrank: index ${i} is out of bounds, array size is ${id.length}`);
|
|
500
|
+
}
|
|
501
|
+
if (id.length === 1) {
|
|
502
|
+
return NaN;
|
|
503
|
+
}
|
|
504
|
+
const value = id[i];
|
|
505
|
+
if (Number.isNaN(value)) {
|
|
341
506
|
return NaN;
|
|
342
507
|
}
|
|
343
508
|
let count = 0;
|
|
344
|
-
for (
|
|
345
|
-
if (
|
|
346
|
-
count++;
|
|
347
|
-
}
|
|
509
|
+
for (const v of id) {
|
|
510
|
+
if (v <= value) count++;
|
|
348
511
|
}
|
|
349
|
-
return count / id.length
|
|
512
|
+
return (count - 1) * 100 / (id.length - 1);
|
|
350
513
|
}
|
|
351
514
|
function sort_indices(id, order = "asc") {
|
|
352
|
-
|
|
353
|
-
indices.sort((a, b) => {
|
|
354
|
-
if (order === "asc") {
|
|
355
|
-
return id[a] - id[b];
|
|
356
|
-
} else {
|
|
357
|
-
return id[b] - id[a];
|
|
358
|
-
}
|
|
359
|
-
});
|
|
360
|
-
return indices;
|
|
515
|
+
return sortedPositions(id, order);
|
|
361
516
|
}
|
|
362
517
|
function standardize(id) {
|
|
363
|
-
|
|
364
|
-
|
|
518
|
+
const values = id.filter((v) => !Number.isNaN(v));
|
|
519
|
+
if (!values.length) {
|
|
520
|
+
return id.map(() => NaN);
|
|
365
521
|
}
|
|
366
|
-
const
|
|
367
|
-
const
|
|
522
|
+
const [p, q] = moments(values);
|
|
523
|
+
const mean = p / values.length;
|
|
524
|
+
const stdDev = Math.sqrt(Math.max(0, q / values.length - mean * mean));
|
|
368
525
|
if (stdDev === 0) {
|
|
369
|
-
return id.map(() => NaN);
|
|
526
|
+
return id.map((v) => Number.isNaN(v) ? NaN : 1);
|
|
370
527
|
}
|
|
371
|
-
return id.map((
|
|
528
|
+
return id.map((v) => Number.isNaN(v) ? NaN : (v - mean) / stdDev);
|
|
372
529
|
}
|
|
373
530
|
function newtype(size2 = 0, initial_value) {
|
|
374
531
|
return new_array(size2, initial_value);
|