@khanacademy/kmath 0.4.7 → 2.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
@@ -7,26 +7,30 @@ var _ = require('underscore');
7
7
  var perseusCore = require('@khanacademy/perseus-core');
8
8
  var $ = require('jquery');
9
9
 
10
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
11
11
 
12
- var ___default = /*#__PURE__*/_interopDefaultLegacy(_);
13
- var $__default = /*#__PURE__*/_interopDefaultLegacy($);
12
+ var ___default = /*#__PURE__*/_interopDefaultCompat(_);
13
+ var $__default = /*#__PURE__*/_interopDefaultCompat($);
14
14
 
15
15
  // This file is processed by a Rollup plugin (replace) to inject the production
16
+ // version number during the release build.
17
+ // In dev, you'll never see the version number.
18
+
16
19
  const libName = "@khanacademy/kmath";
17
- const libVersion = "0.4.7";
20
+ const libVersion = "2.0.0";
18
21
  perseusUtils.addLibraryVersionToPerseusDebug(libName, libVersion);
19
22
 
20
23
  /**
21
24
  * Number Utils
22
25
  * A number is a js-number, e.g. 5.12
23
26
  */
27
+
24
28
  const DEFAULT_TOLERANCE = 1e-9;
25
29
 
26
30
  // TODO: Should this just be Number.Epsilon
27
31
  const EPSILON = Math.pow(2, -42);
28
32
  function is$2(x) {
29
- return ___default["default"].isNumber(x) && !___default["default"].isNaN(x);
33
+ return ___default.default.isNumber(x) && !___default.default.isNaN(x);
30
34
  }
31
35
  function equal$4(x, y, tolerance) {
32
36
  // Checking for undefined makes this function behave nicely
@@ -110,14 +114,14 @@ var number = /*#__PURE__*/Object.freeze({
110
114
  __proto__: null,
111
115
  DEFAULT_TOLERANCE: DEFAULT_TOLERANCE,
112
116
  EPSILON: EPSILON,
113
- is: is$2,
117
+ ceilTo: ceilTo$2,
114
118
  equal: equal$4,
115
- sign: sign$1,
119
+ floorTo: floorTo$2,
120
+ is: is$2,
116
121
  isInteger: isInteger,
117
122
  round: round$2,
118
123
  roundTo: roundTo$2,
119
- floorTo: floorTo$2,
120
- ceilTo: ceilTo$2,
124
+ sign: sign$1,
121
125
  toFraction: toFraction
122
126
  });
123
127
 
@@ -125,6 +129,7 @@ var number = /*#__PURE__*/Object.freeze({
125
129
  * Vector Utils
126
130
  * A vector is an array of numbers e.g. [0, 3, 4].
127
131
  */
132
+
128
133
  function arraySum(array) {
129
134
  return array.reduce((memo, arg) => memo + arg, 0);
130
135
  }
@@ -315,32 +320,32 @@ function ceilTo$1(vec, increment) {
315
320
 
316
321
  var vector$1 = /*#__PURE__*/Object.freeze({
317
322
  __proto__: null,
318
- zip: zip,
319
- map: map,
320
- is: is$1,
321
- normalize: normalize,
322
- length: length,
323
- dot: dot,
324
323
  add: add$1,
325
- subtract: subtract,
326
- negate: negate,
327
- scale: scale,
328
- equal: equal$3,
324
+ angleDeg: angleDeg,
325
+ angleRad: angleRad,
326
+ cartFromPolarDeg: cartFromPolarDeg$1,
327
+ cartFromPolarRad: cartFromPolarRad$1,
328
+ ceilTo: ceilTo$1,
329
329
  codirectional: codirectional,
330
330
  collinear: collinear$1,
331
- polarRadFromCart: polarRadFromCart$1,
331
+ dot: dot,
332
+ equal: equal$3,
333
+ floorTo: floorTo$1,
334
+ is: is$1,
335
+ length: length,
336
+ map: map,
337
+ negate: negate,
338
+ normalize: normalize,
332
339
  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,
340
+ polarRadFromCart: polarRadFromCart$1,
339
341
  projection: projection,
342
+ rotateDeg: rotateDeg$1,
343
+ rotateRad: rotateRad$1,
340
344
  round: round$1,
341
345
  roundTo: roundTo$1,
342
- floorTo: floorTo$1,
343
- ceilTo: ceilTo$1
346
+ scale: scale,
347
+ subtract: subtract,
348
+ zip: zip
344
349
  });
345
350
 
346
351
  /**
@@ -348,6 +353,7 @@ var vector$1 = /*#__PURE__*/Object.freeze({
348
353
  * A point is an array of two numbers e.g. [0, 0].
349
354
  */
350
355
 
356
+
351
357
  // A point, in 2D, 3D, or nD space.
352
358
 
353
359
  // Rotate point (around origin unless a center is specified)
@@ -433,31 +439,32 @@ const ceilTo = ceilTo$1;
433
439
 
434
440
  var point = /*#__PURE__*/Object.freeze({
435
441
  __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
442
  addVector: addVector,
444
443
  addVectors: addVectors,
445
- subtractVector: subtractVector,
444
+ cartFromPolarDeg: cartFromPolarDeg,
445
+ cartFromPolarRad: cartFromPolarRad,
446
+ ceilTo: ceilTo,
447
+ compare: compare,
448
+ distanceToLine: distanceToLine,
449
+ distanceToPoint: distanceToPoint$1,
446
450
  equal: equal$2,
447
- polarRadFromCart: polarRadFromCart,
451
+ floorTo: floorTo,
452
+ is: is,
448
453
  polarDegFromCart: polarDegFromCart,
449
- cartFromPolarRad: cartFromPolarRad,
450
- cartFromPolarDeg: cartFromPolarDeg,
454
+ polarRadFromCart: polarRadFromCart,
455
+ reflectOverLine: reflectOverLine,
456
+ rotateDeg: rotateDeg,
457
+ rotateRad: rotateRad,
451
458
  round: round,
452
459
  roundTo: roundTo,
453
- floorTo: floorTo,
454
- ceilTo: ceilTo
460
+ subtractVector: subtractVector
455
461
  });
456
462
 
457
463
  /**
458
464
  * Line Utils
459
465
  * A line is an array of two points e.g. [[-5, 0], [5, 0]].
460
466
  */
467
+
461
468
  function distanceToPoint(line, point$1) {
462
469
  return distanceToLine(point$1, line);
463
470
  }
@@ -489,9 +496,9 @@ function equal$1(line1, line2, tolerance) {
489
496
  var line = /*#__PURE__*/Object.freeze({
490
497
  __proto__: null,
491
498
  distanceToPoint: distanceToPoint,
492
- reflectPoint: reflectPoint,
499
+ equal: equal$1,
493
500
  midpoint: midpoint,
494
- equal: equal$1
501
+ reflectPoint: reflectPoint
495
502
  });
496
503
 
497
504
  /**
@@ -500,6 +507,7 @@ var line = /*#__PURE__*/Object.freeze({
500
507
  * For example, [[0, 0], [1, 0]] is the ray starting at the origin and
501
508
  * traveling along the positive x-axis.
502
509
  */
510
+
503
511
  function equal(ray1, ray2, tolerance) {
504
512
  // Compare the directions of the rays
505
513
  const v1 = subtract(ray1[1], ray1[0]);
@@ -546,6 +554,8 @@ const KhanMath = {
546
554
  let mod;
547
555
  a = Math.abs(a);
548
556
  b = Math.abs(b);
557
+
558
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
549
559
  while (b) {
550
560
  mod = a % b;
551
561
  a = b;
@@ -569,7 +579,8 @@ const KhanMath = {
569
579
  return false;
570
580
  }
571
581
  if (n < 101) {
572
- return !!$__default["default"].grep(KhanMath.primes, function (p, i) {
582
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
583
+ return !!$__default.default.grep(KhanMath.primes, function (p, i) {
573
584
  return Math.abs(p - n) <= 0.5;
574
585
  }).length;
575
586
  }
@@ -594,7 +605,7 @@ const KhanMath = {
594
605
  const maxf = Math.sqrt(number);
595
606
  for (let f = 2; f <= maxf; f++) {
596
607
  if (number % f === 0) {
597
- return $__default["default"].merge(KhanMath.getPrimeFactorization(f), KhanMath.getPrimeFactorization(number / f));
608
+ return $__default.default.merge(KhanMath.getPrimeFactorization(f), KhanMath.getPrimeFactorization(number / f));
598
609
  }
599
610
  }
600
611
  },
@@ -680,7 +691,7 @@ const KhanMath = {
680
691
  // Note: purposively more inclusive than answer-types' predicate.forms
681
692
  // That is, it is not necessarily true that interpreted input are numeric
682
693
  getNumericFormat: function (text) {
683
- text = $__default["default"].trim(text);
694
+ text = $__default.default.trim(text);
684
695
  text = text.replace(/\u2212/, "-").replace(/([+-])\s+/g, "$1");
685
696
  if (text.match(/^[+-]?\d+$/)) {
686
697
  return "integer";
@@ -721,7 +732,7 @@ const KhanMath = {
721
732
  return sign + (numerator === 1 ? "" : numerator) + pi + (denominator === 1 ? "" : "/" + denominator);
722
733
  }
723
734
  }
724
- if (___default["default"](["proper", "improper", "mixed", "fraction"]).contains(format)) {
735
+ if (___default.default(["proper", "improper", "mixed", "fraction"]).contains(format)) {
725
736
  const fraction = toFraction(number$1);
726
737
  const numerator = Math.abs(fraction[0]);
727
738
  const denominator = fraction[1];
@@ -732,7 +743,9 @@ const KhanMath = {
732
743
  if (format === "mixed") {
733
744
  const modulus = numerator % denominator;
734
745
  const integer = (numerator - modulus) / denominator;
735
- return sign + (integer ? integer + " " : "") + modulus + "/" + denominator;
746
+ return sign + (
747
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
748
+ integer ? integer + " " : "") + modulus + "/" + denominator;
736
749
  } // otherwise proper, improper, or fraction
737
750
  return sign + numerator + "/" + denominator;
738
751
  }
@@ -752,6 +765,7 @@ function add(a, b) {
752
765
  * A collection of geomtry-related utility functions
753
766
  */
754
767
 
768
+
755
769
  // This should really be a readonly tuple of [number, number]
756
770
 
757
771
  // Given a number, return whether it is positive (1), negative (-1), or zero (0)
@@ -780,7 +794,7 @@ function pointInRect(a, b, c) {
780
794
  // http://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/
781
795
  function intersects(ab, cd) {
782
796
  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) {
797
+ const orientations = ___default.default.map(triplets, function (triplet) {
784
798
  return sign(ccw(...triplet));
785
799
  });
786
800
  if (orientations[0] !== orientations[1] && orientations[2] !== orientations[3]) {
@@ -821,7 +835,7 @@ function polygonSidesIntersect(vertices) {
821
835
  return false;
822
836
  }
823
837
  function vector(a, b) {
824
- return ___default["default"].map(___default["default"].zip(a, b), function (pair) {
838
+ return ___default.default.map(___default.default.zip(a, b), function (pair) {
825
839
  return pair[0] - pair[1];
826
840
  });
827
841
  }
@@ -833,8 +847,8 @@ function reverseVector(vector) {
833
847
  // path (assuming a closed loop, where the last point connects back to the
834
848
  // first).
835
849
  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) {
850
+ const segments = ___default.default.zip(points, points.slice(1).concat(points.slice(0, 1)));
851
+ const areas = ___default.default.map(segments, function (segment) {
838
852
  const p1 = segment[0];
839
853
  const p2 = segment[1];
840
854
  return (p2[0] - p1[0]) * (p2[1] + p1[1]);
@@ -842,18 +856,18 @@ function clockwise(points) {
842
856
  return sum(areas) > 0;
843
857
  }
844
858
  function magnitude(v) {
845
- return Math.sqrt(___default["default"].reduce(v, function (memo, el) {
859
+ return Math.sqrt(___default.default.reduce(v, function (memo, el) {
846
860
  // @ts-expect-error - TS2345 - Argument of type 'Coord' is not assignable to parameter of type 'number'.
847
861
  return memo + Math.pow(el, 2);
848
862
  }, 0));
849
863
  }
850
864
  function dotProduct(a, b) {
851
- return ___default["default"].reduce(___default["default"].zip(a, b), function (memo, pair) {
865
+ return ___default.default.reduce(___default.default.zip(a, b), function (memo, pair) {
852
866
  return memo + pair[0] * pair[1];
853
867
  }, 0);
854
868
  }
855
869
  function sideLengths(coords) {
856
- const segments = ___default["default"].zip(coords, rotate(coords));
870
+ const segments = ___default.default.zip(coords, rotate(coords));
857
871
  return segments.map(function (segment) {
858
872
  // @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
873
  return magnitude(vector(...segment));
@@ -862,8 +876,8 @@ function sideLengths(coords) {
862
876
 
863
877
  // Based on http://math.stackexchange.com/a/151149
864
878
  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) {
879
+ const triplets = ___default.default.zip(rotate(coords, -1), coords, rotate(coords, 1));
880
+ const offsets = ___default.default.map(triplets, function (triplet) {
867
881
  const p = vector(triplet[1], triplet[0]);
868
882
  const q = vector(triplet[2], triplet[1]);
869
883
  // @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[]'.
@@ -871,10 +885,10 @@ function angleMeasures(coords) {
871
885
  // @ts-expect-error - TS2556 - A spread argument must either have a tuple type or be passed to a rest parameter.
872
886
  return sign(ccw(...triplet)) > 0 ? raw : -raw;
873
887
  });
874
- const sum = ___default["default"].reduce(offsets, function (memo, arg) {
888
+ const sum = ___default.default.reduce(offsets, function (memo, arg) {
875
889
  return memo + arg;
876
890
  }, 0);
877
- return ___default["default"].map(offsets, function (offset) {
891
+ return ___default.default.map(offsets, function (offset) {
878
892
  return sum > 0 ? Math.PI - offset : Math.PI + offset;
879
893
  });
880
894
  }
@@ -908,14 +922,14 @@ function similar(coords1, coords2, tolerance) {
908
922
  // @ts-expect-error - TS4104 - The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
909
923
  sides = rotate(sides, i);
910
924
  if (perseusCore.approximateDeepEqual(angles1, angles)) {
911
- const sidePairs = ___default["default"].zip(sides1, sides);
912
- const factors = ___default["default"].map(sidePairs, function (pair) {
925
+ const sidePairs = ___default.default.zip(sides1, sides);
926
+ const factors = ___default.default.map(sidePairs, function (pair) {
913
927
  return pair[0] / pair[1];
914
928
  });
915
- const same = ___default["default"].all(factors, function (factor) {
929
+ const same = ___default.default.all(factors, function (factor) {
916
930
  return perseusCore.approximateEqual(factors[0], factor);
917
931
  });
918
- const congruentEnough = ___default["default"].all(sidePairs, function (pair) {
932
+ const congruentEnough = ___default.default.all(sidePairs, function (pair) {
919
933
  return equal$4(pair[0], pair[1], tolerance);
920
934
  });
921
935
  if (same && congruentEnough) {
@@ -1007,26 +1021,27 @@ function getLineIntersectionString(firstPoints, secondPoints) {
1007
1021
 
1008
1022
  var geometry = /*#__PURE__*/Object.freeze({
1009
1023
  __proto__: null,
1010
- sign: sign,
1024
+ angleMeasures: angleMeasures,
1025
+ canonicalSineCoefficients: canonicalSineCoefficients,
1011
1026
  ccw: ccw,
1027
+ clockwise: clockwise,
1012
1028
  collinear: collinear,
1029
+ getLineEquation: getLineEquation,
1030
+ getLineIntersection: getLineIntersection,
1031
+ getLineIntersectionString: getLineIntersectionString,
1013
1032
  intersects: intersects,
1033
+ lawOfCosines: lawOfCosines,
1034
+ magnitude: magnitude,
1014
1035
  polygonSidesIntersect: polygonSidesIntersect,
1015
- vector: vector,
1016
1036
  reverseVector: reverseVector,
1017
- clockwise: clockwise,
1018
- magnitude: magnitude,
1019
- angleMeasures: angleMeasures,
1020
- similar: similar,
1021
- lawOfCosines: lawOfCosines,
1022
- canonicalSineCoefficients: canonicalSineCoefficients,
1023
1037
  rotate: rotate,
1024
- getLineEquation: getLineEquation,
1025
- getLineIntersection: getLineIntersection,
1026
- getLineIntersectionString: getLineIntersectionString
1038
+ sign: sign,
1039
+ similar: similar,
1040
+ vector: vector
1027
1041
  });
1028
1042
 
1029
1043
  // This file contains helper functions for working with angles.
1044
+
1030
1045
  function convertDegreesToRadians(degrees) {
1031
1046
  return degrees / 180 * Math.PI;
1032
1047
  }
@@ -1057,6 +1072,7 @@ function polar(r, th) {
1057
1072
  const getAngleFromVertex = (point, vertex) => {
1058
1073
  const x = point[0] - vertex[0];
1059
1074
  const y = point[1] - vertex[1];
1075
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
1060
1076
  if (!x && !y) {
1061
1077
  return 0;
1062
1078
  }
@@ -1089,12 +1105,12 @@ const getClockwiseAngle = function (coords) {
1089
1105
 
1090
1106
  var angles = /*#__PURE__*/Object.freeze({
1091
1107
  __proto__: null,
1108
+ calculateAngleInDegrees: calculateAngleInDegrees,
1092
1109
  convertDegreesToRadians: convertDegreesToRadians,
1093
1110
  convertRadiansToDegrees: convertRadiansToDegrees,
1094
- calculateAngleInDegrees: calculateAngleInDegrees,
1095
- polar: polar,
1096
1111
  getAngleFromVertex: getAngleFromVertex,
1097
- getClockwiseAngle: getClockwiseAngle
1112
+ getClockwiseAngle: getClockwiseAngle,
1113
+ polar: polar
1098
1114
  });
1099
1115
 
1100
1116
  // TODO: there's another, very similar getSinusoidCoefficients function
@@ -1131,8 +1147,8 @@ function getQuadraticCoefficients(coords) {
1131
1147
 
1132
1148
  var coefficients = /*#__PURE__*/Object.freeze({
1133
1149
  __proto__: null,
1134
- getSinusoidCoefficients: getSinusoidCoefficients,
1135
- getQuadraticCoefficients: getQuadraticCoefficients
1150
+ getQuadraticCoefficients: getQuadraticCoefficients,
1151
+ getSinusoidCoefficients: getSinusoidCoefficients
1136
1152
  });
1137
1153
 
1138
1154
  exports.KhanMath = KhanMath;