@khanacademy/kmath 0.4.7 → 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.
package/dist/index.js CHANGED
@@ -1,40 +1,21 @@
1
- 'use strict';
1
+ import { addLibraryVersionToPerseusDebug } from '@khanacademy/perseus-utils';
2
+ import _ from 'underscore';
3
+ import { approximateEqual, approximateDeepEqual } from '@khanacademy/perseus-core';
4
+ import $ from 'jquery';
2
5
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var perseusUtils = require('@khanacademy/perseus-utils');
6
- var _ = require('underscore');
7
- var perseusCore = require('@khanacademy/perseus-core');
8
- var $ = require('jquery');
9
-
10
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
11
-
12
- var ___default = /*#__PURE__*/_interopDefaultLegacy(_);
13
- var $__default = /*#__PURE__*/_interopDefaultLegacy($);
14
-
15
- // This file is processed by a Rollup plugin (replace) to inject the production
16
6
  const libName = "@khanacademy/kmath";
17
- const libVersion = "0.4.7";
18
- perseusUtils.addLibraryVersionToPerseusDebug(libName, libVersion);
7
+ const libVersion = "1.0.0";
8
+ addLibraryVersionToPerseusDebug(libName, libVersion);
19
9
 
20
- /**
21
- * Number Utils
22
- * A number is a js-number, e.g. 5.12
23
- */
24
10
  const DEFAULT_TOLERANCE = 1e-9;
25
-
26
- // TODO: Should this just be Number.Epsilon
27
11
  const EPSILON = Math.pow(2, -42);
28
12
  function is$2(x) {
29
- return ___default["default"].isNumber(x) && !___default["default"].isNaN(x);
13
+ return _.isNumber(x) && !_.isNaN(x);
30
14
  }
31
15
  function equal$4(x, y, tolerance) {
32
- // Checking for undefined makes this function behave nicely
33
- // with vectors of different lengths that are _.zip'd together
34
16
  if (x == null || y == null) {
35
17
  return x === y;
36
18
  }
37
- // We check === here so that +/-Infinity comparisons work correctly
38
19
  if (x === y) {
39
20
  return true;
40
21
  }
@@ -43,21 +24,16 @@ function equal$4(x, y, tolerance) {
43
24
  }
44
25
  return Math.abs(x - y) < tolerance;
45
26
  }
46
- function sign$1(x, tolerance) /* Should be: 0 | 1 | -1 */{
27
+ function sign$1(x, tolerance) {
47
28
  return equal$4(x, 0, tolerance) ? 0 : Math.abs(x) / x;
48
29
  }
49
30
  function isInteger(num, tolerance) {
50
31
  return equal$4(Math.round(num), num, tolerance);
51
32
  }
52
-
53
- // Round a number to a certain number of decimal places
54
33
  function round$2(num, precision) {
55
34
  const factor = Math.pow(10, precision);
56
35
  return Math.round(num * factor) / factor;
57
36
  }
58
-
59
- // Round num to the nearest multiple of increment
60
- // i.e. roundTo(83, 5) -> 85
61
37
  function roundTo$2(num, increment) {
62
38
  return Math.round(num / increment) * increment;
63
39
  }
@@ -67,26 +43,7 @@ function floorTo$2(num, increment) {
67
43
  function ceilTo$2(num, increment) {
68
44
  return Math.ceil(num / increment) * increment;
69
45
  }
70
-
71
- /**
72
- * toFraction
73
- *
74
- * Returns a [numerator, denominator] array rational representation
75
- * of `decimal`
76
- *
77
- * See http://en.wikipedia.org/wiki/Continued_fraction for implementation
78
- * details
79
- *
80
- * toFraction(4/8) => [1, 2]
81
- * toFraction(0.66) => [33, 50]
82
- * toFraction(0.66, 0.01) => [2/3]
83
- * toFraction(283 + 1/3) => [850, 3]
84
- */
85
- function toFraction(decimal) {
86
- let tolerance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : EPSILON;
87
- let maxDenominator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1000;
88
- // Initialize everything to compute successive terms of
89
- // continued-fraction approximations via recurrence relation
46
+ function toFraction(decimal, tolerance = EPSILON, maxDenominator = 1000) {
90
47
  let n = [1, 0];
91
48
  let d = [0, 1];
92
49
  let a = Math.floor(decimal);
@@ -100,9 +57,6 @@ function toFraction(decimal) {
100
57
  a = Math.floor(1 / rem);
101
58
  rem = 1 / rem - a;
102
59
  }
103
-
104
- // We failed to find a nice rational representation,
105
- // so return an irrational "fraction"
106
60
  return [decimal, 1];
107
61
  }
108
62
 
@@ -110,31 +64,24 @@ var number = /*#__PURE__*/Object.freeze({
110
64
  __proto__: null,
111
65
  DEFAULT_TOLERANCE: DEFAULT_TOLERANCE,
112
66
  EPSILON: EPSILON,
113
- is: is$2,
67
+ ceilTo: ceilTo$2,
114
68
  equal: equal$4,
115
- sign: sign$1,
69
+ floorTo: floorTo$2,
70
+ is: is$2,
116
71
  isInteger: isInteger,
117
72
  round: round$2,
118
73
  roundTo: roundTo$2,
119
- floorTo: floorTo$2,
120
- ceilTo: ceilTo$2,
74
+ sign: sign$1,
121
75
  toFraction: toFraction
122
76
  });
123
77
 
124
- /**
125
- * Vector Utils
126
- * A vector is an array of numbers e.g. [0, 3, 4].
127
- */
128
78
  function arraySum(array) {
129
79
  return array.reduce((memo, arg) => memo + arg, 0);
130
80
  }
131
81
  function arrayProduct(array) {
132
82
  return array.reduce((memo, arg) => memo * arg, 1);
133
83
  }
134
- function zip() {
135
- for (var _len = arguments.length, arrays = new Array(_len), _key = 0; _key < _len; _key++) {
136
- arrays[_key] = arguments[_key];
137
- }
84
+ function zip(...arrays) {
138
85
  const n = Math.min(...arrays.map(a => a.length));
139
86
  const results = [];
140
87
  for (let i = 0; i < n; i++) {
@@ -145,16 +92,6 @@ function zip() {
145
92
  function map(pair, f) {
146
93
  return [f(pair[0], 0), f(pair[1], 1)];
147
94
  }
148
-
149
- /**
150
- * Checks if the given vector contains only numbers and, optionally, is of the
151
- * right dimension (length).
152
- *
153
- * is([1, 2, 3]) -> true
154
- * is([1, "Hello", 3]) -> false
155
- * is([1, 2, 3], 1) -> false
156
- */
157
-
158
95
  function is$1(vec, dimension) {
159
96
  if (!Array.isArray(vec)) {
160
97
  return false;
@@ -164,46 +101,30 @@ function is$1(vec, dimension) {
164
101
  }
165
102
  return vec.every(is$2);
166
103
  }
167
-
168
- // Normalize to a unit vector
169
104
  function normalize(v) {
170
105
  return scale(v, 1 / length(v));
171
106
  }
172
-
173
- // Length/magnitude of a vector
174
107
  function length(v) {
175
108
  return Math.sqrt(dot(v, v));
176
109
  }
177
- // Dot product of two vectors
178
110
  function dot(a, b) {
179
111
  const zipped = zip(a, b);
180
112
  const multiplied = zipped.map(arrayProduct);
181
113
  return arraySum(multiplied);
182
114
  }
183
-
184
- /* vector-add multiple [x, y] coords/vectors
185
- *
186
- * add([1, 2], [3, 4]) -> [4, 6]
187
- */
188
- function add$1() {
189
- const zipped = zip(...arguments);
190
- // @ts-expect-error - TS2322 - Type 'number[]' is not assignable to type 'V'.
115
+ function add$1(...vecs) {
116
+ const zipped = zip(...vecs);
191
117
  return zipped.map(arraySum);
192
118
  }
193
119
  function subtract(v1, v2) {
194
- // @ts-expect-error - TS2322 - Type 'number[]' is not assignable to type 'V'.
195
120
  return zip(v1, v2).map(dim => dim[0] - dim[1]);
196
121
  }
197
122
  function negate(v) {
198
- // @ts-expect-error - TS2322 - Type 'number[]' is not assignable to type 'V'.
199
123
  return v.map(x => {
200
124
  return -x;
201
125
  });
202
126
  }
203
-
204
- // Scale a vector
205
127
  function scale(v1, scalar) {
206
- // @ts-expect-error - TS2322 - Type 'number[]' is not assignable to type 'V'.
207
128
  return v1.map(x => {
208
129
  return x * scalar;
209
130
  });
@@ -212,9 +133,6 @@ function equal$3(v1, v2, tolerance) {
212
133
  return v1.length === v2.length && zip(v1, v2).every(pair => equal$4(pair[0], pair[1], tolerance));
213
134
  }
214
135
  function codirectional(v1, v2, tolerance) {
215
- // The origin is trivially codirectional with all other vectors.
216
- // This gives nice semantics for codirectionality between points when
217
- // comparing their difference vectors.
218
136
  if (equal$4(length(v1), 0, tolerance) || equal$4(length(v2), 0, tolerance)) {
219
137
  return true;
220
138
  }
@@ -225,48 +143,24 @@ function codirectional(v1, v2, tolerance) {
225
143
  function collinear$1(v1, v2, tolerance) {
226
144
  return codirectional(v1, v2, tolerance) || codirectional(v1, negate(v2), tolerance);
227
145
  }
228
-
229
- // TODO(jeremy) These coordinate conversion functions really only handle 2D points (ie. [number, number])
230
-
231
- // Convert a cartesian coordinate into a radian polar coordinate
232
146
  function polarRadFromCart$1(v) {
233
147
  const radius = length(v);
234
148
  let theta = Math.atan2(v[1], v[0]);
235
-
236
- // Convert angle range from [-pi, pi] to [0, 2pi]
237
149
  if (theta < 0) {
238
150
  theta += 2 * Math.PI;
239
151
  }
240
152
  return [radius, theta];
241
153
  }
242
-
243
- // Converts a cartesian coordinate into a degree polar coordinate
244
- function polarDegFromCart$1(v) /* TODO: convert to tuple/Point */{
154
+ function polarDegFromCart$1(v) {
245
155
  const polar = polarRadFromCart$1(v);
246
156
  return [polar[0], polar[1] * 180 / Math.PI];
247
157
  }
248
-
249
- /* Convert a polar coordinate into a cartesian coordinate
250
- *
251
- * Examples:
252
- * cartFromPolarRad(5, Math.PI)
253
- */
254
- function cartFromPolarRad$1(radius) /* TODO: convert to tuple/Point */{
255
- let theta = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
158
+ function cartFromPolarRad$1(radius, theta = 0) {
256
159
  return [radius * Math.cos(theta), radius * Math.sin(theta)];
257
160
  }
258
-
259
- /* Convert a polar coordinate into a cartesian coordinate
260
- *
261
- * Examples:
262
- * cartFromPolarDeg(5, 30)
263
- */
264
- function cartFromPolarDeg$1(radius) {
265
- let theta = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
161
+ function cartFromPolarDeg$1(radius, theta = 0) {
266
162
  return cartFromPolarRad$1(radius, theta * Math.PI / 180);
267
163
  }
268
-
269
- // Rotate vector
270
164
  function rotateRad$1(v, theta) {
271
165
  const polar = polarRadFromCart$1(v);
272
166
  const angle = polar[1] + theta;
@@ -277,80 +171,59 @@ function rotateDeg$1(v, theta) {
277
171
  const angle = polar[1] + theta;
278
172
  return cartFromPolarDeg$1(polar[0], angle);
279
173
  }
280
-
281
- // Angle between two vectors
282
174
  function angleRad(v1, v2) {
283
175
  return Math.acos(dot(v1, v2) / (length(v1) * length(v2)));
284
176
  }
285
177
  function angleDeg(v1, v2) {
286
178
  return angleRad(v1, v2) * 180 / Math.PI;
287
179
  }
288
-
289
- // Vector projection of v1 onto v2
290
180
  function projection(v1, v2) {
291
181
  const scalar = dot(v1, v2) / dot(v2, v2);
292
182
  return scale(v2, scalar);
293
183
  }
294
-
295
- // Round each number to a certain number of decimal places
296
184
  function round$1(vec, precision) {
297
- // @ts-expect-error - TS2322 - Type 'number[]' is not assignable to type 'V'.
298
185
  return vec.map((elem, i) => round$2(elem, precision[i] || precision));
299
186
  }
300
-
301
- // Round each number to the nearest increment
302
-
303
187
  function roundTo$1(vec, increment) {
304
- // @ts-expect-error - TS2322 - Type 'number[]' is not assignable to type 'V'.
305
188
  return vec.map((elem, i) => roundTo$2(elem, increment[i] || increment));
306
189
  }
307
190
  function floorTo$1(vec, increment) {
308
- // @ts-expect-error - TS2322 - Type 'number[]' is not assignable to type 'V'.
309
191
  return vec.map((elem, i) => floorTo$2(elem, increment[i] || increment));
310
192
  }
311
193
  function ceilTo$1(vec, increment) {
312
- // @ts-expect-error - TS2322 - Type 'number[]' is not assignable to type 'V'.
313
194
  return vec.map((elem, i) => ceilTo$2(elem, increment[i] || increment));
314
195
  }
315
196
 
316
197
  var vector$1 = /*#__PURE__*/Object.freeze({
317
198
  __proto__: null,
318
- zip: zip,
319
- map: map,
320
- is: is$1,
321
- normalize: normalize,
322
- length: length,
323
- dot: dot,
324
199
  add: add$1,
325
- subtract: subtract,
326
- negate: negate,
327
- scale: scale,
328
- equal: equal$3,
200
+ angleDeg: angleDeg,
201
+ angleRad: angleRad,
202
+ cartFromPolarDeg: cartFromPolarDeg$1,
203
+ cartFromPolarRad: cartFromPolarRad$1,
204
+ ceilTo: ceilTo$1,
329
205
  codirectional: codirectional,
330
206
  collinear: collinear$1,
331
- polarRadFromCart: polarRadFromCart$1,
207
+ dot: dot,
208
+ equal: equal$3,
209
+ floorTo: floorTo$1,
210
+ is: is$1,
211
+ length: length,
212
+ map: map,
213
+ negate: negate,
214
+ normalize: normalize,
332
215
  polarDegFromCart: polarDegFromCart$1,
333
- cartFromPolarRad: cartFromPolarRad$1,
334
- cartFromPolarDeg: cartFromPolarDeg$1,
335
- rotateRad: rotateRad$1,
336
- rotateDeg: rotateDeg$1,
337
- angleRad: angleRad,
338
- angleDeg: angleDeg,
216
+ polarRadFromCart: polarRadFromCart$1,
339
217
  projection: projection,
218
+ rotateDeg: rotateDeg$1,
219
+ rotateRad: rotateRad$1,
340
220
  round: round$1,
341
221
  roundTo: roundTo$1,
342
- floorTo: floorTo$1,
343
- ceilTo: ceilTo$1
222
+ scale: scale,
223
+ subtract: subtract,
224
+ zip: zip
344
225
  });
345
226
 
346
- /**
347
- * Point Utils
348
- * A point is an array of two numbers e.g. [0, 0].
349
- */
350
-
351
- // A point, in 2D, 3D, or nD space.
352
-
353
- // Rotate point (around origin unless a center is specified)
354
227
  function rotateRad(point, theta, center) {
355
228
  if (center === undefined) {
356
229
  return rotateRad$1(point, theta);
@@ -365,13 +238,9 @@ function rotateDeg(point, theta, center) {
365
238
  return add$1(center, rotateDeg$1(subtract(point, center), theta));
366
239
  }
367
240
  }
368
-
369
- // Distance between two points
370
241
  function distanceToPoint$1(point1, point2) {
371
242
  return length(subtract(point1, point2));
372
243
  }
373
-
374
- // Distance between point and line
375
244
  function distanceToLine(point, line) {
376
245
  const lv = subtract(line[1], line[0]);
377
246
  const pv = subtract(point, line[0]);
@@ -379,8 +248,6 @@ function distanceToLine(point, line) {
379
248
  const distancePv = subtract(projectedPv, pv);
380
249
  return length(distancePv);
381
250
  }
382
-
383
- // Reflect point over line
384
251
  function reflectOverLine(point, line) {
385
252
  const lv = subtract(line[1], line[0]);
386
253
  const pv = subtract(point, line[0]);
@@ -388,17 +255,7 @@ function reflectOverLine(point, line) {
388
255
  const reflectedPv = subtract(scale(projectedPv, 2), pv);
389
256
  return add$1(line[0], reflectedPv);
390
257
  }
391
-
392
- /**
393
- * Compares two points, returning -1, 0, or 1, for use with
394
- * Array.prototype.sort
395
- *
396
- * Note: This technically doesn't satisfy the total-ordering
397
- * requirements of Array.prototype.sort unless equalityTolerance
398
- * is 0. In some cases very close points that compare within a
399
- * few equalityTolerances could appear in the wrong order.
400
- */
401
- function compare(point1, point2, equalityTolerance) /* TODO: convert to -1 | 0 | 1 type */{
258
+ function compare(point1, point2, equalityTolerance) {
402
259
  if (point1.length !== point2.length) {
403
260
  return point1.length - point2.length;
404
261
  }
@@ -409,23 +266,15 @@ function compare(point1, point2, equalityTolerance) /* TODO: convert to -1 | 0 |
409
266
  }
410
267
  return 0;
411
268
  }
412
-
413
- // Check if a value is a point
414
269
  const is = is$1;
415
-
416
- // Add and subtract vector(s)
417
270
  const addVector = add$1;
418
271
  const addVectors = add$1;
419
272
  const subtractVector = subtract;
420
273
  const equal$2 = equal$3;
421
-
422
- // Convert from cartesian to polar and back
423
274
  const polarRadFromCart = polarRadFromCart$1;
424
275
  const polarDegFromCart = polarDegFromCart$1;
425
276
  const cartFromPolarRad = cartFromPolarRad$1;
426
277
  const cartFromPolarDeg = cartFromPolarDeg$1;
427
-
428
- // Rounding
429
278
  const round = round$1;
430
279
  const roundTo = roundTo$1;
431
280
  const floorTo = floorTo$1;
@@ -433,31 +282,27 @@ const ceilTo = ceilTo$1;
433
282
 
434
283
  var point = /*#__PURE__*/Object.freeze({
435
284
  __proto__: null,
436
- rotateRad: rotateRad,
437
- rotateDeg: rotateDeg,
438
- distanceToPoint: distanceToPoint$1,
439
- distanceToLine: distanceToLine,
440
- reflectOverLine: reflectOverLine,
441
- compare: compare,
442
- is: is,
443
285
  addVector: addVector,
444
286
  addVectors: addVectors,
445
- subtractVector: subtractVector,
287
+ cartFromPolarDeg: cartFromPolarDeg,
288
+ cartFromPolarRad: cartFromPolarRad,
289
+ ceilTo: ceilTo,
290
+ compare: compare,
291
+ distanceToLine: distanceToLine,
292
+ distanceToPoint: distanceToPoint$1,
446
293
  equal: equal$2,
447
- polarRadFromCart: polarRadFromCart,
294
+ floorTo: floorTo,
295
+ is: is,
448
296
  polarDegFromCart: polarDegFromCart,
449
- cartFromPolarRad: cartFromPolarRad,
450
- cartFromPolarDeg: cartFromPolarDeg,
297
+ polarRadFromCart: polarRadFromCart,
298
+ reflectOverLine: reflectOverLine,
299
+ rotateDeg: rotateDeg,
300
+ rotateRad: rotateRad,
451
301
  round: round,
452
302
  roundTo: roundTo,
453
- floorTo: floorTo,
454
- ceilTo: ceilTo
303
+ subtractVector: subtractVector
455
304
  });
456
305
 
457
- /**
458
- * Line Utils
459
- * A line is an array of two points e.g. [[-5, 0], [5, 0]].
460
- */
461
306
  function distanceToPoint(line, point$1) {
462
307
  return distanceToLine(point$1, line);
463
308
  }
@@ -468,20 +313,14 @@ function midpoint(line) {
468
313
  return [(line[0][0] + line[1][0]) / 2, (line[0][1] + line[1][1]) / 2];
469
314
  }
470
315
  function equal$1(line1, line2, tolerance) {
471
- // TODO: A nicer implementation might just check collinearity of
472
- // vectors using underscore magick
473
- // Compare the directions of the lines
474
316
  const v1 = subtract(line1[1], line1[0]);
475
317
  const v2 = subtract(line2[1], line2[0]);
476
318
  if (!collinear$1(v1, v2, tolerance)) {
477
319
  return false;
478
320
  }
479
- // If the start point is the same for the two lines, then they are the same
480
321
  if (equal$2(line1[0], line2[0])) {
481
322
  return true;
482
323
  }
483
- // Make sure that the direction to get from line1 to
484
- // line2 is the same as the direction of the lines
485
324
  const line1ToLine2Vector = subtract(line2[0], line1[0]);
486
325
  return collinear$1(v1, line1ToLine2Vector, tolerance);
487
326
  }
@@ -489,19 +328,12 @@ function equal$1(line1, line2, tolerance) {
489
328
  var line = /*#__PURE__*/Object.freeze({
490
329
  __proto__: null,
491
330
  distanceToPoint: distanceToPoint,
492
- reflectPoint: reflectPoint,
331
+ equal: equal$1,
493
332
  midpoint: midpoint,
494
- equal: equal$1
333
+ reflectPoint: reflectPoint
495
334
  });
496
335
 
497
- /**
498
- * Ray Utils
499
- * A ray (→) is an array of an endpoint and another point along the ray.
500
- * For example, [[0, 0], [1, 0]] is the ray starting at the origin and
501
- * traveling along the positive x-axis.
502
- */
503
336
  function equal(ray1, ray2, tolerance) {
504
- // Compare the directions of the rays
505
337
  const v1 = subtract(ray1[1], ray1[0]);
506
338
  const v2 = subtract(ray2[1], ray2[0]);
507
339
  const sameOrigin = equal$2(ray1[0], ray2[0]);
@@ -515,11 +347,9 @@ var ray = /*#__PURE__*/Object.freeze({
515
347
  });
516
348
 
517
349
  const KhanMath = {
518
- // Simplify formulas before display
519
350
  cleanMath: function (expr) {
520
351
  return typeof expr === "string" ? expr.replace(/\+\s*-/g, "- ").replace(/-\s*-/g, "+ ").replace(/\^1/g, "") : expr;
521
352
  },
522
- // Bound a number by 1e-6 and 1e20 to avoid exponents after toString
523
353
  bound: function (num) {
524
354
  if (num === 0) {
525
355
  return num;
@@ -537,10 +367,7 @@ const KhanMath = {
537
367
  },
538
368
  getGCD: function (a, b) {
539
369
  if (arguments.length > 2) {
540
- // TODO(kevinb): rewrite using rest args instead of arguments
541
- // eslint-disable-next-line prefer-rest-params
542
370
  const rest = [].slice.call(arguments, 1);
543
- // @ts-expect-error - TS2556 - A spread argument must either have a tuple type or be passed to a rest parameter.
544
371
  return KhanMath.getGCD(a, KhanMath.getGCD(...rest));
545
372
  }
546
373
  let mod;
@@ -555,10 +382,7 @@ const KhanMath = {
555
382
  },
556
383
  getLCM: function (a, b) {
557
384
  if (arguments.length > 2) {
558
- // TODO(kevinb): rewrite using rest args instead of arguments
559
- // eslint-disable-next-line prefer-rest-params
560
385
  const rest = [].slice.call(arguments, 1);
561
- // @ts-expect-error - TS2556 - A spread argument must either have a tuple type or be passed to a rest parameter.
562
386
  return KhanMath.getLCM(a, KhanMath.getLCM(...rest));
563
387
  }
564
388
  return Math.abs(a * b) / KhanMath.getGCD(a, b);
@@ -569,7 +393,7 @@ const KhanMath = {
569
393
  return false;
570
394
  }
571
395
  if (n < 101) {
572
- return !!$__default["default"].grep(KhanMath.primes, function (p, i) {
396
+ return !!$.grep(KhanMath.primes, function (p, i) {
573
397
  return Math.abs(p - n) <= 0.5;
574
398
  }).length;
575
399
  }
@@ -583,7 +407,6 @@ const KhanMath = {
583
407
  }
584
408
  return true;
585
409
  },
586
- // @ts-expect-error - TS2366 - Function lacks ending return statement and return type does not include 'undefined'.
587
410
  getPrimeFactorization: function (number) {
588
411
  if (number === 1) {
589
412
  return [];
@@ -594,39 +417,24 @@ const KhanMath = {
594
417
  const maxf = Math.sqrt(number);
595
418
  for (let f = 2; f <= maxf; f++) {
596
419
  if (number % f === 0) {
597
- return $__default["default"].merge(KhanMath.getPrimeFactorization(f), KhanMath.getPrimeFactorization(number / f));
420
+ return $.merge(KhanMath.getPrimeFactorization(f), KhanMath.getPrimeFactorization(number / f));
598
421
  }
599
422
  }
600
423
  },
601
- // Round a number to the nearest increment
602
- // E.g., if increment = 30 and num = 40, return 30. if increment = 30 and
603
- // num = 45, return 60.
604
424
  roundToNearest: function (increment, num) {
605
425
  return Math.round(num / increment) * increment;
606
426
  },
607
- // Round a number to a certain number of decimal places
608
427
  roundTo: function (precision, num) {
609
428
  const factor = Math.pow(10, precision).toFixed(5);
610
- // @ts-expect-error - TS2345 - Argument of type 'string' is not assignable to parameter of type 'number'. | TS2363 - The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type. | TS2363 - The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.
611
429
  return Math.round((num * factor).toFixed(5)) / factor;
612
430
  },
613
- /**
614
- * Return a string of num rounded to a fixed precision decimal places,
615
- * with an approx symbol if num had to be rounded, and trailing 0s
616
- */
617
431
  toFixedApprox: function (num, precision) {
618
- // TODO(aria): Make this locale-dependent
619
432
  const fixedStr = num.toFixed(precision);
620
433
  if (equal$4(+fixedStr, num)) {
621
434
  return fixedStr;
622
435
  }
623
436
  return "\\approx " + fixedStr;
624
437
  },
625
- /**
626
- * Return a string of num rounded to precision decimal places, with an
627
- * approx symbol if num had to be rounded, but no trailing 0s if it was
628
- * not rounded.
629
- */
630
438
  roundToApprox: function (num, precision) {
631
439
  const fixed = KhanMath.roundTo(precision, num);
632
440
  if (equal$4(fixed, num)) {
@@ -634,11 +442,6 @@ const KhanMath = {
634
442
  }
635
443
  return KhanMath.toFixedApprox(num, precision);
636
444
  },
637
- // toFraction(4/8) => [1, 2]
638
- // toFraction(0.666) => [333, 500]
639
- // toFraction(0.666, 0.001) => [2, 3]
640
- //
641
- // tolerance can't be bigger than 1, sorry
642
445
  toFraction: function (decimal, tolerance) {
643
446
  if (tolerance == null) {
644
447
  tolerance = Math.pow(2, -46);
@@ -659,8 +462,6 @@ const KhanMath = {
659
462
  let hiD = 1;
660
463
  let midN = 1;
661
464
  let midD = 2;
662
-
663
- // eslint-disable-next-line no-constant-condition
664
465
  while (true) {
665
466
  if (Math.abs(Number(midN / midD) - decimal) <= tolerance) {
666
467
  return [midN, midD];
@@ -676,11 +477,8 @@ const KhanMath = {
676
477
  midD = loD + hiD;
677
478
  }
678
479
  },
679
- // Returns the format (string) of a given numeric string
680
- // Note: purposively more inclusive than answer-types' predicate.forms
681
- // That is, it is not necessarily true that interpreted input are numeric
682
480
  getNumericFormat: function (text) {
683
- text = $__default["default"].trim(text);
481
+ text = $.trim(text);
684
482
  text = text.replace(/\u2212/, "-").replace(/([+-])\s+/g, "$1");
685
483
  if (text.match(/^[+-]?\d+$/)) {
686
484
  return "integer";
@@ -700,13 +498,12 @@ const KhanMath = {
700
498
  }
701
499
  return null;
702
500
  },
703
- // Returns a string of the number in a specified format
704
501
  toNumericString: function (number$1, format) {
705
502
  if (number$1 == null) {
706
503
  return "";
707
504
  }
708
505
  if (number$1 === 0) {
709
- return "0"; // otherwise it might end up as 0% or 0pi
506
+ return "0";
710
507
  }
711
508
  if (format === "percent") {
712
509
  return number$1 * 100 + "%";
@@ -721,23 +518,21 @@ const KhanMath = {
721
518
  return sign + (numerator === 1 ? "" : numerator) + pi + (denominator === 1 ? "" : "/" + denominator);
722
519
  }
723
520
  }
724
- if (___default["default"](["proper", "improper", "mixed", "fraction"]).contains(format)) {
521
+ if (_(["proper", "improper", "mixed", "fraction"]).contains(format)) {
725
522
  const fraction = toFraction(number$1);
726
523
  const numerator = Math.abs(fraction[0]);
727
524
  const denominator = fraction[1];
728
525
  const sign = number$1 < 0 ? "-" : "";
729
526
  if (denominator === 1) {
730
- return sign + numerator; // for integers, irrational, d > 1000
527
+ return sign + numerator;
731
528
  }
732
529
  if (format === "mixed") {
733
530
  const modulus = numerator % denominator;
734
531
  const integer = (numerator - modulus) / denominator;
735
532
  return sign + (integer ? integer + " " : "") + modulus + "/" + denominator;
736
- } // otherwise proper, improper, or fraction
533
+ }
737
534
  return sign + numerator + "/" + denominator;
738
535
  }
739
-
740
- // otherwise (decimal, float, long long)
741
536
  return String(number$1);
742
537
  }
743
538
  };
@@ -748,39 +543,24 @@ function add(a, b) {
748
543
  return a + b;
749
544
  }
750
545
 
751
- /**
752
- * A collection of geomtry-related utility functions
753
- */
754
-
755
- // This should really be a readonly tuple of [number, number]
756
-
757
- // Given a number, return whether it is positive (1), negative (-1), or zero (0)
758
546
  function sign(val) {
759
- if (perseusCore.approximateEqual(val, 0)) {
547
+ if (approximateEqual(val, 0)) {
760
548
  return 0;
761
549
  }
762
550
  return val > 0 ? 1 : -1;
763
551
  }
764
-
765
- // Determine whether three points are collinear (0), for a clockwise turn (negative),
766
- // or counterclockwise turn (positive)
767
552
  function ccw(a, b, c) {
768
553
  return (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]);
769
554
  }
770
555
  function collinear(a, b, c) {
771
- return perseusCore.approximateEqual(ccw(a, b, c), 0);
556
+ return approximateEqual(ccw(a, b, c), 0);
772
557
  }
773
-
774
- // Given rect bounding points A and B, whether point C is inside the rect
775
558
  function pointInRect(a, b, c) {
776
559
  return c[0] <= Math.max(a[0], b[0]) && c[0] >= Math.min(a[0], b[0]) && c[1] <= Math.max(a[1], b[1]) && c[1] >= Math.min(a[1], b[1]);
777
560
  }
778
-
779
- // Whether line segment AB intersects line segment CD
780
- // http://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/
781
561
  function intersects(ab, cd) {
782
562
  const triplets = [[ab[0], ab[1], cd[0]], [ab[0], ab[1], cd[1]], [cd[0], cd[1], ab[0]], [cd[0], cd[1], ab[1]]];
783
- const orientations = ___default["default"].map(triplets, function (triplet) {
563
+ const orientations = _.map(triplets, function (triplet) {
784
564
  return sign(ccw(...triplet));
785
565
  });
786
566
  if (orientations[0] !== orientations[1] && orientations[2] !== orientations[3]) {
@@ -793,21 +573,14 @@ function intersects(ab, cd) {
793
573
  }
794
574
  return false;
795
575
  }
796
-
797
- // Whether any two sides of a polygon intersect each other
798
576
  function polygonSidesIntersect(vertices) {
799
577
  for (let i = 0; i < vertices.length; i++) {
800
578
  for (let k = i + 1; k < vertices.length; k++) {
801
- // If any two vertices are the same point, sides overlap
802
579
  if (equal$2(vertices[i], vertices[k])) {
803
580
  return true;
804
581
  }
805
-
806
- // Find the other end of the sides starting at vertices i and k
807
582
  const iNext = (i + 1) % vertices.length;
808
583
  const kNext = (k + 1) % vertices.length;
809
-
810
- // Adjacent sides always intersect (at the vertex); skip those
811
584
  if (iNext === k || kNext === i) {
812
585
  continue;
813
586
  }
@@ -821,20 +594,16 @@ function polygonSidesIntersect(vertices) {
821
594
  return false;
822
595
  }
823
596
  function vector(a, b) {
824
- return ___default["default"].map(___default["default"].zip(a, b), function (pair) {
597
+ return _.map(_.zip(a, b), function (pair) {
825
598
  return pair[0] - pair[1];
826
599
  });
827
600
  }
828
601
  function reverseVector(vector) {
829
602
  return [-vector[0], -vector[1]];
830
603
  }
831
-
832
- // Returns whether connecting the given sequence of `points` forms a clockwise
833
- // path (assuming a closed loop, where the last point connects back to the
834
- // first).
835
604
  function clockwise(points) {
836
- const segments = ___default["default"].zip(points, points.slice(1).concat(points.slice(0, 1)));
837
- const areas = ___default["default"].map(segments, function (segment) {
605
+ const segments = _.zip(points, points.slice(1).concat(points.slice(0, 1)));
606
+ const areas = _.map(segments, function (segment) {
838
607
  const p1 = segment[0];
839
608
  const p2 = segment[1];
840
609
  return (p2[0] - p1[0]) * (p2[1] + p1[1]);
@@ -842,44 +611,36 @@ function clockwise(points) {
842
611
  return sum(areas) > 0;
843
612
  }
844
613
  function magnitude(v) {
845
- return Math.sqrt(___default["default"].reduce(v, function (memo, el) {
846
- // @ts-expect-error - TS2345 - Argument of type 'Coord' is not assignable to parameter of type 'number'.
614
+ return Math.sqrt(_.reduce(v, function (memo, el) {
847
615
  return memo + Math.pow(el, 2);
848
616
  }, 0));
849
617
  }
850
618
  function dotProduct(a, b) {
851
- return ___default["default"].reduce(___default["default"].zip(a, b), function (memo, pair) {
619
+ return _.reduce(_.zip(a, b), function (memo, pair) {
852
620
  return memo + pair[0] * pair[1];
853
621
  }, 0);
854
622
  }
855
623
  function sideLengths(coords) {
856
- const segments = ___default["default"].zip(coords, rotate(coords));
624
+ const segments = _.zip(coords, rotate(coords));
857
625
  return segments.map(function (segment) {
858
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'readonly Coord[]'. | TS2556 - A spread argument must either have a tuple type or be passed to a rest parameter.
859
626
  return magnitude(vector(...segment));
860
627
  });
861
628
  }
862
-
863
- // Based on http://math.stackexchange.com/a/151149
864
629
  function angleMeasures(coords) {
865
- const triplets = ___default["default"].zip(rotate(coords, -1), coords, rotate(coords, 1));
866
- const offsets = ___default["default"].map(triplets, function (triplet) {
630
+ const triplets = _.zip(rotate(coords, -1), coords, rotate(coords, 1));
631
+ const offsets = _.map(triplets, function (triplet) {
867
632
  const p = vector(triplet[1], triplet[0]);
868
633
  const q = vector(triplet[2], triplet[1]);
869
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'Coord'. | TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'readonly Coord[]'. | TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'readonly Coord[]'.
870
634
  const raw = Math.acos(dotProduct(p, q) / (magnitude(p) * magnitude(q)));
871
- // @ts-expect-error - TS2556 - A spread argument must either have a tuple type or be passed to a rest parameter.
872
635
  return sign(ccw(...triplet)) > 0 ? raw : -raw;
873
636
  });
874
- const sum = ___default["default"].reduce(offsets, function (memo, arg) {
637
+ const sum = _.reduce(offsets, function (memo, arg) {
875
638
  return memo + arg;
876
639
  }, 0);
877
- return ___default["default"].map(offsets, function (offset) {
640
+ return _.map(offsets, function (offset) {
878
641
  return sum > 0 ? Math.PI - offset : Math.PI + offset;
879
642
  });
880
643
  }
881
-
882
- // Whether two polygons are similar (or if specified, congruent)
883
644
  function similar(coords1, coords2, tolerance) {
884
645
  if (coords1.length !== coords2.length) {
885
646
  return false;
@@ -892,30 +653,22 @@ function similar(coords1, coords2, tolerance) {
892
653
  for (let i = 0; i < 2 * n; i++) {
893
654
  let angles = angles2.slice();
894
655
  let sides = sides2.slice();
895
-
896
- // Reverse angles and sides to allow matching reflected polygons
897
656
  if (i >= n) {
898
657
  angles.reverse();
899
658
  sides.reverse();
900
- // Since sides are calculated from two coordinates,
901
- // simply reversing results in an off by one error
902
- // @ts-expect-error - TS4104 - The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
903
659
  sides = rotate(sides, 1);
904
660
  }
905
-
906
- // @ts-expect-error - TS4104 - The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
907
661
  angles = rotate(angles, i);
908
- // @ts-expect-error - TS4104 - The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
909
662
  sides = rotate(sides, i);
910
- if (perseusCore.approximateDeepEqual(angles1, angles)) {
911
- const sidePairs = ___default["default"].zip(sides1, sides);
912
- const factors = ___default["default"].map(sidePairs, function (pair) {
663
+ if (approximateDeepEqual(angles1, angles)) {
664
+ const sidePairs = _.zip(sides1, sides);
665
+ const factors = _.map(sidePairs, function (pair) {
913
666
  return pair[0] / pair[1];
914
667
  });
915
- const same = ___default["default"].all(factors, function (factor) {
916
- return perseusCore.approximateEqual(factors[0], factor);
668
+ const same = _.all(factors, function (factor) {
669
+ return approximateEqual(factors[0], factor);
917
670
  });
918
- const congruentEnough = ___default["default"].all(sidePairs, function (pair) {
671
+ const congruentEnough = _.all(sidePairs, function (pair) {
919
672
  return equal$4(pair[0], pair[1], tolerance);
920
673
  });
921
674
  if (same && congruentEnough) {
@@ -925,32 +678,21 @@ function similar(coords1, coords2, tolerance) {
925
678
  }
926
679
  return false;
927
680
  }
928
-
929
- // Given triangle with sides ABC return angle opposite side C in degrees
930
681
  function lawOfCosines(a, b, c) {
931
682
  return Math.acos((a * a + b * b - c * c) / (2 * a * b)) * 180 / Math.PI;
932
683
  }
933
- function canonicalSineCoefficients(_ref) {
934
- let [amplitude, angularFrequency, phase, verticalOffset] = _ref;
935
- // For a curve of the form f(x) = a * Sin(b * x - c) + d,
936
- // this function ensures that a, b > 0, and c is its
937
- // smallest possible positive value.
938
-
939
- // Guarantee a > 0
684
+ function canonicalSineCoefficients([amplitude, angularFrequency, phase, verticalOffset]) {
940
685
  if (amplitude < 0) {
941
686
  amplitude *= -1;
942
687
  angularFrequency *= -1;
943
688
  phase *= -1;
944
689
  }
945
690
  const period = 2 * Math.PI;
946
- // Guarantee b > 0
947
691
  if (angularFrequency < 0) {
948
692
  angularFrequency *= -1;
949
693
  phase *= -1;
950
694
  phase += period / 2;
951
695
  }
952
-
953
- // Guarantee c is smallest possible positive value
954
696
  while (phase > 0) {
955
697
  phase -= period;
956
698
  }
@@ -959,26 +701,19 @@ function canonicalSineCoefficients(_ref) {
959
701
  }
960
702
  return [amplitude, angularFrequency, phase, verticalOffset];
961
703
  }
962
-
963
- // e.g. rotate([1, 2, 3]) -> [2, 3, 1]
964
704
  function rotate(array, n) {
965
705
  n = typeof n === "undefined" ? 1 : n % array.length;
966
706
  return array.slice(n).concat(array.slice(0, n));
967
707
  }
968
708
  function getLineEquation(first, second) {
969
- if (perseusCore.approximateEqual(first[0], second[0])) {
709
+ if (approximateEqual(first[0], second[0])) {
970
710
  return "x = " + first[0].toFixed(3);
971
711
  }
972
712
  const m = (second[1] - first[1]) / (second[0] - first[0]);
973
713
  const b = first[1] - m * first[0];
974
714
  return "y = " + m.toFixed(3) + "x + " + b.toFixed(3);
975
715
  }
976
-
977
- // Stolen from the wikipedia article
978
- // http://en.wikipedia.org/wiki/Line-line_intersection
979
- function getLineIntersection(
980
- // TODO(LP-10725): update these to be 2-tuples
981
- firstPoints, secondPoints) {
716
+ function getLineIntersection(firstPoints, secondPoints) {
982
717
  const x1 = firstPoints[0][0];
983
718
  const y1 = firstPoints[0][1];
984
719
  const x2 = firstPoints[1][0];
@@ -989,7 +724,6 @@ firstPoints, secondPoints) {
989
724
  const y4 = secondPoints[1][1];
990
725
  const determinant = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
991
726
  if (Math.abs(determinant) < 1e-9) {
992
- // Lines are parallel
993
727
  return null;
994
728
  }
995
729
  const x = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / determinant;
@@ -1007,43 +741,35 @@ function getLineIntersectionString(firstPoints, secondPoints) {
1007
741
 
1008
742
  var geometry = /*#__PURE__*/Object.freeze({
1009
743
  __proto__: null,
1010
- sign: sign,
744
+ angleMeasures: angleMeasures,
745
+ canonicalSineCoefficients: canonicalSineCoefficients,
1011
746
  ccw: ccw,
747
+ clockwise: clockwise,
1012
748
  collinear: collinear,
749
+ getLineEquation: getLineEquation,
750
+ getLineIntersection: getLineIntersection,
751
+ getLineIntersectionString: getLineIntersectionString,
1013
752
  intersects: intersects,
753
+ lawOfCosines: lawOfCosines,
754
+ magnitude: magnitude,
1014
755
  polygonSidesIntersect: polygonSidesIntersect,
1015
- vector: vector,
1016
756
  reverseVector: reverseVector,
1017
- clockwise: clockwise,
1018
- magnitude: magnitude,
1019
- angleMeasures: angleMeasures,
1020
- similar: similar,
1021
- lawOfCosines: lawOfCosines,
1022
- canonicalSineCoefficients: canonicalSineCoefficients,
1023
757
  rotate: rotate,
1024
- getLineEquation: getLineEquation,
1025
- getLineIntersection: getLineIntersection,
1026
- getLineIntersectionString: getLineIntersectionString
758
+ sign: sign,
759
+ similar: similar,
760
+ vector: vector
1027
761
  });
1028
762
 
1029
- // This file contains helper functions for working with angles.
1030
763
  function convertDegreesToRadians(degrees) {
1031
764
  return degrees / 180 * Math.PI;
1032
765
  }
1033
766
  function convertRadiansToDegrees(radians) {
1034
767
  const degree = radians / Math.PI * 180;
1035
- // Account for floating point errors.
1036
768
  return Number(degree.toPrecision(15));
1037
769
  }
1038
-
1039
- // Returns a value between -180 and 180, inclusive. The angle is measured
1040
- // between the positive x-axis and the given vector.
1041
- function calculateAngleInDegrees(_ref) {
1042
- let [x, y] = _ref;
770
+ function calculateAngleInDegrees([x, y]) {
1043
771
  return Math.atan2(y, x) * 180 / Math.PI;
1044
772
  }
1045
-
1046
- // Converts polar coordinates to cartesian. The th(eta) parameter is in degrees.
1047
773
  function polar(r, th) {
1048
774
  if (typeof r === "number") {
1049
775
  r = [r, r];
@@ -1051,9 +777,6 @@ function polar(r, th) {
1051
777
  th = th * Math.PI / 180;
1052
778
  return [r[0] * Math.cos(th), r[1] * Math.sin(th)];
1053
779
  }
1054
- // This function calculates the angle between two points and an optional vertex.
1055
- // If the vertex is not provided, the angle is measured between the two points.
1056
- // This does not account for reflex angles or clockwise position.
1057
780
  const getAngleFromVertex = (point, vertex) => {
1058
781
  const x = point[0] - vertex[0];
1059
782
  const y = point[1] - vertex[1];
@@ -1062,25 +785,11 @@ const getAngleFromVertex = (point, vertex) => {
1062
785
  }
1063
786
  return (180 + Math.atan2(-y, -x) * 180 / Math.PI + 360) % 360;
1064
787
  };
1065
-
1066
- // This function calculates the clockwise angle between three points,
1067
- // and is used to generate the labels and equation strings of the
1068
- // current angle for the interactive graph.
1069
- const getClockwiseAngle = function (coords) {
1070
- let allowReflexAngles = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
788
+ const getClockwiseAngle = (coords, allowReflexAngles = false) => {
1071
789
  const coordsCopy = [...coords];
1072
- // The coords are saved as [point1, vertex, point2] in the interactive graph
1073
790
  const areClockwise = clockwise([coordsCopy[0], coordsCopy[2], coordsCopy[1]]);
1074
-
1075
- // We may need to reverse the coordinates if we allow
1076
- // reflex angles and the points are not in clockwise order.
1077
791
  const shouldReverseCoords = !areClockwise || allowReflexAngles;
1078
-
1079
- // Reverse the coordinates accordingly to ensure the angle is calculated correctly
1080
792
  const clockwiseCoords = shouldReverseCoords ? coordsCopy.reverse() : coordsCopy;
1081
-
1082
- // Calculate the angles between the two points and get the difference
1083
- // between the two angles to get the clockwise angle.
1084
793
  const startAngle = getAngleFromVertex(clockwiseCoords[0], clockwiseCoords[1]);
1085
794
  const endAngle = getAngleFromVertex(clockwiseCoords[2], clockwiseCoords[1]);
1086
795
  const angle = (startAngle + 360 - endAngle) % 360;
@@ -1089,38 +798,29 @@ const getClockwiseAngle = function (coords) {
1089
798
 
1090
799
  var angles = /*#__PURE__*/Object.freeze({
1091
800
  __proto__: null,
801
+ calculateAngleInDegrees: calculateAngleInDegrees,
1092
802
  convertDegreesToRadians: convertDegreesToRadians,
1093
803
  convertRadiansToDegrees: convertRadiansToDegrees,
1094
- calculateAngleInDegrees: calculateAngleInDegrees,
1095
- polar: polar,
1096
804
  getAngleFromVertex: getAngleFromVertex,
1097
- getClockwiseAngle: getClockwiseAngle
805
+ getClockwiseAngle: getClockwiseAngle,
806
+ polar: polar
1098
807
  });
1099
808
 
1100
- // TODO: there's another, very similar getSinusoidCoefficients function
1101
- // they should probably be merged
1102
809
  function getSinusoidCoefficients(coords) {
1103
- // It's assumed that p1 is the root and p2 is the first peak
1104
810
  const p1 = coords[0];
1105
811
  const p2 = coords[1];
1106
-
1107
- // Resulting coefficients are canonical for this sine curve
1108
812
  const amplitude = p2[1] - p1[1];
1109
813
  const angularFrequency = Math.PI / (2 * (p2[0] - p1[0]));
1110
814
  const phase = p1[0] * angularFrequency;
1111
815
  const verticalOffset = p1[1];
1112
816
  return [amplitude, angularFrequency, phase, verticalOffset];
1113
817
  }
1114
- // TODO: there's another, very similar getQuadraticCoefficients function
1115
- // they should probably be merged
1116
818
  function getQuadraticCoefficients(coords) {
1117
819
  const p1 = coords[0];
1118
820
  const p2 = coords[1];
1119
821
  const p3 = coords[2];
1120
822
  const denom = (p1[0] - p2[0]) * (p1[0] - p3[0]) * (p2[0] - p3[0]);
1121
823
  if (denom === 0) {
1122
- // Many of the callers assume that the return value is always defined.
1123
- // @ts-expect-error - TS2322 - Type 'undefined' is not assignable to type 'QuadraticCoefficient'.
1124
824
  return;
1125
825
  }
1126
826
  const a = (p3[0] * (p2[1] - p1[1]) + p2[0] * (p1[1] - p3[1]) + p1[0] * (p3[1] - p2[1])) / denom;
@@ -1131,19 +831,9 @@ function getQuadraticCoefficients(coords) {
1131
831
 
1132
832
  var coefficients = /*#__PURE__*/Object.freeze({
1133
833
  __proto__: null,
1134
- getSinusoidCoefficients: getSinusoidCoefficients,
1135
- getQuadraticCoefficients: getQuadraticCoefficients
834
+ getQuadraticCoefficients: getQuadraticCoefficients,
835
+ getSinusoidCoefficients: getSinusoidCoefficients
1136
836
  });
1137
837
 
1138
- exports.KhanMath = KhanMath;
1139
- exports.angles = angles;
1140
- exports.coefficients = coefficients;
1141
- exports.geometry = geometry;
1142
- exports.libVersion = libVersion;
1143
- exports.line = line;
1144
- exports.number = number;
1145
- exports.point = point;
1146
- exports.ray = ray;
1147
- exports.sum = sum;
1148
- exports.vector = vector$1;
838
+ export { KhanMath, angles, coefficients, geometry, libVersion, line, number, point, ray, sum, vector$1 as vector };
1149
839
  //# sourceMappingURL=index.js.map