slangmath 1.0.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.
@@ -0,0 +1,284 @@
1
+ /**
2
+ * SLaNg Helper Utilities
3
+ * High-level helpers for common mathematical operations
4
+ */
5
+
6
+ import {
7
+ createTerm,
8
+ createFraction,
9
+ definiteIntegrateFraction,
10
+ expandProduct,
11
+ simplifyFraction,
12
+ evaluateEquation,
13
+ differentiateFraction,
14
+ deepClone
15
+ } from './slang-math.js';
16
+
17
+ // ============================================================================
18
+ // EQUATION BUILDERS
19
+ // ============================================================================
20
+
21
+ /**
22
+ * Create a polynomial from coefficients
23
+ * @param {Array<number>} coeffs - Coefficients from highest to lowest degree
24
+ * @param {string} variable - Variable name (default 'x')
25
+ *
26
+ * Example: polynomial([1, -2, 1], 'x') creates x² - 2x + 1
27
+ */
28
+ function polynomial(coeffs, variable = 'x') {
29
+ const terms = [];
30
+ const degree = coeffs.length - 1;
31
+
32
+ for (let i = 0; i < coeffs.length; i++) {
33
+ const power = degree - i;
34
+ const coeff = coeffs[i];
35
+
36
+ if (coeff === 0) continue;
37
+
38
+ if (power === 0) {
39
+ terms.push(createTerm(coeff));
40
+ } else {
41
+ terms.push(createTerm(coeff, { [variable]: power }));
42
+ }
43
+ }
44
+
45
+ return [[createFraction(terms, 1)]];
46
+ }
47
+
48
+ /**
49
+ * Create a monomial: coeff * x^px * y^py * z^pz * ...
50
+ */
51
+ function monomial(coeff, powers = {}) {
52
+ return [[createFraction([createTerm(coeff, powers)], 1)]];
53
+ }
54
+
55
+ /**
56
+ * Create a sum of monomials
57
+ * @param {Array} terms - Array of [coeff, powers] pairs
58
+ *
59
+ * Example: sum([[2, {x:2}], [3, {x:1}], [1, {}]]) creates 2x² + 3x + 1
60
+ */
61
+ function sum(terms) {
62
+ const slangTerms = terms.map(([coeff, powers]) => createTerm(coeff, powers));
63
+ return [[createFraction(slangTerms, 1)]];
64
+ }
65
+
66
+ /**
67
+ * Create a product of polynomials
68
+ * @param {Array} factors - Array of polynomial fractions
69
+ *
70
+ * Example: product([[1+x], [1-x]]) creates (1+x)(1-x)
71
+ */
72
+ function product(...factors) {
73
+ // Convert each factor array to fraction format
74
+ const fractions = factors.map(factor => {
75
+ if (Array.isArray(factor[0][0]?.numi?.terms)) {
76
+ return factor[0][0]; // Already a fraction
77
+ }
78
+ return createFraction(factor.map(([c, p]) => createTerm(c, p)), 1);
79
+ });
80
+
81
+ return [fractions];
82
+ }
83
+
84
+ // ============================================================================
85
+ // CALCULATION HELPERS
86
+ // ============================================================================
87
+
88
+ /**
89
+ * Compute definite integral over a rectangular region
90
+ * @param {Object} expr - Expression to integrate
91
+ * @param {Object} bounds - {x: [lower, upper], y: [lower, upper], ...}
92
+ *
93
+ * Example:
94
+ * integralOverRegion(xy, {x: [0, 2], y: [0, 3]})
95
+ * computes ∫₀² ∫₀³ xy dy dx
96
+ */
97
+ function integralOverRegion(expr, bounds) {
98
+ let result = deepClone(expr);
99
+
100
+ for (let [variable, [lower, upper]] of Object.entries(bounds)) {
101
+ result = definiteIntegrateFraction(result, lower, upper, variable);
102
+ result = simplifyFraction(result);
103
+ }
104
+
105
+ return result;
106
+ }
107
+
108
+ /**
109
+ * Compute integral and return numeric value
110
+ */
111
+ function integralValue(expr, bounds) {
112
+ const result = integralOverRegion(expr, bounds);
113
+ return evaluateEquation([[result]], {});
114
+ }
115
+
116
+ /**
117
+ * Compute partial derivative with respect to variable
118
+ * @param {Object} expr - Expression to differentiate
119
+ * @param {string} variable - Variable to differentiate with respect to
120
+ * @param {number} order - Order of derivative (default 1)
121
+ */
122
+ function partialDerivative(expr, variable, order = 1) {
123
+ let result = deepClone(expr);
124
+
125
+ for (let i = 0; i < order; i++) {
126
+ result = differentiateFraction(result, variable);
127
+ result = simplifyFraction(result);
128
+ }
129
+
130
+ return result;
131
+ }
132
+
133
+ /**
134
+ * Expand and simplify a product expression
135
+ */
136
+ function expandAndSimplify(productArray) {
137
+ const expanded = expandProduct(productArray);
138
+ return simplifyFraction(expanded);
139
+ }
140
+
141
+ /**
142
+ * Evaluate expression at point
143
+ * @param {Object} expr - Expression in equation format
144
+ * @param {Object} point - {x: value, y: value, ...}
145
+ */
146
+ function evaluateAt(expr, point) {
147
+ return evaluateEquation([Array.isArray(expr) ? expr : [expr]], point);
148
+ }
149
+
150
+ // ============================================================================
151
+ // COMMON FORMULAS
152
+ // ============================================================================
153
+
154
+ /**
155
+ * Common mathematical functions as SLaNg expressions
156
+ */
157
+ const formulas = {
158
+ // Circle area element: r dr dθ
159
+ circleAreaElement: (r = 'r') =>
160
+ [[createFraction([createTerm(1, { [r]: 1 })], 1)]],
161
+
162
+ // Disk of radius R: ∫₀²ᵖ ∫₀ᴿ r dr dθ
163
+ diskArea: (R) => {
164
+ const rdr = formulas.circleAreaElement('r');
165
+ return integralValue(rdr[0][0], { r: [0, R] }) * 2 * Math.PI;
166
+ },
167
+
168
+ // Sphere volume element in spherical coords: r² sin(φ) dr dφ dθ
169
+ // (approximated for polynomial case)
170
+
171
+ // Average value of f over [a,b]: 1/(b-a) ∫ₐᵇ f dx
172
+ average: (expr, variable, a, b) => {
173
+ const integral = definiteIntegrateFraction(expr, a, b, variable);
174
+ const value = evaluateEquation([[integral]], {});
175
+ return value / (b - a);
176
+ },
177
+
178
+ // Center of mass (1D): ∫ x·ρ(x) dx / ∫ ρ(x) dx
179
+ centerOfMass1D: (density, variable, a, b) => {
180
+ // Create x * density
181
+ const xDensity = deepClone(density);
182
+ for (let term of xDensity.numi.terms) {
183
+ if (!term.var) term.var = {};
184
+ term.var[variable] = (term.var[variable] || 0) + 1;
185
+ }
186
+
187
+ const numerator = integralValue(xDensity, { [variable]: [a, b] });
188
+ const denominator = integralValue(density, { [variable]: [a, b] });
189
+
190
+ return numerator / denominator;
191
+ }
192
+ };
193
+
194
+ // ============================================================================
195
+ // GEOMETRY HELPERS
196
+ // ============================================================================
197
+
198
+ /**
199
+ * Volume under surface z = f(x,y) over region R
200
+ */
201
+ function volumeUnderSurface(surface, xBounds, yBounds) {
202
+ return integralValue(surface, { x: xBounds, y: yBounds });
203
+ }
204
+
205
+ /**
206
+ * Area of region in xy-plane (integrate 1 over region)
207
+ */
208
+ function areaOfRegion(xBounds, yBounds) {
209
+ const one = createFraction([createTerm(1)], 1);
210
+ return integralValue(one, { x: xBounds, y: yBounds });
211
+ }
212
+
213
+ // ============================================================================
214
+ // VERIFICATION HELPERS
215
+ // ============================================================================
216
+
217
+ /**
218
+ * Check if integration was done correctly by differentiating
219
+ */
220
+ function verifyIntegration(original, integrated, variable) {
221
+ const derivative = differentiateFraction(integrated, variable);
222
+ const simplified = simplifyFraction(derivative);
223
+
224
+ // Compare structures (simple comparison)
225
+ return JSON.stringify(simplifyFraction(original)) ===
226
+ JSON.stringify(simplified);
227
+ }
228
+
229
+ /**
230
+ * Numerical verification: sample at random points
231
+ */
232
+ function numericalVerification(expr1, expr2, variables, numSamples = 10) {
233
+ const errors = [];
234
+
235
+ for (let i = 0; i < numSamples; i++) {
236
+ const point = {};
237
+ for (let v of variables) {
238
+ point[v] = Math.random() * 10 - 5; // Random value in [-5, 5]
239
+ }
240
+
241
+ const val1 = evaluateAt([expr1], point);
242
+ const val2 = evaluateAt([expr2], point);
243
+ const error = Math.abs(val1 - val2);
244
+
245
+ if (error > 1e-10) {
246
+ errors.push({ point, val1, val2, error });
247
+ }
248
+ }
249
+
250
+ return {
251
+ passed: errors.length === 0,
252
+ errors
253
+ };
254
+ }
255
+
256
+ // ============================================================================
257
+ // EXPORTS
258
+ // ============================================================================
259
+
260
+ export {
261
+ // Builders
262
+ polynomial,
263
+ monomial,
264
+ sum,
265
+ product,
266
+
267
+ // Calculations
268
+ integralOverRegion,
269
+ integralValue,
270
+ partialDerivative,
271
+ expandAndSimplify,
272
+ evaluateAt,
273
+
274
+ // Formulas
275
+ formulas,
276
+
277
+ // Geometry
278
+ volumeUnderSurface,
279
+ areaOfRegion,
280
+
281
+ // Verification
282
+ verifyIntegration,
283
+ numericalVerification
284
+ };
package/slang-math.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./slang-basic.js";
2
+ export * from "./slang-advanced.js";
3
+ export * from "./slang-helpers.js";