@khanacademy/kmath 0.0.4 → 0.0.6

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/package.json CHANGED
@@ -1,10 +1,19 @@
1
1
  {
2
+ "name": "@khanacademy/kmath",
3
+ "description": "Khan Academy's Javascript Numeric Math Utilities",
4
+ "author": "Khan Academy",
5
+ "license": "MIT",
6
+ "version": "0.0.6",
2
7
  "publishConfig": {
3
8
  "access": "public"
4
9
  },
5
- "name": "@khanacademy/kmath",
6
- "version": "0.0.4",
7
- "description": "Khan Academy's Javascript Numeric Math Utilities",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/Khan/kmath.git"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/Khan/perseus/issues"
16
+ },
8
17
  "module": "dist/es/index.js",
9
18
  "main": "dist/index.js",
10
19
  "source": "src/index.js",
@@ -13,12 +22,11 @@
13
22
  },
14
23
  "dependencies": {},
15
24
  "devDependencies": {
16
- "perseus-build-settings": "^0.0.1",
25
+ "perseus-build-settings": "^0.0.3",
17
26
  "underscore": "1.4.4"
18
27
  },
19
28
  "peerDependencies": {
20
29
  "underscore": "1.4.4"
21
30
  },
22
- "author": "Khan Academy",
23
- "license": "MIT"
31
+ "keywords": []
24
32
  }
package/src/line.js CHANGED
@@ -15,10 +15,7 @@ export function distanceToPoint(line: Line, point: Point): number {
15
15
  return kpoint.distanceToLine(point, line);
16
16
  }
17
17
 
18
- export function reflectPoint(
19
- line: Line,
20
- point: Point,
21
- ): $ReadOnlyArray<number> /* TODO: convert to Point */ {
18
+ export function reflectPoint(line: Line, point: Point): Point {
22
19
  return kpoint.reflectOverLine(point, line);
23
20
  }
24
21
 
package/src/logo.js CHANGED
@@ -1,13 +1,15 @@
1
+ /* eslint-disable import/no-default-export */
2
+ // @flow
1
3
  // This file describes the graphie source code of the kmath logo
2
4
  // currently used on khan.github.io.
3
5
  //
4
6
  // Also located at http://ka-perseus-graphie.s3.amazonaws.com/42ef3cbadc3e6464124533191728c3c5c55c7355.svg
5
7
 
6
- // eslint-disable-next-line flowtype/no-types-missing-file-annotation
8
+ // eslint-disable-next-line ft-flow/no-types-missing-file-annotation
7
9
  declare var init: $FlowFixMe;
8
- // eslint-disable-next-line flowtype/no-types-missing-file-annotation
10
+ // eslint-disable-next-line ft-flow/no-types-missing-file-annotation
9
11
  declare var ellipse: $FlowFixMe;
10
- // eslint-disable-next-line flowtype/no-types-missing-file-annotation
12
+ // eslint-disable-next-line ft-flow/no-types-missing-file-annotation
11
13
  declare var line: $FlowFixMe;
12
14
 
13
15
  const GREEN = "#28AE7B";
package/src/point.js CHANGED
@@ -6,14 +6,14 @@
6
6
 
7
7
  import _ from "underscore";
8
8
 
9
- import * as kvector from "./vector.js";
10
9
  import * as knumber from "./number.js";
10
+ import * as kvector from "./vector.js";
11
11
 
12
12
  // A point, in 2D, 3D, or nD space.
13
13
  export type Point = $ReadOnlyArray<number>;
14
14
 
15
15
  // Rotate point (around origin unless a center is specified)
16
- export function rotateRad(point: Point, theta: number, center: Point): Point {
16
+ export function rotateRad(point: Point, theta: number, center?: Point): Point {
17
17
  if (center === undefined) {
18
18
  return kvector.rotateRad(point, theta);
19
19
  } else {
@@ -24,7 +24,7 @@ export function rotateRad(point: Point, theta: number, center: Point): Point {
24
24
  }
25
25
  }
26
26
 
27
- export function rotateDeg(point: Point, theta: number, center: Point): Point {
27
+ export function rotateDeg(point: Point, theta: number, center?: Point): Point {
28
28
  if (center === undefined) {
29
29
  return kvector.rotateDeg(point, theta);
30
30
  } else {
@@ -50,10 +50,7 @@ export function distanceToLine(point: Point, line: [Point, Point]): number {
50
50
  }
51
51
 
52
52
  // Reflect point over line
53
- export function reflectOverLine(
54
- point: Point,
55
- line: [Point, Point],
56
- ): $ReadOnlyArray<number> /* TODO: convert to Point */ {
53
+ export function reflectOverLine<P: Point>(point: P, line: [P, P]): P {
57
54
  const lv = kvector.subtract(line[1], line[0]);
58
55
  const pv = kvector.subtract(point, line[0]);
59
56
  const projectedPv = kvector.projection(pv, lv);
package/src/ray.js CHANGED
@@ -6,14 +6,14 @@
6
6
  * traveling along the positive x-axis.
7
7
  */
8
8
 
9
- import * as kvector from "./vector.js";
10
9
  import * as kpoint from "./point.js";
10
+ import * as kvector from "./vector.js";
11
11
 
12
12
  import type {Point} from "./point";
13
13
 
14
14
  export type Ray = [Point, Point];
15
15
 
16
- export function equal(ray1: Ray, ray2: Ray, tolerance: number): boolean {
16
+ export function equal(ray1: Ray, ray2: Ray, tolerance?: number): boolean {
17
17
  // Compare the directions of the rays
18
18
  const v1 = kvector.subtract(ray1[1], ray1[0]);
19
19
  const v2 = kvector.subtract(ray2[1], ray2[0]);
package/src/vector.js CHANGED
@@ -5,8 +5,11 @@
5
5
  */
6
6
 
7
7
  import _ from "underscore";
8
+
8
9
  import * as knumber from "./number.js";
9
10
 
11
+ type Vector = $ReadOnlyArray<number>;
12
+
10
13
  function arraySum(array: $ReadOnlyArray<number>): number {
11
14
  return array.reduce((memo, arg) => memo + arg, 0);
12
15
  }
@@ -15,7 +18,15 @@ function arrayProduct(array: $ReadOnlyArray<number>): number {
15
18
  return array.reduce((memo, arg) => memo * arg, 1);
16
19
  }
17
20
 
18
- export function is<T>(vec: $ReadOnlyArray<T>, dimension: number): boolean {
21
+ /**
22
+ * Checks if the given vector contains only numbers and, optionally, is of the
23
+ * right dimension (length).
24
+ *
25
+ * is([1, 2, 3]) -> true
26
+ * is([1, "Hello", 3]) -> false
27
+ * is([1, 2, 3], 1) -> false
28
+ */
29
+ export function is<T>(vec: $ReadOnlyArray<T>, dimension?: number): boolean {
19
30
  if (!_.isArray(vec)) {
20
31
  return false;
21
32
  }
@@ -26,19 +37,16 @@ export function is<T>(vec: $ReadOnlyArray<T>, dimension: number): boolean {
26
37
  }
27
38
 
28
39
  // Normalize to a unit vector
29
- export function normalize(v: $ReadOnlyArray<number>): $ReadOnlyArray<number> {
40
+ export function normalize<V: Vector>(v: V): V {
30
41
  return scale(v, 1 / length(v));
31
42
  }
32
43
 
33
44
  // Length/magnitude of a vector
34
- export function length(v: $ReadOnlyArray<number>): number {
45
+ export function length(v: Vector): number {
35
46
  return Math.sqrt(dot(v, v));
36
47
  }
37
48
  // Dot product of two vectors
38
- export function dot(
39
- a: $ReadOnlyArray<number>,
40
- b: $ReadOnlyArray<number>,
41
- ): number {
49
+ export function dot(a: Vector, b: Vector): number {
42
50
  // $FlowFixMe[incompatible-call] underscore doesn't like $ReadOnlyArray
43
51
  const zipped = _.zip(a, b);
44
52
  const multiplied = zipped.map(arrayProduct);
@@ -49,43 +57,33 @@ export function dot(
49
57
  *
50
58
  * add([1, 2], [3, 4]) -> [4, 6]
51
59
  */
52
- export function add(
53
- ...vecs: $ReadOnlyArray<$ReadOnlyArray<number>>
54
- ): $ReadOnlyArray<number> {
60
+ export function add<V: Vector>(...vecs: $ReadOnlyArray<V>): V {
55
61
  // $FlowFixMe[incompatible-call] underscore doesn't like $ReadOnlyArray
56
62
  const zipped = _.zip(...vecs);
57
63
  return zipped.map(arraySum);
58
64
  }
59
65
 
60
- export function subtract(
61
- v1: $ReadOnlyArray<number>,
62
- v2: $ReadOnlyArray<number>,
63
- ): $ReadOnlyArray<number> {
66
+ export function subtract<V: Vector>(v1: V, v2: V): V {
64
67
  // $FlowFixMe[incompatible-call] underscore doesn't like $ReadOnlyArray
65
68
  return _.zip(v1, v2).map((dim) => dim[0] - dim[1]);
66
69
  }
67
70
 
68
- export function negate(v: $ReadOnlyArray<number>): $ReadOnlyArray<number> {
71
+ export function negate<V: Vector>(v: V): V {
72
+ // $FlowFixMe[incompatible-return] Flow's `.map()` libdef is lacking
69
73
  return v.map((x) => {
70
74
  return -x;
71
75
  });
72
76
  }
73
77
 
74
78
  // Scale a vector
75
- export function scale(
76
- v1: $ReadOnlyArray<number>,
77
- scalar: number,
78
- ): $ReadOnlyArray<number> {
79
+ export function scale<V: Vector>(v1: V, scalar: number): V {
80
+ // $FlowFixMe[incompatible-return] Flow's `.map()` libdef is lacking
79
81
  return v1.map((x) => {
80
82
  return x * scalar;
81
83
  });
82
84
  }
83
85
 
84
- export function equal(
85
- v1: $ReadOnlyArray<number>,
86
- v2: $ReadOnlyArray<number>,
87
- tolerance?: number,
88
- ): boolean {
86
+ export function equal(v1: Vector, v2: Vector, tolerance?: number): boolean {
89
87
  // _.zip will nicely deal with the lengths, going through
90
88
  // the length of the longest vector. knumber.equal then
91
89
  // returns false for any number compared to the undefined
@@ -97,8 +95,8 @@ export function equal(
97
95
  }
98
96
 
99
97
  export function codirectional(
100
- v1: $ReadOnlyArray<number>,
101
- v2: $ReadOnlyArray<number>,
98
+ v1: Vector,
99
+ v2: Vector,
102
100
  tolerance?: number,
103
101
  ): boolean {
104
102
  // The origin is trivially codirectional with all other vectors.
@@ -117,17 +115,15 @@ export function codirectional(
117
115
  return equal(v1, v2, tolerance);
118
116
  }
119
117
 
120
- export function collinear(
121
- v1: $ReadOnlyArray<number>,
122
- v2: $ReadOnlyArray<number>,
123
- tolerance?: number,
124
- ): boolean {
118
+ export function collinear(v1: Vector, v2: Vector, tolerance?: number): boolean {
125
119
  return (
126
120
  codirectional(v1, v2, tolerance) ||
127
121
  codirectional(v1, negate(v2), tolerance)
128
122
  );
129
123
  }
130
124
 
125
+ // TODO(jeremy) These coordinate conversion functions really only handle 2D points (ie. [number, number])
126
+
131
127
  // Convert a cartesian coordinate into a radian polar coordinate
132
128
  export function polarRadFromCart(
133
129
  v: $ReadOnlyArray<number>,
@@ -155,7 +151,6 @@ export function polarDegFromCart(
155
151
  *
156
152
  * Examples:
157
153
  * cartFromPolarRad(5, Math.PI)
158
- * cartFromPolarRad([5, Math.PI])
159
154
  */
160
155
  export function cartFromPolarRad(
161
156
  radius: number,
@@ -168,7 +163,6 @@ export function cartFromPolarRad(
168
163
  *
169
164
  * Examples:
170
165
  * cartFromPolarDeg(5, 30)
171
- * cartFromPolarDeg([5, 30])
172
166
  */
173
167
  export function cartFromPolarDeg(
174
168
  radius: number,
@@ -197,34 +191,23 @@ export function rotateDeg(
197
191
  }
198
192
 
199
193
  // Angle between two vectors
200
- export function angleRad(
201
- v1: $ReadOnlyArray<number>,
202
- v2: $ReadOnlyArray<number>,
203
- ): number {
194
+ export function angleRad(v1: Vector, v2: Vector): number {
204
195
  return Math.acos(dot(v1, v2) / (length(v1) * length(v2)));
205
196
  }
206
197
 
207
- export function angleDeg(
208
- v1: $ReadOnlyArray<number>,
209
- v2: $ReadOnlyArray<number>,
210
- ): number {
198
+ export function angleDeg(v1: Vector, v2: Vector): number {
211
199
  return (angleRad(v1, v2) * 180) / Math.PI;
212
200
  }
213
201
 
214
202
  // Vector projection of v1 onto v2
215
- export function projection(
216
- v1: $ReadOnlyArray<number>,
217
- v2: $ReadOnlyArray<number>,
218
- ): $ReadOnlyArray<number> {
203
+ export function projection<V: Vector>(v1: V, v2: V): V {
219
204
  const scalar = dot(v1, v2) / dot(v2, v2);
220
205
  return scale(v2, scalar);
221
206
  }
222
207
 
223
208
  // Round each number to a certain number of decimal places
224
- export function round(
225
- vec: $ReadOnlyArray<number>,
226
- precision: $ReadOnlyArray<number> | number,
227
- ): $ReadOnlyArray<number> {
209
+ export function round<V: Vector>(vec: V, precision: V | number): V {
210
+ // $FlowFixMe[incompatible-return] Flow's `.map()` libdef is lacking
228
211
  return vec.map((elem, i) =>
229
212
  // $FlowFixMe[prop-missing]
230
213
  // $FlowFixMe[incompatible-call]
@@ -233,10 +216,8 @@ export function round(
233
216
  }
234
217
 
235
218
  // Round each number to the nearest increment
236
- export function roundTo(
237
- vec: $ReadOnlyArray<number>,
238
- increment: $ReadOnlyArray<number> | number,
239
- ): $ReadOnlyArray<number> {
219
+ export function roundTo<V: Vector>(vec: V, increment: V | number): V {
220
+ // $FlowFixMe[incompatible-return] Flow's `.map()` libdef is lacking
240
221
  return vec.map((elem, i) =>
241
222
  // $FlowFixMe[prop-missing]
242
223
  // $FlowFixMe[incompatible-call]
@@ -244,10 +225,8 @@ export function roundTo(
244
225
  );
245
226
  }
246
227
 
247
- export function floorTo(
248
- vec: $ReadOnlyArray<number>,
249
- increment: $ReadOnlyArray<number> | number,
250
- ): $ReadOnlyArray<number> {
228
+ export function floorTo<V: Vector>(vec: V, increment: V | number): V {
229
+ // $FlowFixMe[incompatible-return] Flow's `.map()` libdef is lacking
251
230
  return vec.map((elem, i) =>
252
231
  // $FlowFixMe[prop-missing]
253
232
  // $FlowFixMe[incompatible-call]
@@ -255,10 +234,8 @@ export function floorTo(
255
234
  );
256
235
  }
257
236
 
258
- export function ceilTo(
259
- vec: $ReadOnlyArray<number>,
260
- increment: $ReadOnlyArray<number> | number,
261
- ): $ReadOnlyArray<number> {
237
+ export function ceilTo<V: Vector>(vec: V, increment: V | number): V {
238
+ // $FlowFixMe[incompatible-return] Flow's `.map()` libdef is lacking
262
239
  return vec.map((elem, i) =>
263
240
  // $FlowFixMe[prop-missing]
264
241
  // $FlowFixMe[incompatible-call]