@khanacademy/kas 0.2.3
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/CHANGELOG.md +7 -0
- package/LICENSE.txt +21 -0
- package/README.md +94 -0
- package/dist/es/index.js +2 -0
- package/dist/es/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.flow +2 -0
- package/dist/index.js.map +1 -0
- package/experimenter.html +75 -0
- package/package.json +38 -0
- package/src/__genfiles__/parser.js +840 -0
- package/src/__genfiles__/unitparser.js +679 -0
- package/src/__tests__/checking-form_test.js +76 -0
- package/src/__tests__/comparing_test.js +322 -0
- package/src/__tests__/compilation_test.js +97 -0
- package/src/__tests__/evaluating_test.js +73 -0
- package/src/__tests__/index_test.js +364 -0
- package/src/__tests__/parsing_test.js +480 -0
- package/src/__tests__/rendering_test.js +272 -0
- package/src/__tests__/transforming_test.js +331 -0
- package/src/__tests__/units_test.js +188 -0
- package/src/compare.js +69 -0
- package/src/index.js +2 -0
- package/src/nodes.js +3504 -0
- package/src/parser-generator.js +212 -0
- package/src/unitvalue.jison +161 -0
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
import _ from "underscore";
|
|
2
|
+
|
|
3
|
+
import * as KAS from "../index.js";
|
|
4
|
+
|
|
5
|
+
expect.extend({
|
|
6
|
+
toParseAs(input: string, expected: string, options: $FlowFixMe) {
|
|
7
|
+
const actual = KAS.parse(input, options).expr.print();
|
|
8
|
+
|
|
9
|
+
if (actual !== expected) {
|
|
10
|
+
return {
|
|
11
|
+
pass: false,
|
|
12
|
+
message: () => `${input} parses as ${expected}`,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return {pass: !this.isNot};
|
|
17
|
+
},
|
|
18
|
+
toParseWithStructure(input: string, expected: string, options: $FlowFixMe) {
|
|
19
|
+
const actual = KAS.parse(input, options).expr.repr();
|
|
20
|
+
|
|
21
|
+
if (actual !== expected) {
|
|
22
|
+
return {
|
|
23
|
+
pass: false,
|
|
24
|
+
message: () => `${input} parses as ${expected}`,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return {pass: !this.isNot};
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe("parsing", () => {
|
|
33
|
+
test("empty", () => {
|
|
34
|
+
expect("").toParseAs("");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("positive and negative primitives", () => {
|
|
38
|
+
expect("0").toParseAs("0");
|
|
39
|
+
expect("1.").toParseAs("1");
|
|
40
|
+
expect("3.14").toParseAs("3.14");
|
|
41
|
+
expect(".14").toParseAs("0.14");
|
|
42
|
+
expect("pi").toParseAs("pi");
|
|
43
|
+
expect("e").toParseAs("e");
|
|
44
|
+
expect("x").toParseAs("x");
|
|
45
|
+
expect("theta").toParseAs("theta");
|
|
46
|
+
|
|
47
|
+
expect("-0").toParseAs("-1*0");
|
|
48
|
+
expect("-1.").toParseAs("-1");
|
|
49
|
+
expect("-3.14").toParseAs("-3.14");
|
|
50
|
+
expect("-.14").toParseAs("-0.14");
|
|
51
|
+
expect("-pi").toParseAs("-1*pi");
|
|
52
|
+
expect("-e").toParseAs("-1*e");
|
|
53
|
+
expect("-theta").toParseAs("-1*theta");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("LaTeX constants", () => {
|
|
57
|
+
expect("\\theta").toParseAs("theta");
|
|
58
|
+
expect("\\pi").toParseAs("pi");
|
|
59
|
+
expect("\\phi").toParseAs("phi");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("ignore TeX spaces", () => {
|
|
63
|
+
expect("a\\space b").toParseAs("a*b");
|
|
64
|
+
expect("a\\ b").toParseAs("a*b");
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("positive and negative rationals", () => {
|
|
68
|
+
expect("1/2").toParseAs("1/2");
|
|
69
|
+
expect("-1/2").toParseAs("-1/2");
|
|
70
|
+
expect("1/-2").toParseAs("-1/2");
|
|
71
|
+
expect("-1/-2").toParseAs("-1*-1/2");
|
|
72
|
+
expect("42/42").toParseAs("42/42");
|
|
73
|
+
expect("42/1").toParseAs("42/1");
|
|
74
|
+
expect("0/42").toParseAs("0/42");
|
|
75
|
+
|
|
76
|
+
expect("2 (1/2)").toParseAs("2*1/2");
|
|
77
|
+
expect("1/2 1/2").toParseAs("1/2*1/2");
|
|
78
|
+
expect("-1/2").toParseAs("-1/2");
|
|
79
|
+
expect("1/2 2").toParseAs("1/2*2");
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("rationals using \\frac", () => {
|
|
83
|
+
expect("\\frac{1}{2}").toParseAs("1/2");
|
|
84
|
+
expect("\\frac{-1}{2}").toParseAs("-1/2");
|
|
85
|
+
expect("\\frac{1}{-2}").toParseAs("-1/2");
|
|
86
|
+
expect("\\frac{-1}{-2}").toParseAs("-1*-1/2");
|
|
87
|
+
expect("\\frac{42}{42}").toParseAs("42/42");
|
|
88
|
+
expect("\\frac{42}{1}").toParseAs("42/1");
|
|
89
|
+
expect("\\frac{0}{42}").toParseAs("0/42");
|
|
90
|
+
|
|
91
|
+
expect("2\\frac{1}{2}").toParseAs("2*1/2");
|
|
92
|
+
expect("\\frac{1}{2}\\frac{1}{2}").toParseAs("1/2*1/2");
|
|
93
|
+
expect("-\\frac{1}{2}").toParseAs("-1/2");
|
|
94
|
+
expect("\\frac{1}{2}2").toParseAs("1/2*2");
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("rationals using \\dfrac", () => {
|
|
98
|
+
expect("\\dfrac{1}{2}").toParseAs("1/2");
|
|
99
|
+
expect("\\dfrac{-1}{2}").toParseAs("-1/2");
|
|
100
|
+
expect("\\dfrac{1}{-2}").toParseAs("-1/2");
|
|
101
|
+
expect("\\dfrac{-1}{-2}").toParseAs("-1*-1/2");
|
|
102
|
+
expect("\\dfrac{42}{42}").toParseAs("42/42");
|
|
103
|
+
expect("\\dfrac{42}{1}").toParseAs("42/1");
|
|
104
|
+
expect("\\dfrac{0}{42}").toParseAs("0/42");
|
|
105
|
+
|
|
106
|
+
expect("2\\dfrac{1}{2}").toParseAs("2*1/2");
|
|
107
|
+
expect("\\dfrac{1}{2}\\dfrac{1}{2}").toParseAs("1/2*1/2");
|
|
108
|
+
expect("-\\dfrac{1}{2}").toParseAs("-1/2");
|
|
109
|
+
expect("\\dfrac{1}{2}2").toParseAs("1/2*2");
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test("parens", () => {
|
|
113
|
+
expect("(0)").toParseAs("0");
|
|
114
|
+
expect("(ab)").toParseAs("a*b");
|
|
115
|
+
expect("(a/b)").toParseAs("a*b^(-1)");
|
|
116
|
+
expect("(a^b)").toParseAs("a^(b)");
|
|
117
|
+
expect("(ab)c").toParseAs("a*b*c");
|
|
118
|
+
expect("a(bc)").toParseAs("a*b*c");
|
|
119
|
+
expect("a+(b+c)").toParseAs("a+b+c");
|
|
120
|
+
expect("(a+b)+c").toParseAs("a+b+c");
|
|
121
|
+
expect("a(b+c)").toParseAs("a*(b+c)");
|
|
122
|
+
expect("(a+b)^c").toParseAs("(a+b)^(c)");
|
|
123
|
+
expect("(ab)^c").toParseAs("(a*b)^(c)");
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("subscripts", () => {
|
|
127
|
+
expect("a").toParseAs("a");
|
|
128
|
+
expect("a_0").toParseAs("a_(0)");
|
|
129
|
+
expect("a_i").toParseAs("a_(i)");
|
|
130
|
+
expect("a_n").toParseAs("a_(n)");
|
|
131
|
+
expect("a_n+1").toParseAs("a_(n)+1");
|
|
132
|
+
expect("a_(n+1)").toParseAs("a_(n+1)");
|
|
133
|
+
expect("a_{n+1}").toParseAs("a_(n+1)");
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("negation", () => {
|
|
137
|
+
expect("-x").toParseAs("-1*x");
|
|
138
|
+
expect("--x").toParseAs("-1*-1*x");
|
|
139
|
+
expect("---x").toParseAs("-1*-1*-1*x");
|
|
140
|
+
expect("-1").toParseAs("-1");
|
|
141
|
+
expect("--1").toParseAs("-1*-1");
|
|
142
|
+
expect("---1").toParseAs("-1*-1*-1");
|
|
143
|
+
expect("-3x").toParseAs("-3*x");
|
|
144
|
+
expect("--3x").toParseAs("-1*-3*x");
|
|
145
|
+
expect("-x*3").toParseAs("x*-3");
|
|
146
|
+
expect("--x*3").toParseAs("-1*x*-3");
|
|
147
|
+
expect("\u2212x").toParseAs("-1*x");
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test("addition and subtraction", () => {
|
|
151
|
+
expect("a+b").toParseAs("a+b");
|
|
152
|
+
expect("a-b").toParseAs("a+-1*b");
|
|
153
|
+
expect("a--b").toParseAs("a+-1*-1*b");
|
|
154
|
+
expect("a---b").toParseAs("a+-1*-1*-1*b");
|
|
155
|
+
expect("2-4").toParseAs("2+-4");
|
|
156
|
+
expect("2--4").toParseAs("2+-1*-4");
|
|
157
|
+
expect("2---4").toParseAs("2+-1*-1*-4");
|
|
158
|
+
expect("2-x*4").toParseAs("2+x*-4");
|
|
159
|
+
expect("1-2+a-b+pi-e").toParseAs("1+-2+a+-1*b+pi+-1*e");
|
|
160
|
+
expect("x+1").toParseAs("x+1");
|
|
161
|
+
expect("x-1").toParseAs("x+-1");
|
|
162
|
+
expect("(x-1)").toParseAs("x+-1");
|
|
163
|
+
expect("a(x-1)").toParseAs("a*(x+-1)");
|
|
164
|
+
expect("a\u2212b").toParseAs("a+-1*b");
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test("multiplication", () => {
|
|
168
|
+
expect("a*b").toParseAs("a*b");
|
|
169
|
+
expect("-a*b").toParseAs("-1*a*b");
|
|
170
|
+
expect("a*-b").toParseAs("a*-1*b");
|
|
171
|
+
expect("-ab").toParseAs("-1*a*b");
|
|
172
|
+
expect("-a*b").toParseAs("-1*a*b");
|
|
173
|
+
expect("-(ab)").toParseAs("-1*a*b");
|
|
174
|
+
expect("a\u00b7b").toParseAs("a*b");
|
|
175
|
+
expect("a\u00d7b").toParseAs("a*b");
|
|
176
|
+
expect("a\\cdotb").toParseAs("a*b");
|
|
177
|
+
expect("a\\timesb").toParseAs("a*b");
|
|
178
|
+
expect("a\\astb").toParseAs("a*b");
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("division", () => {
|
|
182
|
+
expect("a/b").toParseAs("a*b^(-1)");
|
|
183
|
+
expect("a/bc").toParseAs("a*b^(-1)*c");
|
|
184
|
+
expect("(ab)/c").toParseAs("a*b*c^(-1)");
|
|
185
|
+
expect("ab/c").toParseAs("a*b*c^(-1)");
|
|
186
|
+
expect("ab/cd").toParseAs("a*b*c^(-1)*d");
|
|
187
|
+
expect("a\\divb").toParseAs("a*b^(-1)");
|
|
188
|
+
expect("a\u00F7b").toParseAs("a*b^(-1)");
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test("exponentiation", () => {
|
|
192
|
+
expect("x^y").toParseAs("x^(y)");
|
|
193
|
+
expect("x^y^z").toParseAs("x^(y^(z))");
|
|
194
|
+
expect("x^yz").toParseAs("x^(y)*z");
|
|
195
|
+
expect("-x^2").toParseAs("-1*x^(2)");
|
|
196
|
+
expect("-(x^2)").toParseAs("-1*x^(2)");
|
|
197
|
+
expect("0-x^2").toParseAs("0+-1*x^(2)");
|
|
198
|
+
expect("x^-y").toParseAs("x^(-1*y)");
|
|
199
|
+
expect("x^(-y)").toParseAs("x^(-1*y)");
|
|
200
|
+
expect("x^-(y)").toParseAs("x^(-1*y)");
|
|
201
|
+
expect("x^-(-y)").toParseAs("x^(-1*-1*y)");
|
|
202
|
+
expect("x^--y").toParseAs("x^(-1*-1*y)");
|
|
203
|
+
expect("x^-yz").toParseAs("x^(-1*y)*z");
|
|
204
|
+
expect("x^-y^z").toParseAs("x^(-1*y^(z))");
|
|
205
|
+
expect("x**y").toParseAs("x^(y)");
|
|
206
|
+
|
|
207
|
+
expect("x^{a}").toParseAs("x^(a)");
|
|
208
|
+
expect("x^{ab}").toParseAs("x^(a*b)");
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test("square root", () => {
|
|
212
|
+
expect("sqrt(x)").toParseAs("x^(1/2)");
|
|
213
|
+
expect("sqrt(x)y").toParseAs("x^(1/2)*y");
|
|
214
|
+
expect("1/sqrt(x)").toParseAs("x^(-1/2)");
|
|
215
|
+
expect("1/sqrt(x)y").toParseAs("x^(-1/2)*y");
|
|
216
|
+
|
|
217
|
+
expect("sqrt(2)/2").toParseAs("2^(1/2)*1/2");
|
|
218
|
+
expect("sqrt(2)^2").toParseAs("(2^(1/2))^(2)");
|
|
219
|
+
|
|
220
|
+
expect("\\sqrt(x)").toParseAs("x^(1/2)");
|
|
221
|
+
expect("\\sqrt(x)y").toParseAs("x^(1/2)*y");
|
|
222
|
+
expect("1/\\sqrt(x)").toParseAs("x^(-1/2)");
|
|
223
|
+
expect("1/\\sqrt(x)y").toParseAs("x^(-1/2)*y");
|
|
224
|
+
|
|
225
|
+
expect("\\sqrt(2)/2").toParseAs("2^(1/2)*1/2");
|
|
226
|
+
expect("\\sqrt(2)^2").toParseAs("(2^(1/2))^(2)");
|
|
227
|
+
|
|
228
|
+
expect("\\sqrt{2}").toParseAs("2^(1/2)");
|
|
229
|
+
expect("\\sqrt{2+2}").toParseAs("(2+2)^(1/2)");
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
test("nth root", () => {
|
|
233
|
+
expect("sqrt[3]{x}").toParseAs("x^(1/3)");
|
|
234
|
+
expect("sqrt[4]{x}y").toParseAs("x^(1/4)*y");
|
|
235
|
+
expect("1/sqrt[5]{x}").toParseAs("x^(-1/5)");
|
|
236
|
+
expect("1/sqrt[7]{x}y").toParseAs("x^(-1/7)*y");
|
|
237
|
+
|
|
238
|
+
expect("sqrt[3]{2}/2").toParseAs("2^(1/3)*1/2");
|
|
239
|
+
expect("sqrt[3]{2}^2").toParseAs("(2^(1/3))^(2)");
|
|
240
|
+
|
|
241
|
+
expect("\\sqrt[4]{x}").toParseAs("x^(1/4)");
|
|
242
|
+
expect("\\sqrt[4]{x}y").toParseAs("x^(1/4)*y");
|
|
243
|
+
expect("1/\\sqrt[4]{x}").toParseAs("x^(-1/4)");
|
|
244
|
+
expect("1/\\sqrt[4]{x}y").toParseAs("x^(-1/4)*y");
|
|
245
|
+
|
|
246
|
+
expect("\\sqrt[5]{2}/2").toParseAs("2^(1/5)*1/2");
|
|
247
|
+
expect("\\sqrt[5]{2}^2").toParseAs("(2^(1/5))^(2)");
|
|
248
|
+
|
|
249
|
+
expect("\\sqrt[6]{2}").toParseAs("2^(1/6)");
|
|
250
|
+
expect("\\sqrt[6]{2+2}").toParseAs("(2+2)^(1/6)");
|
|
251
|
+
|
|
252
|
+
expect("\\sqrt[2]{2}").toParseAs("2^(1/2)");
|
|
253
|
+
expect("\\sqrt[2]{2+2}").toParseAs("(2+2)^(1/2)");
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
test("absolute value", () => {
|
|
257
|
+
expect("abs(x)").toParseAs("abs(x)");
|
|
258
|
+
expect("abs(abs(x))").toParseAs("abs(abs(x))");
|
|
259
|
+
expect("abs(x)abs(y)").toParseAs("abs(x)*abs(y)");
|
|
260
|
+
|
|
261
|
+
expect("|x|").toParseAs("abs(x)");
|
|
262
|
+
expect("||x||").toParseAs("abs(abs(x))");
|
|
263
|
+
// TODO(alex): fix the below so it doesn't require an *
|
|
264
|
+
// may require own lexer/preprocessor
|
|
265
|
+
expect("|x|*|y|").toParseAs("abs(x)*abs(y)");
|
|
266
|
+
|
|
267
|
+
expect("\\abs(x)").toParseAs("abs(x)");
|
|
268
|
+
expect("\\abs(\\abs(x))").toParseAs("abs(abs(x))");
|
|
269
|
+
expect("\\abs(x)\\abs(y)").toParseAs("abs(x)*abs(y)");
|
|
270
|
+
|
|
271
|
+
expect("\\left|x\\right|").toParseAs("abs(x)");
|
|
272
|
+
expect("\\left|\\left|x\\right|\\right|").toParseAs("abs(abs(x))");
|
|
273
|
+
expect("\\left|x\\right|\\left|y\\right|").toParseAs("abs(x)*abs(y)");
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
test("logarithms", () => {
|
|
277
|
+
expect("lnx").toParseAs("ln(x)");
|
|
278
|
+
expect("ln x").toParseAs("ln(x)");
|
|
279
|
+
expect("ln x^y").toParseAs("ln(x^(y))");
|
|
280
|
+
expect("ln xy").toParseAs("ln(x*y)");
|
|
281
|
+
expect("ln x/y").toParseAs("ln(x*y^(-1))");
|
|
282
|
+
expect("ln x+y").toParseAs("ln(x)+y");
|
|
283
|
+
expect("ln x-y").toParseAs("ln(x)+-1*y");
|
|
284
|
+
|
|
285
|
+
expect("ln xyz").toParseAs("ln(x*y*z)");
|
|
286
|
+
expect("ln xy/z").toParseAs("ln(x*y*z^(-1))");
|
|
287
|
+
expect("ln xy/z+1").toParseAs("ln(x*y*z^(-1))+1");
|
|
288
|
+
|
|
289
|
+
expect("ln x(y)").toParseAs("ln(x)*y");
|
|
290
|
+
|
|
291
|
+
expect("logx").toParseAs("log_(10) (x)");
|
|
292
|
+
expect("log x").toParseAs("log_(10) (x)");
|
|
293
|
+
expect("log_2x").toParseAs("log_(2) (x)");
|
|
294
|
+
expect("log _ 2 x").toParseAs("log_(2) (x)");
|
|
295
|
+
expect("log_bx_0").toParseAs("log_(b) (x_(0))");
|
|
296
|
+
expect("log_x_0b").toParseAs("log_(x_(0)) (b)");
|
|
297
|
+
|
|
298
|
+
expect("log_2.5x").toParseAs("log_(2.5) (x)");
|
|
299
|
+
|
|
300
|
+
expect("ln ln x").toParseAs("ln(ln(x))");
|
|
301
|
+
expect("ln x ln y").toParseAs("ln(x)*ln(y)");
|
|
302
|
+
expect("ln x/ln y").toParseAs("ln(x)*ln(y)^(-1)");
|
|
303
|
+
|
|
304
|
+
expect("\\lnx").toParseAs("ln(x)");
|
|
305
|
+
expect("\\ln x").toParseAs("ln(x)");
|
|
306
|
+
expect("\\ln x^y").toParseAs("ln(x^(y))");
|
|
307
|
+
expect("\\ln xy").toParseAs("ln(x*y)");
|
|
308
|
+
expect("\\ln x/y").toParseAs("ln(x*y^(-1))");
|
|
309
|
+
expect("\\ln x+y").toParseAs("ln(x)+y");
|
|
310
|
+
expect("\\ln x-y").toParseAs("ln(x)+-1*y");
|
|
311
|
+
|
|
312
|
+
expect("\\logx").toParseAs("log_(10) (x)");
|
|
313
|
+
expect("\\log x").toParseAs("log_(10) (x)");
|
|
314
|
+
expect("\\log_2x").toParseAs("log_(2) (x)");
|
|
315
|
+
expect("\\log _ 2 x").toParseAs("log_(2) (x)");
|
|
316
|
+
expect("\\log_bx_0").toParseAs("log_(b) (x_(0))");
|
|
317
|
+
expect("\\log_x_0b").toParseAs("log_(x_(0)) (b)");
|
|
318
|
+
|
|
319
|
+
expect("\\log_2.5x").toParseAs("log_(2.5) (x)");
|
|
320
|
+
|
|
321
|
+
expect("\\frac{\\logx}{y}").toParseAs("log_(10) (x)*y^(-1)");
|
|
322
|
+
expect("\\frac{\\log x}{y}").toParseAs("log_(10) (x)*y^(-1)");
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
test("trig functions", () => {
|
|
326
|
+
var functions = ["sin", "cos", "tan", "csc", "sec", "cot"];
|
|
327
|
+
|
|
328
|
+
var inverses = _.map(functions, function (func) {
|
|
329
|
+
return "arc" + func;
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
_.each(functions.concat(inverses), function (func) {
|
|
333
|
+
expect(func + "x").toParseAs(func + "(x)");
|
|
334
|
+
expect("\\" + func + "x").toParseAs(func + "(x)");
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
expect("sin^-1 x").toParseAs("arcsin(x)");
|
|
338
|
+
expect("\\sin^-1 x").toParseAs("arcsin(x)");
|
|
339
|
+
|
|
340
|
+
expect("(sinx)^2").toParseAs("sin(x)^(2)");
|
|
341
|
+
expect("sin^2x").toParseAs("sin(x)^(2)");
|
|
342
|
+
expect("sin^2(x)").toParseAs("sin(x)^(2)");
|
|
343
|
+
expect("sin^2 x").toParseAs("sin(x)^(2)");
|
|
344
|
+
expect("(sin^2x)").toParseAs("sin(x)^(2)");
|
|
345
|
+
|
|
346
|
+
expect("sin xy").toParseAs("sin(x*y)");
|
|
347
|
+
expect("sin x(y)").toParseAs("sin(x)*y");
|
|
348
|
+
expect("sin x/y").toParseAs("sin(x*y^(-1))");
|
|
349
|
+
expect("(sin x)/y").toParseAs("sin(x)*y^(-1)");
|
|
350
|
+
|
|
351
|
+
expect("sin sin x").toParseAs("sin(sin(x))");
|
|
352
|
+
expect("sin x sin y").toParseAs("sin(x)*sin(y)");
|
|
353
|
+
expect("sin x/sin y").toParseAs("sin(x)*sin(y)^(-1)");
|
|
354
|
+
|
|
355
|
+
expect("1/(sinx)^2").toParseAs("sin(x)^(-2)");
|
|
356
|
+
expect("1/sin^2x").toParseAs("sin(x)^(-2)");
|
|
357
|
+
expect("1/sin^2(x)").toParseAs("sin(x)^(-2)");
|
|
358
|
+
expect("1/(sin^2x)").toParseAs("sin(x)^(-2)");
|
|
359
|
+
|
|
360
|
+
expect("sin(theta)").toParseAs("sin(theta)");
|
|
361
|
+
expect("\\sin(\\theta)").toParseAs("sin(theta)");
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
test("hyperbolic functions", () => {
|
|
365
|
+
expect("sinh xy").toParseAs("sinh(x*y)");
|
|
366
|
+
expect("1/(sinhx)^2").toParseAs("sinh(x)^(-2)");
|
|
367
|
+
expect("\\sinh(\\theta)").toParseAs("sinh(theta)");
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
test("formulas", () => {
|
|
371
|
+
expect("mx+b").toParseAs("m*x+b");
|
|
372
|
+
expect("v^2/r").toParseAs("v^(2)*r^(-1)");
|
|
373
|
+
expect("4/3pir^3").toParseAs("4/3*pi*r^(3)");
|
|
374
|
+
expect("4/3\u03C0r^3").toParseAs("4/3*pi*r^(3)");
|
|
375
|
+
expect("sin^2 x + cos^2 x = 1").toParseAs("sin(x)^(2)+cos(x)^(2)=1");
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
test("factors", () => {
|
|
379
|
+
expect("(6x+1)(x-1)").toParseAs("(6*x+1)*(x+-1)");
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
test("whitespace", () => {
|
|
383
|
+
expect("12/3").toParseAs("12/3");
|
|
384
|
+
expect("12 /3").toParseAs("12/3");
|
|
385
|
+
expect("12/ 3").toParseAs("12/3");
|
|
386
|
+
expect("xy").toParseAs("x*y");
|
|
387
|
+
expect("x y").toParseAs("x*y");
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
test("equations", () => {
|
|
391
|
+
expect("y=x").toParseAs("y=x");
|
|
392
|
+
expect("y=x^2").toParseAs("y=x^(2)");
|
|
393
|
+
expect("1<2").toParseAs("1<2");
|
|
394
|
+
expect("1<=2").toParseAs("1<=2");
|
|
395
|
+
expect("1\\le2").toParseAs("1<=2");
|
|
396
|
+
expect("2>1").toParseAs("2>1");
|
|
397
|
+
expect("2>=1").toParseAs("2>=1");
|
|
398
|
+
expect("2\\ge1").toParseAs("2>=1");
|
|
399
|
+
expect("1<>2").toParseAs("1<>2");
|
|
400
|
+
expect("1=/=2").toParseAs("1<>2");
|
|
401
|
+
expect("1\\ne2").toParseAs("1<>2");
|
|
402
|
+
expect("1\\neq2").toParseAs("1<>2");
|
|
403
|
+
expect("a\u2260b").toParseAs("a<>b");
|
|
404
|
+
expect("a\u2264b").toParseAs("a<=b");
|
|
405
|
+
expect("a\u2265b").toParseAs("a>=b");
|
|
406
|
+
|
|
407
|
+
expect("y \\le x").toParseAs("y<=x");
|
|
408
|
+
expect("y \\leq x").toParseAs("y<=x");
|
|
409
|
+
expect("y \\ge x").toParseAs("y>=x");
|
|
410
|
+
expect("y \\geq x").toParseAs("y>=x");
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
test("function variables", () => {
|
|
414
|
+
expect("f(x)").toParseAs("f*x");
|
|
415
|
+
expect("f(x)").toParseAs("f(x)", {functions: ["f"]});
|
|
416
|
+
expect("f(x+y)").toParseAs("f(x+y)", {functions: ["f"]});
|
|
417
|
+
expect("f(x)g(x)").toParseAs("f(x)*g(x)", {functions: ["f", "g"]});
|
|
418
|
+
expect("f(g(h(x)))").toParseAs("f(g(h(x)))", {
|
|
419
|
+
functions: ["f", "g", "h"],
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
expect("f\\left(x\\right)").toParseAs("f*x");
|
|
423
|
+
expect("f\\left(x\\right)").toParseAs("f(x)", {functions: ["f"]});
|
|
424
|
+
expect("f\\left(x+y\\right)").toParseAs("f(x+y)", {
|
|
425
|
+
functions: ["f"],
|
|
426
|
+
});
|
|
427
|
+
expect("f\\left(x\\right)g\\left(x\\right)").toParseAs("f(x)*g(x)", {
|
|
428
|
+
functions: ["f", "g"],
|
|
429
|
+
});
|
|
430
|
+
expect("f\\left(g\\left(h\\left(x\\right)\\right)\\right)").toParseAs(
|
|
431
|
+
"f(g(h(x)))",
|
|
432
|
+
{functions: ["f", "g", "h"]},
|
|
433
|
+
);
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
test("structure", () => {
|
|
437
|
+
expect("").toParseWithStructure("Add()");
|
|
438
|
+
expect("1.").toParseWithStructure("1");
|
|
439
|
+
expect("1/2").toParseWithStructure("1/2");
|
|
440
|
+
expect("1/-2").toParseWithStructure("-1/2");
|
|
441
|
+
expect("x/-2").toParseWithStructure("Mul(Var(x),-1/2)");
|
|
442
|
+
expect("a+b").toParseWithStructure("Add(Var(a),Var(b))");
|
|
443
|
+
expect("a+b+c").toParseWithStructure("Add(Var(a),Var(b),Var(c))");
|
|
444
|
+
expect("a-b").toParseWithStructure("Add(Var(a),Mul(-1,Var(b)))");
|
|
445
|
+
expect("a-b+c").toParseWithStructure(
|
|
446
|
+
"Add(Var(a),Mul(-1,Var(b)),Var(c))",
|
|
447
|
+
);
|
|
448
|
+
expect("abc").toParseWithStructure("Mul(Var(a),Var(b),Var(c))");
|
|
449
|
+
expect("a/bc").toParseWithStructure(
|
|
450
|
+
"Mul(Var(a),Pow(Var(b),-1),Var(c))",
|
|
451
|
+
);
|
|
452
|
+
expect("a*(b+c)").toParseWithStructure(
|
|
453
|
+
"Mul(Var(a),Add(Var(b),Var(c)))",
|
|
454
|
+
);
|
|
455
|
+
expect("x--y").toParseWithStructure("Add(Var(x),Mul(-1,-1,Var(y)))");
|
|
456
|
+
expect("--y").toParseWithStructure("Mul(-1,-1,Var(y))");
|
|
457
|
+
expect("e").toParseWithStructure("Const(e)");
|
|
458
|
+
expect("2e").toParseWithStructure("Mul(2,Const(e))");
|
|
459
|
+
expect("2e^x").toParseWithStructure("Mul(2,Pow(Const(e),Var(x)))");
|
|
460
|
+
expect("cdef").toParseWithStructure(
|
|
461
|
+
"Mul(Var(c),Var(d),Const(e),Var(f))",
|
|
462
|
+
);
|
|
463
|
+
expect("pi").toParseWithStructure("Const(pi)");
|
|
464
|
+
expect("pi^2").toParseWithStructure("Pow(Const(pi),2)");
|
|
465
|
+
expect("pir").toParseWithStructure("Mul(Const(pi),Var(r))");
|
|
466
|
+
expect("pir^2").toParseWithStructure("Mul(Const(pi),Pow(Var(r),2))");
|
|
467
|
+
expect("y=x^2").toParseWithStructure("Eq(Var(y),=,Pow(Var(x),2))");
|
|
468
|
+
expect("log_2x").toParseWithStructure("Log(2,Var(x))");
|
|
469
|
+
expect("f(x+y)").toParseWithStructure("Mul(Var(f),Add(Var(x),Var(y)))");
|
|
470
|
+
expect("f(x+y)").toParseWithStructure("Func(f,Add(Var(x),Var(y)))", {
|
|
471
|
+
functions: ["f"],
|
|
472
|
+
});
|
|
473
|
+
expect("sin(theta)").toParseWithStructure("Trig(sin,Var(theta))");
|
|
474
|
+
expect("tanh(theta)").toParseWithStructure("Trig(tanh,Var(theta))");
|
|
475
|
+
|
|
476
|
+
// verify that negative signs get folded into numbers
|
|
477
|
+
expect("-x*3").toParseWithStructure("Mul(Var(x),-3)");
|
|
478
|
+
expect("sin -x*3").toParseWithStructure("Trig(sin,Mul(Var(x),-3))");
|
|
479
|
+
});
|
|
480
|
+
});
|