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