math-utils-simple 3.0.0 → 4.0.1

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,7 +1,7 @@
1
1
  {
2
2
  "name": "math-utils-simple",
3
- "version": "3.0.0",
4
- "description": "A simple math utility library for npm",
3
+ "version": "4.0.1",
4
+ "description": "Math utility library for npm",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
7
7
  "exports": {
@@ -16,6 +16,14 @@
16
16
  "npm",
17
17
  "library"
18
18
  ],
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/umar-farooq-5757/math-utils-simple.git"
22
+ },
23
+ "bugs": {
24
+ "url": "https://github.com/umar-farooq-5757/math-utils-simple/issues"
25
+ },
26
+ "homepage": "https://github.com/umar-farooq-5757/math-utils-simple#readme",
19
27
  "author": "Umar Farooq",
20
28
  "license": "MIT"
21
29
  }
@@ -0,0 +1,9 @@
1
+ import cosineSimilarity from "./cosineSimilarity.js";
2
+
3
+ export default function angleBetweenVectors(a, b) {
4
+ const cosine = cosineSimilarity(a, b);
5
+
6
+ return Math.acos(
7
+ Math.min(1, Math.max(-1, cosine))
8
+ );
9
+ }
@@ -0,0 +1,13 @@
1
+ import dotProduct from "./dotProduct.js";
2
+ import vectorMagnitude from "./vectorMagnitude.js";
3
+
4
+ export default function cosineSimilarity(a, b) {
5
+ const magA = vectorMagnitude(a);
6
+ const magB = vectorMagnitude(b);
7
+
8
+ if (magA === 0 || magB === 0) {
9
+ throw new Error("Cannot calculate similarity for a zero vector.");
10
+ }
11
+
12
+ return dotProduct(a, b) / (magA * magB);
13
+ }
@@ -0,0 +1,15 @@
1
+ export default function crossProduct(a, b) {
2
+ if (!Array.isArray(a) || !Array.isArray(b)) {
3
+ throw new TypeError("Expected two arrays.");
4
+ }
5
+
6
+ if (a.length !== 3 || b.length !== 3) {
7
+ throw new Error("Cross product requires two 3-dimensional vectors.");
8
+ }
9
+
10
+ return [
11
+ a[1] * b[2] - a[2] * b[1],
12
+ a[2] * b[0] - a[0] * b[2],
13
+ a[0] * b[1] - a[1] * b[0],
14
+ ];
15
+ }
@@ -0,0 +1,15 @@
1
+ export default function cumulativeSum(array) {
2
+ if (!Array.isArray(array)) {
3
+ throw new TypeError("Expected an array.");
4
+ }
5
+
6
+ const result = [];
7
+ let sum = 0;
8
+
9
+ for (const value of array) {
10
+ sum += value;
11
+ result.push(sum);
12
+ }
13
+
14
+ return result;
15
+ }
@@ -0,0 +1,17 @@
1
+ export default function dotProduct(a, b) {
2
+ if (!Array.isArray(a) || !Array.isArray(b)) {
3
+ throw new TypeError("Expected two arrays.");
4
+ }
5
+
6
+ if (a.length !== b.length) {
7
+ throw new Error("Arrays must have the same length.");
8
+ }
9
+
10
+ let result = 0;
11
+
12
+ for (let i = 0; i < a.length; i++) {
13
+ result += a[i] * b[i];
14
+ }
15
+
16
+ return result;
17
+ }
@@ -0,0 +1,11 @@
1
+ export default function elementWiseAdd(a, b) {
2
+ if (!Array.isArray(a) || !Array.isArray(b)) {
3
+ throw new TypeError("Expected two arrays.");
4
+ }
5
+
6
+ if (a.length !== b.length) {
7
+ throw new Error("Arrays must have the same length.");
8
+ }
9
+
10
+ return a.map((value, index) => value + b[index]);
11
+ }
@@ -0,0 +1,13 @@
1
+ export default function elementWiseDivide(a, b) {
2
+ if (a.length !== b.length) {
3
+ throw new Error("Arrays must have the same length.");
4
+ }
5
+
6
+ return a.map((value, index) => {
7
+ if (b[index] === 0) {
8
+ throw new Error("Division by zero.");
9
+ }
10
+
11
+ return value / b[index];
12
+ });
13
+ }
@@ -0,0 +1,11 @@
1
+ export default function elementWiseMultiply(a, b) {
2
+ if (!Array.isArray(a) || !Array.isArray(b)) {
3
+ throw new TypeError("Expected two arrays.");
4
+ }
5
+
6
+ if (a.length !== b.length) {
7
+ throw new Error("Arrays must have the same length.");
8
+ }
9
+
10
+ return a.map((value, index) => value * b[index]);
11
+ }
@@ -0,0 +1,7 @@
1
+ export default function elementWiseSubtract(a, b) {
2
+ if (a.length !== b.length) {
3
+ throw new Error("Arrays must have the same length.");
4
+ }
5
+
6
+ return a.map((value, index) => value - b[index]);
7
+ }
@@ -0,0 +1,26 @@
1
+ export default function matrixMultiply(a, b) {
2
+ const rowsA = a.length;
3
+ const colsA = a[0].length;
4
+
5
+ const rowsB = b.length;
6
+ const colsB = b[0].length;
7
+
8
+ if (colsA !== rowsB) {
9
+ throw new Error("Matrix dimensions are incompatible.");
10
+ }
11
+
12
+ const result = Array.from(
13
+ { length: rowsA },
14
+ () => Array(colsB).fill(0)
15
+ );
16
+
17
+ for (let i = 0; i < rowsA; i++) {
18
+ for (let j = 0; j < colsB; j++) {
19
+ for (let k = 0; k < colsA; k++) {
20
+ result[i][j] += a[i][k] * b[k][j];
21
+ }
22
+ }
23
+ }
24
+
25
+ return result;
26
+ }
@@ -0,0 +1,23 @@
1
+ export default function movingAverage(array, window) {
2
+ if (!Array.isArray(array)) {
3
+ throw new TypeError("Expected an array.");
4
+ }
5
+
6
+ if (window <= 0 || window > array.length) {
7
+ throw new Error("Invalid window size.");
8
+ }
9
+
10
+ const result = [];
11
+
12
+ for (let i = 0; i <= array.length - window; i++) {
13
+ let sum = 0;
14
+
15
+ for (let j = 0; j < window; j++) {
16
+ sum += array[i + j];
17
+ }
18
+
19
+ result.push(sum / window);
20
+ }
21
+
22
+ return result;
23
+ }
@@ -0,0 +1,15 @@
1
+ export default function normalize(array) {
2
+ if (!Array.isArray(array)) {
3
+ throw new TypeError("Expected an array.");
4
+ }
5
+
6
+ const magnitude = Math.sqrt(
7
+ array.reduce((sum, value) => sum + value * value, 0)
8
+ );
9
+
10
+ if (magnitude === 0) {
11
+ throw new Error("Cannot normalize a zero vector.");
12
+ }
13
+
14
+ return array.map(value => value / magnitude);
15
+ }
@@ -0,0 +1,13 @@
1
+ import dotProduct from "./dotProduct.js";
2
+
3
+ export default function projectVector(a, b) {
4
+ const denominator = dotProduct(b, b);
5
+
6
+ if (denominator === 0) {
7
+ throw new Error("Cannot project onto a zero vector.");
8
+ }
9
+
10
+ const scalar = dotProduct(a, b) / denominator;
11
+
12
+ return b.map(value => scalar * value);
13
+ }
@@ -0,0 +1,7 @@
1
+ export default function scalarDivide(array, scalar) {
2
+ if (scalar === 0) {
3
+ throw new Error("Division by zero.");
4
+ }
5
+
6
+ return array.map(value => value / scalar);
7
+ }
@@ -0,0 +1,3 @@
1
+ export default function scalarMultiply(array, scalar) {
2
+ return array.map(value => value * scalar);
3
+ }
@@ -0,0 +1,20 @@
1
+ export default function transpose(matrix) {
2
+ if (matrix.length === 0) {
3
+ return [];
4
+ }
5
+
6
+ const rows = matrix.length;
7
+ const cols = matrix[0].length;
8
+
9
+ const result = [];
10
+
11
+ for (let col = 0; col < cols; col++) {
12
+ result[col] = [];
13
+
14
+ for (let row = 0; row < rows; row++) {
15
+ result[col][row] = matrix[row][col];
16
+ }
17
+ }
18
+
19
+ return result;
20
+ }
@@ -0,0 +1,11 @@
1
+ import vectorMagnitude from "./vectorMagnitude.js";
2
+
3
+ export default function vectorDistance(a, b) {
4
+ if (a.length !== b.length) {
5
+ throw new Error("Vectors must have the same length.");
6
+ }
7
+
8
+ const difference = a.map((value, index) => value - b[index]);
9
+
10
+ return vectorMagnitude(difference);
11
+ }
@@ -0,0 +1,5 @@
1
+ export default function vectorMagnitude(array) {
2
+ return Math.sqrt(
3
+ array.reduce((sum, value) => sum + value * value, 0)
4
+ );
5
+ }
package/src/index.js CHANGED
@@ -84,4 +84,45 @@ export { default as min } from "./statistics/min.js";
84
84
  export { default as count } from "./statistics/count.js";
85
85
  export { default as frequency } from "./statistics/frequency.js";
86
86
  export { default as quartiles } from "./statistics/quartiles.js";
87
- export { default as interQuartileRange } from "./statistics/interQuartileRange.js";
87
+ export { default as interQuartileRange } from "./statistics/interQuartileRange.js";
88
+
89
+ // ARRAYS
90
+ export { default as dotProduct } from "./arrays/dotProduct.js";
91
+ export { default as crossProduct } from "./arrays/crossProduct.js";
92
+ export { default as elementWiseAdd } from "./arrays/elementWiseAdd.js";
93
+ export { default as elementWiseSubtract } from "./arrays/elementWiseSubtract.js";
94
+ export { default as elementWiseMultiply } from "./arrays/elementWiseMultiply.js";
95
+ export { default as elementWiseDivide } from "./arrays/elementWiseDivide.js";
96
+ export { default as scalarMultiply } from "./arrays/scalarMultiply.js";
97
+ export { default as scalarDivide } from "./arrays/scalarDivide.js";
98
+ export { default as normalizeVector } from "./arrays/normalizeVector.js";
99
+ export { default as vectorMagnitude } from "./arrays/vectorMagnitude.js";
100
+ export { default as vectorDistance } from "./arrays/vectorDistance.js";
101
+ export { default as cosineSimilarity } from "./arrays/cosineSimilarity.js";
102
+ export { default as angleBetweenVectors } from "./arrays/angleBetweenVectors.js";
103
+ export { default as projectVector } from "./arrays/projectVector.js";
104
+ export { default as cumulativeSum } from "./arrays/cumulativeSum.js";
105
+ export { default as movingAverage } from "./arrays/movingAverage.js";
106
+ export { default as transpose } from "./arrays/transpose.js";
107
+ export { default as matrixMultiply } from "./arrays/matrixMultiply.js";
108
+
109
+ // RANDOM
110
+ export { default as random } from "./random/random.js";
111
+ export { default as randomInt } from "./random/randomInt.js";
112
+ export { default as randomFloat } from "./random/randomFloat.js";
113
+ export { default as randomBoolean } from "./random/randomBoolean.js";
114
+ export { default as randomChoice } from "./random/randomChoice.js";
115
+ export { default as shuffle } from "./random/shuffle.js";
116
+ export { default as sample } from "./random/sample.js";
117
+ /**
118
+ * future goals
119
+ * randomSign() → returns -1 or 1
120
+ randomHexColor()
121
+ randomRGB()
122
+ randomUUID() (using crypto.randomUUID())
123
+ randomString(length, charset)
124
+ randomDate(start, end)
125
+ weightedChoice(items, weights)
126
+ randomGaussian(mean, stdDev) (normal distribution via the Box–Muller transform)
127
+ randomSeed(seed) (seeded pseudo-random number generator)
128
+ */
@@ -0,0 +1,3 @@
1
+ export default function random() {
2
+ return Math.random();
3
+ }
@@ -0,0 +1,3 @@
1
+ export default function randomBoolean() {
2
+ return Math.random() < 0.5;
3
+ }
@@ -0,0 +1,11 @@
1
+ export default function randomChoice(array) {
2
+ if (!Array.isArray(array)) {
3
+ throw new TypeError("Expected an array.");
4
+ }
5
+
6
+ if (array.length === 0) {
7
+ throw new Error("Cannot choose from an empty array.");
8
+ }
9
+
10
+ return array[Math.floor(Math.random() * array.length)];
11
+ }
@@ -0,0 +1,11 @@
1
+ export default function randomFloat(min, max) {
2
+ if (typeof min !== "number" || typeof max !== "number") {
3
+ throw new TypeError("Expected numeric bounds.");
4
+ }
5
+
6
+ if (min > max) {
7
+ throw new Error("Minimum cannot be greater than maximum.");
8
+ }
9
+
10
+ return Math.random() * (max - min) + min;
11
+ }
@@ -0,0 +1,11 @@
1
+ export default function randomInt(min, max) {
2
+ if (!Number.isInteger(min) || !Number.isInteger(max)) {
3
+ throw new TypeError("Expected integer bounds.");
4
+ }
5
+
6
+ if (min > max) {
7
+ throw new Error("Minimum cannot be greater than maximum.");
8
+ }
9
+
10
+ return Math.floor(Math.random() * (max - min + 1)) + min;
11
+ }
@@ -0,0 +1,17 @@
1
+ import shuffle from "./shuffle.js";
2
+
3
+ export default function sample(array, count) {
4
+ if (!Array.isArray(array)) {
5
+ throw new TypeError("Expected an array.");
6
+ }
7
+
8
+ if (!Number.isInteger(count) || count < 0) {
9
+ throw new Error("Count must be a non-negative integer.");
10
+ }
11
+
12
+ if (count > array.length) {
13
+ throw new Error("Count cannot exceed array length.");
14
+ }
15
+
16
+ return shuffle(array).slice(0, count);
17
+ }
@@ -0,0 +1,15 @@
1
+ export default function shuffle(array) {
2
+ if (!Array.isArray(array)) {
3
+ throw new TypeError("Expected an array.");
4
+ }
5
+
6
+ const result = [...array];
7
+
8
+ for (let i = result.length - 1; i > 0; i--) {
9
+ const j = Math.floor(Math.random() * (i + 1));
10
+
11
+ [result[i], result[j]] = [result[j], result[i]];
12
+ }
13
+
14
+ return result;
15
+ }