@mirascript/mirascript 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.
Files changed (191) hide show
  1. package/dist/chunk-5FQWUJIY.js +766 -0
  2. package/dist/chunk-5FQWUJIY.js.map +6 -0
  3. package/dist/chunk-BTDGMWFK.js +202 -0
  4. package/dist/chunk-BTDGMWFK.js.map +6 -0
  5. package/dist/chunk-DCXIWIW5.js +3419 -0
  6. package/dist/chunk-DCXIWIW5.js.map +6 -0
  7. package/dist/chunk-RAPJ3XLV.js +10 -0
  8. package/dist/chunk-RAPJ3XLV.js.map +6 -0
  9. package/dist/cli/execute.d.ts +4 -0
  10. package/dist/cli/execute.d.ts.map +1 -0
  11. package/dist/cli/index.d.ts +2 -0
  12. package/dist/cli/index.d.ts.map +1 -0
  13. package/dist/cli/index.js +191 -0
  14. package/dist/cli/index.js.map +6 -0
  15. package/dist/cli/print.d.ts +4 -0
  16. package/dist/cli/print.d.ts.map +1 -0
  17. package/dist/compiler/compile-bytecode.d.ts +12 -0
  18. package/dist/compiler/compile-bytecode.d.ts.map +1 -0
  19. package/dist/compiler/compile-fast.d.ts +7 -0
  20. package/dist/compiler/compile-fast.d.ts.map +1 -0
  21. package/dist/compiler/create-script.d.ts +7 -0
  22. package/dist/compiler/create-script.d.ts.map +1 -0
  23. package/dist/compiler/diagnostic.d.ts +56 -0
  24. package/dist/compiler/diagnostic.d.ts.map +1 -0
  25. package/dist/compiler/emit.d.ts +4 -0
  26. package/dist/compiler/emit.d.ts.map +1 -0
  27. package/dist/compiler/index.d.ts +13 -0
  28. package/dist/compiler/index.d.ts.map +1 -0
  29. package/dist/compiler/types.d.ts +16 -0
  30. package/dist/compiler/types.d.ts.map +1 -0
  31. package/dist/compiler/worker-manager.d.ts +6 -0
  32. package/dist/compiler/worker-manager.d.ts.map +1 -0
  33. package/dist/compiler/worker.d.ts +6 -0
  34. package/dist/compiler/worker.d.ts.map +1 -0
  35. package/dist/compiler/worker.js +34 -0
  36. package/dist/compiler/worker.js.map +6 -0
  37. package/dist/helpers/constants.d.ts +3 -0
  38. package/dist/helpers/constants.d.ts.map +1 -0
  39. package/dist/helpers/serialize.d.ts +45 -0
  40. package/dist/helpers/serialize.d.ts.map +1 -0
  41. package/dist/helpers/utils.d.ts +36 -0
  42. package/dist/helpers/utils.d.ts.map +1 -0
  43. package/dist/index.d.ts +4 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +61 -0
  46. package/dist/index.js.map +6 -0
  47. package/dist/subtle.d.ts +7 -0
  48. package/dist/subtle.d.ts.map +1 -0
  49. package/dist/subtle.js +30 -0
  50. package/dist/subtle.js.map +6 -0
  51. package/dist/vm/env.d.ts +3 -0
  52. package/dist/vm/env.d.ts.map +1 -0
  53. package/dist/vm/error.d.ts +11 -0
  54. package/dist/vm/error.d.ts.map +1 -0
  55. package/dist/vm/helpers.d.ts +21 -0
  56. package/dist/vm/helpers.d.ts.map +1 -0
  57. package/dist/vm/index.d.ts +5 -0
  58. package/dist/vm/index.d.ts.map +1 -0
  59. package/dist/vm/lib/_helpers.d.ts +35 -0
  60. package/dist/vm/lib/_helpers.d.ts.map +1 -0
  61. package/dist/vm/lib/_loader.d.ts +16 -0
  62. package/dist/vm/lib/_loader.d.ts.map +1 -0
  63. package/dist/vm/lib/global/bit.d.ts +9 -0
  64. package/dist/vm/lib/global/bit.d.ts.map +1 -0
  65. package/dist/vm/lib/global/debug.d.ts +5 -0
  66. package/dist/vm/lib/global/debug.d.ts.map +1 -0
  67. package/dist/vm/lib/global/index.d.ts +10 -0
  68. package/dist/vm/lib/global/index.d.ts.map +1 -0
  69. package/dist/vm/lib/global/json.d.ts +4 -0
  70. package/dist/vm/lib/global/json.d.ts.map +1 -0
  71. package/dist/vm/lib/global/math-additional.d.ts +3 -0
  72. package/dist/vm/lib/global/math-additional.d.ts.map +1 -0
  73. package/dist/vm/lib/global/math-arr.d.ts +8 -0
  74. package/dist/vm/lib/global/math-arr.d.ts.map +1 -0
  75. package/dist/vm/lib/global/math-const.d.ts +3 -0
  76. package/dist/vm/lib/global/math-const.d.ts.map +1 -0
  77. package/dist/vm/lib/global/math-unary.d.ts +29 -0
  78. package/dist/vm/lib/global/math-unary.d.ts.map +1 -0
  79. package/dist/vm/lib/global/math.d.ts +9 -0
  80. package/dist/vm/lib/global/math.d.ts.map +1 -0
  81. package/dist/vm/lib/global/mod/index.d.ts +3 -0
  82. package/dist/vm/lib/global/mod/index.d.ts.map +1 -0
  83. package/dist/vm/lib/global/mod/matrix.d.ts +16 -0
  84. package/dist/vm/lib/global/mod/matrix.d.ts.map +1 -0
  85. package/dist/vm/lib/global/sequence/all-any.d.ts +4 -0
  86. package/dist/vm/lib/global/sequence/all-any.d.ts.map +1 -0
  87. package/dist/vm/lib/global/sequence/entries.d.ts +12 -0
  88. package/dist/vm/lib/global/sequence/entries.d.ts.map +1 -0
  89. package/dist/vm/lib/global/sequence/find.d.ts +10 -0
  90. package/dist/vm/lib/global/sequence/find.d.ts.map +1 -0
  91. package/dist/vm/lib/global/sequence/flatten.d.ts +3 -0
  92. package/dist/vm/lib/global/sequence/flatten.d.ts.map +1 -0
  93. package/dist/vm/lib/global/sequence/index.d.ts +12 -0
  94. package/dist/vm/lib/global/sequence/index.d.ts.map +1 -0
  95. package/dist/vm/lib/global/sequence/len.d.ts +3 -0
  96. package/dist/vm/lib/global/sequence/len.d.ts.map +1 -0
  97. package/dist/vm/lib/global/sequence/map-filter.d.ts +9 -0
  98. package/dist/vm/lib/global/sequence/map-filter.d.ts.map +1 -0
  99. package/dist/vm/lib/global/sequence/repeat.d.ts +4 -0
  100. package/dist/vm/lib/global/sequence/repeat.d.ts.map +1 -0
  101. package/dist/vm/lib/global/sequence/reverse.d.ts +3 -0
  102. package/dist/vm/lib/global/sequence/reverse.d.ts.map +1 -0
  103. package/dist/vm/lib/global/sequence/sort.d.ts +5 -0
  104. package/dist/vm/lib/global/sequence/sort.d.ts.map +1 -0
  105. package/dist/vm/lib/global/sequence/with.d.ts +5 -0
  106. package/dist/vm/lib/global/sequence/with.d.ts.map +1 -0
  107. package/dist/vm/lib/global/sequence/zip.d.ts +4 -0
  108. package/dist/vm/lib/global/sequence/zip.d.ts.map +1 -0
  109. package/dist/vm/lib/global/string.d.ts +12 -0
  110. package/dist/vm/lib/global/string.d.ts.map +1 -0
  111. package/dist/vm/lib/global/time.d.ts +15 -0
  112. package/dist/vm/lib/global/time.d.ts.map +1 -0
  113. package/dist/vm/lib/global/to-primitive.d.ts +6 -0
  114. package/dist/vm/lib/global/to-primitive.d.ts.map +1 -0
  115. package/dist/vm/operations.d.ts +49 -0
  116. package/dist/vm/operations.d.ts.map +1 -0
  117. package/dist/vm/types/checker.d.ts +30 -0
  118. package/dist/vm/types/checker.d.ts.map +1 -0
  119. package/dist/vm/types/context.d.ts +43 -0
  120. package/dist/vm/types/context.d.ts.map +1 -0
  121. package/dist/vm/types/extern.d.ts +32 -0
  122. package/dist/vm/types/extern.d.ts.map +1 -0
  123. package/dist/vm/types/function.d.ts +49 -0
  124. package/dist/vm/types/function.d.ts.map +1 -0
  125. package/dist/vm/types/index.d.ts +75 -0
  126. package/dist/vm/types/index.d.ts.map +1 -0
  127. package/dist/vm/types/module.d.ts +25 -0
  128. package/dist/vm/types/module.d.ts.map +1 -0
  129. package/dist/vm/types/script.d.ts +14 -0
  130. package/dist/vm/types/script.d.ts.map +1 -0
  131. package/dist/vm/types/wrapper.d.ts +25 -0
  132. package/dist/vm/types/wrapper.d.ts.map +1 -0
  133. package/package.json +55 -0
  134. package/src/cli/execute.ts +32 -0
  135. package/src/cli/index.ts +73 -0
  136. package/src/cli/print.ts +41 -0
  137. package/src/compiler/compile-bytecode.ts +65 -0
  138. package/src/compiler/compile-fast.ts +81 -0
  139. package/src/compiler/create-script.ts +34 -0
  140. package/src/compiler/diagnostic.ts +175 -0
  141. package/src/compiler/emit.ts +764 -0
  142. package/src/compiler/index.ts +67 -0
  143. package/src/compiler/types.ts +16 -0
  144. package/src/compiler/worker-manager.ts +60 -0
  145. package/src/compiler/worker.ts +37 -0
  146. package/src/helpers/constants.ts +3 -0
  147. package/src/helpers/serialize.ts +280 -0
  148. package/src/helpers/utils.ts +16 -0
  149. package/src/index.ts +3 -0
  150. package/src/subtle.ts +6 -0
  151. package/src/vm/env.ts +16 -0
  152. package/src/vm/error.ts +22 -0
  153. package/src/vm/helpers.ts +121 -0
  154. package/src/vm/index.ts +5 -0
  155. package/src/vm/lib/_helpers.ts +215 -0
  156. package/src/vm/lib/_loader.ts +51 -0
  157. package/src/vm/lib/global/bit.ts +93 -0
  158. package/src/vm/lib/global/debug.ts +36 -0
  159. package/src/vm/lib/global/index.ts +9 -0
  160. package/src/vm/lib/global/json.ts +45 -0
  161. package/src/vm/lib/global/math-additional.ts +71 -0
  162. package/src/vm/lib/global/math-arr.ts +62 -0
  163. package/src/vm/lib/global/math-const.ts +2 -0
  164. package/src/vm/lib/global/math-unary.ts +171 -0
  165. package/src/vm/lib/global/math.ts +27 -0
  166. package/src/vm/lib/global/mod/index.ts +4 -0
  167. package/src/vm/lib/global/mod/matrix.ts +579 -0
  168. package/src/vm/lib/global/sequence/all-any.ts +73 -0
  169. package/src/vm/lib/global/sequence/entries.ts +67 -0
  170. package/src/vm/lib/global/sequence/find.ts +49 -0
  171. package/src/vm/lib/global/sequence/flatten.ts +16 -0
  172. package/src/vm/lib/global/sequence/index.ts +11 -0
  173. package/src/vm/lib/global/sequence/len.ts +15 -0
  174. package/src/vm/lib/global/sequence/map-filter.ts +82 -0
  175. package/src/vm/lib/global/sequence/repeat.ts +28 -0
  176. package/src/vm/lib/global/sequence/reverse.ts +17 -0
  177. package/src/vm/lib/global/sequence/sort.ts +88 -0
  178. package/src/vm/lib/global/sequence/with.ts +43 -0
  179. package/src/vm/lib/global/sequence/zip.ts +40 -0
  180. package/src/vm/lib/global/string.ts +149 -0
  181. package/src/vm/lib/global/time.ts +73 -0
  182. package/src/vm/lib/global/to-primitive.ts +58 -0
  183. package/src/vm/operations.ts +497 -0
  184. package/src/vm/types/checker.ts +164 -0
  185. package/src/vm/types/context.ts +161 -0
  186. package/src/vm/types/extern.ts +166 -0
  187. package/src/vm/types/function.ts +136 -0
  188. package/src/vm/types/index.ts +124 -0
  189. package/src/vm/types/module.ts +40 -0
  190. package/src/vm/types/script.ts +18 -0
  191. package/src/vm/types/wrapper.ts +28 -0
@@ -0,0 +1,579 @@
1
+ import { isArray } from '../../../../helpers/utils.js';
2
+ import { Cp } from '../../../helpers.js';
3
+ import { $Add, $Call, $Div, $Mul, $Sub, $ToNumber } from '../../../operations.js';
4
+ import { isVmArray, isVmConst, type VmAny, type VmArray, type VmConst, type VmValue } from '../../../types/index.js';
5
+ import {
6
+ VmLib,
7
+ expectArray,
8
+ expectCallable,
9
+ expectConst,
10
+ required,
11
+ throwError,
12
+ getNumbers,
13
+ arrayLen,
14
+ map,
15
+ } from '../../_helpers.js';
16
+
17
+ /** 计算尺寸 */
18
+ function sizeImpl(matrix: VmValue): [] | [number] | [number, number] {
19
+ if (!isVmArray(matrix)) return [];
20
+ if (matrix.length === 0) return [0];
21
+
22
+ const numRows = matrix.length;
23
+ let numCols = 0;
24
+
25
+ for (const row of matrix) {
26
+ if (isVmArray(row)) {
27
+ numCols = Math.max(numCols, row.length);
28
+ } else {
29
+ return [numRows];
30
+ }
31
+ }
32
+
33
+ return [numRows, numCols];
34
+ }
35
+
36
+ /** 数组元素转为 number */
37
+ function num(v: VmConst | undefined): number {
38
+ return $ToNumber(v ?? null);
39
+ }
40
+
41
+ export const size = VmLib(
42
+ (matrix) => {
43
+ required('matrix', matrix, []);
44
+ return sizeImpl(matrix);
45
+ },
46
+ {
47
+ summary: '获取矩阵尺寸',
48
+ params: { matrix: '要获取尺寸的矩阵' },
49
+ paramsType: { matrix: 'any[][]' },
50
+ returnsType: '[number, number]',
51
+ examples: ['matrix.size([[1, 2], [3, 4]]) // [2, 2]'],
52
+ },
53
+ );
54
+
55
+ export const transpose = VmLib(
56
+ (matrix) => {
57
+ required('matrix', matrix, []);
58
+ const [numRows, numCols] = sizeImpl(matrix);
59
+ if (numRows == null || numCols == null) return matrix; // 一维数组或空数组无需转置
60
+
61
+ const transposed: VmConst[][] = [];
62
+ for (let j = 0; j < numCols; j++) {
63
+ Cp();
64
+ const tj = [];
65
+ for (let i = 0; i < numRows; i++) {
66
+ const row = (matrix as VmConst[][])[i] ?? null;
67
+ const item = row?.[j] ?? null;
68
+ tj[i] = item;
69
+ }
70
+ transposed[j] = tj;
71
+ }
72
+ return transposed;
73
+ },
74
+ {
75
+ summary: '转置矩阵',
76
+ params: { matrix: '要转置的矩阵' },
77
+ paramsType: { matrix: 'any[][]' },
78
+ returnsType: 'any[][]',
79
+ examples: ['matrix.transpose([[1, 2], [3, 4]]) // [[1, 3], [2, 4]]'],
80
+ },
81
+ );
82
+
83
+ /** 逐项操作 */
84
+ function entrywiseImpl(
85
+ a: VmConst,
86
+ b: VmConst,
87
+ f: (a: VmConst, b: VmConst) => VmConst,
88
+ vvf?: (va: readonly VmConst[], vb: readonly VmConst[], ar: number, br: number) => VmConst,
89
+ mmf?: (
90
+ ma: readonly VmConst[][],
91
+ mb: readonly VmConst[][],
92
+ ar: number,
93
+ ac: number,
94
+ br: number,
95
+ bc: number,
96
+ ) => VmConst,
97
+ vmf?: (va: readonly VmConst[], mb: readonly VmConst[][], al: number, br: number, bc: number) => VmConst,
98
+ mvf?: (ma: readonly VmConst[][], vb: readonly VmConst[], ar: number, ac: number, bl: number) => VmConst,
99
+ ): VmConst {
100
+ let [ar, ac] = sizeImpl(a);
101
+ let [br, bc] = sizeImpl(b);
102
+
103
+ if (ar == null) {
104
+ if (br == null) {
105
+ // s/s
106
+ return f(a, b);
107
+ } else if (bc == null) {
108
+ // s/v
109
+ const result: VmConst[] = [];
110
+ for (let r = 0; r < br; r++) {
111
+ const bItem = (b as VmConst[])[r] ?? null;
112
+ result[r] = f(a, bItem);
113
+ }
114
+ return result;
115
+ } else {
116
+ // s/m
117
+ const result: VmConst[][] = [];
118
+ for (let r = 0; r < br; r++) {
119
+ const bRow = (b as VmConst[][])[r] ?? [];
120
+ const rRow: VmConst[] = [];
121
+ result[r] = rRow;
122
+ for (let c = 0; c < bc; c++) {
123
+ const bItem = bRow[c] ?? null;
124
+ rRow[c] = f(a, bItem);
125
+ }
126
+ }
127
+ return result;
128
+ }
129
+ }
130
+ if (br == null) {
131
+ if (ac == null) {
132
+ // v/s
133
+ const result: VmConst[] = [];
134
+ for (let r = 0; r < ar; r++) {
135
+ const aItem = (a as VmConst[])[r] ?? null;
136
+ result[r] = f(aItem, b);
137
+ }
138
+ return result;
139
+ } else {
140
+ // m/s
141
+ const result: VmConst[][] = [];
142
+ for (let r = 0; r < ar; r++) {
143
+ const aRow = (a as VmConst[][])[r] ?? [];
144
+ const rRow: VmConst[] = [];
145
+ result[r] = rRow;
146
+ for (let c = 0; c < ac; c++) {
147
+ const aItem = aRow[c] ?? null;
148
+ rRow[c] = f(aItem, b);
149
+ }
150
+ }
151
+ return result;
152
+ }
153
+ }
154
+ if (ac == null && bc == null) {
155
+ // v/v
156
+ if (vvf != null) {
157
+ return vvf(a as VmConst[], b as VmConst[], ar, br);
158
+ }
159
+ const rr = Math.max(ar, br);
160
+ const result: VmConst[] = [];
161
+ for (let r = 0; r < rr; r++) {
162
+ const aItem = (a as VmConst[])[r] ?? null;
163
+ const bItem = (b as VmConst[])[r] ?? null;
164
+ result[r] = f(aItem, bItem);
165
+ }
166
+ return result;
167
+ }
168
+
169
+ // m/m (m/v v/m)
170
+ if (ac == null) {
171
+ // v/m
172
+ if (vmf != null) {
173
+ return vmf(a as VmConst[], b as VmConst[][], ar, br, bc!);
174
+ }
175
+ ac = ar!;
176
+ ar = 1;
177
+ a = [a];
178
+ }
179
+ if (bc == null) {
180
+ // m/v
181
+ if (mvf != null) {
182
+ return mvf(a as VmConst[][], b as VmConst[], ar, ac, br);
183
+ }
184
+ bc = br!;
185
+ br = 1;
186
+ b = [b];
187
+ }
188
+
189
+ if (mmf != null) {
190
+ return mmf(a as VmConst[][], b as VmConst[][], ar, ac, br, bc);
191
+ }
192
+ const rr = Math.max(ar, br);
193
+ const rc = Math.max(ac, bc);
194
+ const result: VmConst[][] = [];
195
+ for (let r = 0; r < rr; r++) {
196
+ const rRow: VmConst[] = [];
197
+ result[r] = rRow;
198
+ for (let c = 0; c < rc; c++) {
199
+ const aItem = (a as VmConst[][])[ar === 1 ? 0 : r]?.[ac === 1 ? 0 : c] ?? null;
200
+ const bItem = (b as VmConst[][])[br === 1 ? 0 : r]?.[bc === 1 ? 0 : c] ?? null;
201
+ rRow[c] = f(aItem, bItem);
202
+ }
203
+ }
204
+ return result;
205
+ }
206
+
207
+ export const entrywise = VmLib(
208
+ (a, b, f) => {
209
+ expectConst('a', a, null);
210
+ expectConst('b', b, null);
211
+ expectCallable('f', f, null);
212
+ return entrywiseImpl(a, b, (a, b) => {
213
+ Cp();
214
+ const ret = $Call(f, [a, b]);
215
+ if (!isVmConst(ret)) return null;
216
+ return ret;
217
+ });
218
+ },
219
+ {
220
+ summary: '逐项操作',
221
+ params: { a: '第一个操作数', b: '第二个操作数', f: '操作函数' },
222
+ paramsType: { a: 'any | any[] | any[][]', b: 'any | any[] | any[][]', f: 'fn(a: any, b: any) -> any' },
223
+ returnsType: 'any | any[] | any[][]',
224
+ examples: [`matrix.entrywise([1, 2], [3, 4], fn (x, y) { x + y }) // [4, 6]`],
225
+ },
226
+ );
227
+
228
+ export const add = VmLib(
229
+ (a, b) => {
230
+ expectConst('a', a, null);
231
+ expectConst('b', b, null);
232
+ return entrywiseImpl(a, b, $Add);
233
+ },
234
+ {
235
+ summary: '逐项相加',
236
+ params: { a: '第一个操作数', b: '第二个操作数' },
237
+ paramsType: { a: 'number | number[] | number[][]', b: 'number | number[] | number[][]' },
238
+ returnsType: 'number | number[] | number[][]',
239
+ examples: ['matrix.add([1, 2], [3, 4]) // [4, 6]'],
240
+ },
241
+ );
242
+
243
+ export const subtract = VmLib(
244
+ (a, b) => {
245
+ expectConst('a', a, null);
246
+ expectConst('b', b, null);
247
+ return entrywiseImpl(a, b, $Sub);
248
+ },
249
+ {
250
+ summary: '逐项相减',
251
+ params: { a: '第一个操作数', b: '第二个操作数' },
252
+ paramsType: { a: 'number | number[] | number[][]', b: 'number | number[] | number[][]' },
253
+ returnsType: 'number | number[] | number[][]',
254
+ examples: ['matrix.subtract([3, 4], [1, 2]) // [2, 2]'],
255
+ },
256
+ );
257
+
258
+ export const entrywise_multiply = VmLib(
259
+ (a, b) => {
260
+ expectConst('a', a, null);
261
+ expectConst('b', b, null);
262
+ return entrywiseImpl(a, b, $Mul);
263
+ },
264
+ {
265
+ summary: '逐项相乘',
266
+ params: { a: '第一个操作数', b: '第二个操作数' },
267
+ paramsType: { a: 'number | number[] | number[][]', b: 'number | number[] | number[][]' },
268
+ returnsType: 'number | number[] | number[][]',
269
+ examples: ['matrix.entrywise_multiply([1, 2], [3, 4]) // [3, 8]'],
270
+ },
271
+ );
272
+
273
+ export const entrywise_divide = VmLib(
274
+ (a, b) => {
275
+ expectConst('a', a, null);
276
+ expectConst('b', b, null);
277
+ return entrywiseImpl(a, b, $Div);
278
+ },
279
+ {
280
+ summary: '逐项相除',
281
+ params: { a: '第一个操作数', b: '第二个操作数' },
282
+ paramsType: { a: 'number | number[] | number[][]', b: 'number | number[] | number[][]' },
283
+ returnsType: 'number | number[] | number[][]',
284
+ examples: ['matrix.entrywise_divide([4, 6], [2, 3]) // [2, 2]'],
285
+ },
286
+ );
287
+
288
+ export const multiply = VmLib(
289
+ (a, b) => {
290
+ expectConst('a', a, null);
291
+ expectConst('b', b, null);
292
+ return entrywiseImpl(
293
+ a,
294
+ b,
295
+ $Mul,
296
+ (a, b, al, bl) => {
297
+ const l = Math.max(al, bl);
298
+ let s = 0;
299
+ for (let i = 0; i < l; i++) {
300
+ s += num(a[i]) * num(b[i]);
301
+ }
302
+ return s;
303
+ },
304
+ (a, b, ar, ac, br, bc) => {
305
+ if (ac !== br) throwError(`Incompatible matrix dimensions`, null);
306
+ const result: VmConst[][] = [];
307
+ for (let r = 0; r < ar; r++) {
308
+ const rRow: VmConst[] = [];
309
+ result[r] = rRow;
310
+ for (let c = 0; c < bc; c++) {
311
+ let item = 0;
312
+ for (let k = 0; k < ac; k++) {
313
+ item += num((a as VmConst[][])[r]?.[k]) * num((b as VmConst[][])[k]?.[c]);
314
+ }
315
+ rRow[c] = item;
316
+ }
317
+ }
318
+ return result;
319
+ },
320
+ (a, b, al, br, bc) => {
321
+ if (al !== br) throwError(`Incompatible matrix dimensions`, null);
322
+ const result: VmConst[] = [];
323
+ for (let c = 0; c < bc; c++) {
324
+ let item = 0;
325
+ for (let k = 0; k < al; k++) {
326
+ item += num(a[k]) * num((b as VmConst[][])[k]?.[c]);
327
+ }
328
+ result[c] = item;
329
+ }
330
+ return result;
331
+ },
332
+ (a, b, ar, ac, bl) => {
333
+ if (ac !== bl) throwError(`Incompatible matrix dimensions`, null);
334
+ const result: VmConst[] = [];
335
+ for (let r = 0; r < ar; r++) {
336
+ let item = 0;
337
+ for (let k = 0; k < ac; k++) {
338
+ item += num((a as VmConst[][])[r]?.[k]) * num(b[k]);
339
+ }
340
+ result[r] = item;
341
+ }
342
+ return result;
343
+ },
344
+ );
345
+ },
346
+ {
347
+ summary: '矩阵相乘',
348
+ params: { a: '第一个操作数', b: '第二个操作数' },
349
+ paramsType: { a: 'number | number[] | number[][]', b: 'number | number[] | number[][]' },
350
+ returnsType: 'number | number[] | number[][]',
351
+ examples: ['matrix.multiply([[1, 2], [3, 4]], [5, 6]) // [17, 39]'],
352
+ },
353
+ );
354
+
355
+ export const invert = VmLib(
356
+ (a) => {
357
+ expectConst('a', a, null);
358
+ const [rows, cols] = sizeImpl(a);
359
+ if (rows == null) return 1 / num(a); // 标量取倒数
360
+ if (cols == null) return map(a, (v) => 1 / num(v)); // 向量按元素取倒数
361
+
362
+ if (rows !== cols) throwError(`Matrix must be square`, a);
363
+ const m = a as VmConst[][];
364
+ // https://github.com/josdejong/mathjs
365
+ if (rows === 1) {
366
+ // 1x1 矩阵
367
+ const e = num(m[0]?.[0]);
368
+ // if (e === 0) {
369
+ // throwError(`Matrix is singular`, null);
370
+ // }
371
+ return [[1 / e]];
372
+ }
373
+ if (rows === 2) {
374
+ // 2x2 矩阵
375
+ const a = num(m[0]?.[0]);
376
+ const b = num(m[0]?.[1]);
377
+ const c = num(m[1]?.[0]);
378
+ const d = num(m[1]?.[1]);
379
+
380
+ const det = a * d - b * c;
381
+ // if (det === 0) throwError(`Matrix is singular`, null);
382
+ return [
383
+ [d / det, -b / det],
384
+ [-c / det, a / det],
385
+ ];
386
+ }
387
+
388
+ // 更高阶矩阵 使用高斯消元法
389
+
390
+ // 初始化输入
391
+ const A: number[][] = [];
392
+ // 初始化结果为单位矩阵
393
+ const B: number[][] = [];
394
+ for (let r = 0; r < rows; r++) {
395
+ const Ar: number[] = [];
396
+ const Br: number[] = [];
397
+ A[r] = Ar;
398
+ B[r] = Br;
399
+ for (let c = 0; c < cols; c++) {
400
+ Ar[c] = num(m[r]?.[c]);
401
+ Br[c] = r === c ? 1 : 0;
402
+ }
403
+ }
404
+
405
+ // loop over all columns, and perform row reductions
406
+ for (let c = 0; c < cols; c++) {
407
+ // Pivoting: Swap row c with row r, where row r contains the largest element A[r][c]
408
+ let ABig = Math.abs(A[c]![c]!);
409
+ let rBig = c;
410
+ let r = c + 1;
411
+ while (r < rows) {
412
+ if (Math.abs(A[r]![c]!) > ABig) {
413
+ ABig = Math.abs(A[r]![c]!);
414
+ rBig = r;
415
+ }
416
+ r++;
417
+ }
418
+ // if (ABig === 0) {
419
+ // throwError(`Matrix is singular`, null);
420
+ // }
421
+ r = rBig;
422
+ if (r !== c) {
423
+ const temp1 = A[c]!;
424
+ A[c] = A[r]!;
425
+ A[r] = temp1;
426
+ const temp2 = B[c]!;
427
+ B[c] = B[r]!;
428
+ B[r] = temp2;
429
+ }
430
+
431
+ // eliminate non-zero values on the other rows at column c
432
+ const Ac = A[c]!;
433
+ const Bc = B[c]!;
434
+ for (r = 0; r < rows; r++) {
435
+ const Ar = A[r]!;
436
+ const Br = B[r]!;
437
+ if (r !== c) {
438
+ // eliminate value at column c and row r
439
+ if (Ar[c] !== 0) {
440
+ const f = -Ar[c]! / Ac[c]!;
441
+
442
+ // add (f * row c) to row r to eliminate the value
443
+ // at column c
444
+ for (let s = c; s < cols; s++) {
445
+ Ar[s] = Ar[s]! + f * Ac[s]!;
446
+ }
447
+ for (let s = 0; s < cols; s++) {
448
+ Br[s] = Br[s]! + f * Bc[s]!;
449
+ }
450
+ }
451
+ } else {
452
+ // normalize value at Acc to 1,
453
+ // divide each value on row r with the value at Acc
454
+ const f = Ac[c]!;
455
+ for (let s = c; s < cols; s++) {
456
+ Ar[s] = Ar[s]! / f;
457
+ }
458
+ for (let s = 0; s < cols; s++) {
459
+ Br[s] = Br[s]! / f;
460
+ }
461
+ }
462
+ }
463
+ }
464
+ return B;
465
+ },
466
+ {
467
+ summary: '矩阵求逆',
468
+ params: { a: '待求逆的矩阵' },
469
+ paramsType: { a: 'number | number[][]' },
470
+ returnsType: 'number | number[][]',
471
+ examples: ['matrix.invert([[1, 2], [3, 4]]) // [[-2, 1], [1.5, -0.5]]'],
472
+ },
473
+ );
474
+
475
+ /** 填充 */
476
+ function filled(size: readonly VmAny[], value: VmConst): VmArray {
477
+ const s = getNumbers(size);
478
+ if (s.length === 0) return [];
479
+ while (s.length > 0) {
480
+ const repeat = arrayLen(s.pop());
481
+ Cp();
482
+ const data: VmConst[] = [];
483
+ data.length = repeat;
484
+ // 从 MiraScript 语义而言,可以使用同一个引用
485
+ data.fill(value);
486
+ value = data;
487
+ }
488
+ return value as VmArray;
489
+ }
490
+
491
+ export const zeros = VmLib((...size) => filled(size, 0), {
492
+ summary: '创建一个全零的矩阵',
493
+ params: { '..size': '矩阵的维度' },
494
+ paramsType: { '..size': 'number[]' },
495
+ returnsType: 'number[][]',
496
+ examples: ['matrix.zeros(2, 3) // [[0, 0, 0], [0, 0, 0]]'],
497
+ });
498
+
499
+ export const ones = VmLib((...size) => filled(size, 1), {
500
+ summary: '创建一个全一的矩阵',
501
+ params: { '..size': '矩阵的维度' },
502
+ paramsType: { '..size': 'number[]' },
503
+ returnsType: 'number[][]',
504
+ examples: ['matrix.ones(2, 2) // [[1, 1], [1, 1]]'],
505
+ });
506
+
507
+ export const identity = VmLib(
508
+ (...size) => {
509
+ let s = getNumbers(size);
510
+ if (s.length === 0) return [];
511
+ if (s.length > 2) throwError('Invalid matrix size', []);
512
+ if (s.length === 1) s = [s[0]!, s[0]!];
513
+ const m = arrayLen(s[0]);
514
+ const n = arrayLen(s[1]);
515
+ // 由于 `filled` 函数返回只读数组,其每行为相同引用,这里需要手动创建每行
516
+ const ret: number[][] = [];
517
+ for (let i = 0; i < m; i++) {
518
+ const row: number[] = [];
519
+ ret[i] = row;
520
+ row.length = n;
521
+ row.fill(0);
522
+ if (i < n) row[i] = 1;
523
+ }
524
+ return ret;
525
+ },
526
+ {
527
+ summary: '创建一个单位矩阵',
528
+ params: { '..size': '矩阵的维度' },
529
+ paramsType: { '..size': '[number] | [number, number]' },
530
+ returnsType: 'number[][]',
531
+ examples: ['matrix.identity(3) // [[1, 0, 0], [0, 1, 0], [0, 0, 1]]'],
532
+ },
533
+ );
534
+
535
+ export const diagonal = VmLib(
536
+ (x, k = 0) => {
537
+ expectArray('x', x, []);
538
+ const fk = Math.round($ToNumber(k) || 0);
539
+ if (x.every((e) => isArray(e))) {
540
+ // 获取对角线元素
541
+ const diag: VmConst[] = [];
542
+ for (let i = 0; i < x.length; i++) {
543
+ const row = x[i] as VmArray | undefined;
544
+ const r = i + fk;
545
+ if (r < 0) continue;
546
+ if (!row || r >= row.length) break;
547
+ diag.push(row[r] ?? null);
548
+ }
549
+ return diag;
550
+ }
551
+ // 创建对角矩阵
552
+ const l = x.length;
553
+ const m = arrayLen(fk < 0 ? l - fk : l);
554
+ const n = arrayLen(fk > 0 ? l + fk : l);
555
+ const result: VmConst[][] = [];
556
+ for (let i = 0; i < m; i++) {
557
+ const row: VmConst[] = [];
558
+ result[i] = row;
559
+ row.length = n;
560
+ row.fill(0);
561
+ for (let j = 0; j < n; j++) {
562
+ if (i + fk === j) {
563
+ row[j] = x[fk >= 0 ? i : j] ?? null;
564
+ }
565
+ }
566
+ }
567
+ return result;
568
+ },
569
+ {
570
+ summary: '创建一个对角矩阵或获取矩阵的对角线',
571
+ params: { x: '对角线元素或要获取对角线的矩阵', k: '对角线偏移量,默认为 0' },
572
+ paramsType: { x: 'number[] | number[][]', k: 'number' },
573
+ returnsType: 'number[][] | number[]',
574
+ examples: [
575
+ 'matrix.diagonal([1, 2, 3]) // [[1, 0, 0], [0, 2, 0], [0, 0, 3]]',
576
+ 'matrix.diagonal([[1, 2], [3, 4]]) // [1, 4]',
577
+ ],
578
+ },
579
+ );
@@ -0,0 +1,73 @@
1
+ import { entries } from '../../../../helpers/utils.js';
2
+ import { Cp } from '../../../helpers.js';
3
+ import { $Call, $ToBoolean } from '../../../operations.js';
4
+ import { isVmArray } from '../../../types/index.js';
5
+ import { expectArrayOrRecord, expectCallable, VmLib } from '../../_helpers.js';
6
+
7
+ export const all = VmLib(
8
+ (data, predicate) => {
9
+ expectArrayOrRecord('data', data, null);
10
+ expectCallable('predicate', predicate, data);
11
+ if (isVmArray(data)) {
12
+ for (let i = 0; i < data.length; i++) {
13
+ Cp();
14
+ const value = data[i] ?? null;
15
+ const ret = $Call(predicate, [value, i, data]);
16
+ if (!$ToBoolean(ret)) return false;
17
+ }
18
+ return true;
19
+ } else {
20
+ for (const [key, v] of entries(data)) {
21
+ Cp();
22
+ const value = v ?? null;
23
+ const ret = $Call(predicate, [value, key, data]);
24
+ if (!$ToBoolean(ret)) return false;
25
+ }
26
+ return true;
27
+ }
28
+ },
29
+ {
30
+ summary: '检查数组或记录中的所有键值对是否都满足条件',
31
+ params: { data: '要检查的数组或记录', predicate: '用于测试每个键值对的函数,返回 true 或 false' },
32
+ paramsType: {
33
+ data: 'array | record',
34
+ predicate: 'fn(value: any, key: number | string, input: type(data)) -> boolean',
35
+ },
36
+ returnsType: 'boolean',
37
+ examples: ['all([1, 2, 3], fn { it > 0 }) // true'],
38
+ },
39
+ );
40
+
41
+ export const any = VmLib(
42
+ (data, predicate) => {
43
+ expectArrayOrRecord('data', data, null);
44
+ expectCallable('predicate', predicate, data);
45
+ if (isVmArray(data)) {
46
+ for (let i = 0; i < data.length; i++) {
47
+ Cp();
48
+ const value = data[i] ?? null;
49
+ const ret = $Call(predicate, [value, i, data]);
50
+ if ($ToBoolean(ret)) return true;
51
+ }
52
+ return false;
53
+ } else {
54
+ for (const [key, v] of entries(data)) {
55
+ Cp();
56
+ const value = v ?? null;
57
+ const ret = $Call(predicate, [value, key, data]);
58
+ if ($ToBoolean(ret)) return true;
59
+ }
60
+ return false;
61
+ }
62
+ },
63
+ {
64
+ summary: '检查数组或记录中的是否存在满足条件的键值对',
65
+ params: { data: '要检查的数组或记录', predicate: '用于测试每个键值对的函数,返回 true 或 false' },
66
+ paramsType: {
67
+ data: 'array | record',
68
+ predicate: 'fn(value: any, key: number | string, input: type(data)) -> boolean',
69
+ },
70
+ returnsType: 'boolean',
71
+ examples: ['any([0, 1, 2], fn { it > 1 }) // true'],
72
+ },
73
+ );