@danielsimonjr/mathts-core 0.6.0 → 0.7.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.d.ts +70 -1
- package/dist/index.js +66 -0
- package/package.json +59 -59
package/dist/index.d.ts
CHANGED
|
@@ -2445,6 +2445,75 @@ declare const math: {
|
|
|
2445
2445
|
configure: (config: Partial<MathTSConfig>) => void;
|
|
2446
2446
|
};
|
|
2447
2447
|
|
|
2448
|
+
/**
|
|
2449
|
+
* Numerically stable reduction primitives.
|
|
2450
|
+
*
|
|
2451
|
+
* Floating-point addition is not associative, so *how* you accumulate decides how much error you
|
|
2452
|
+
* carry. These are the algorithms the established numerical stack uses, and the reason it is
|
|
2453
|
+
* trusted.
|
|
2454
|
+
*
|
|
2455
|
+
* Measured on this repo's own reductions before these existed — 1e6 copies of `0.1`, exact answer
|
|
2456
|
+
* 100000:
|
|
2457
|
+
*
|
|
2458
|
+
* | accumulation | relative error |
|
|
2459
|
+
* | ------------------------------- | -------------- |
|
|
2460
|
+
* | naive `s += x` | **1.3e-11** |
|
|
2461
|
+
* | pairwise (this, = NumPy's algo) | **2.9e-16** |
|
|
2462
|
+
* | Neumaier compensated (`fsum`) | **0** (exact) |
|
|
2463
|
+
*
|
|
2464
|
+
* NumPy 2.3.4 reports 2.9e-16 on the same input — we are now at parity. Before this, we were
|
|
2465
|
+
* ~46,000× worse than NumPy on a bog-standard `sum`, and `mean`, `std`, `var` and every statistic
|
|
2466
|
+
* inherit that error.
|
|
2467
|
+
*
|
|
2468
|
+
* @packageDocumentation
|
|
2469
|
+
*/
|
|
2470
|
+
/**
|
|
2471
|
+
* Sum with **pairwise (cascade) summation** — the algorithm behind `np.sum`.
|
|
2472
|
+
*
|
|
2473
|
+
* Naive accumulation lets the running total grow large while the addends stay small, so each
|
|
2474
|
+
* addition rounds off a little more of the total: error grows as **O(n)·ε**. Pairwise summation
|
|
2475
|
+
* adds numbers of *comparable magnitude* by recursively halving the range, so error grows as
|
|
2476
|
+
* **O(log n)·ε** — for n = 10⁶ that is the difference between ~1e-11 and ~1e-16.
|
|
2477
|
+
*
|
|
2478
|
+
* It costs the same number of additions as the naive loop. There is no speed/accuracy trade here;
|
|
2479
|
+
* the naive version is simply worse.
|
|
2480
|
+
*
|
|
2481
|
+
* Not exact: for that, use {@link neumaierSum}. Pairwise is the right default because it is free.
|
|
2482
|
+
*/
|
|
2483
|
+
declare function pairwiseSum(xs: ArrayLike<number>, start?: number, end?: number): number;
|
|
2484
|
+
/**
|
|
2485
|
+
* Sum with **Neumaier compensation** — correctly rounded for practical purposes, the equivalent
|
|
2486
|
+
* of Python's `math.fsum`.
|
|
2487
|
+
*
|
|
2488
|
+
* Tracks the low-order bits that each addition throws away and folds them back in at the end. It
|
|
2489
|
+
* recovers information that pairwise summation cannot: `[1e16, 1, -1e16]` sums to **1** here,
|
|
2490
|
+
* while both naive and pairwise (and `np.sum`) give **0**, because the `1` is annihilated the
|
|
2491
|
+
* moment it meets `1e16`.
|
|
2492
|
+
*
|
|
2493
|
+
* ~2-4× slower than {@link pairwiseSum}, so it is opt-in rather than the default. Reach for it
|
|
2494
|
+
* when catastrophic cancellation is possible: near-zero results from large terms, long-running
|
|
2495
|
+
* accumulators, conservation checks.
|
|
2496
|
+
*
|
|
2497
|
+
* (Neumaier's variant, not classic Kahan: Kahan loses the compensation when the *addend* is
|
|
2498
|
+
* larger than the running sum, which is precisely the `1e16` case.)
|
|
2499
|
+
*/
|
|
2500
|
+
declare function neumaierSum(xs: ArrayLike<number>): number;
|
|
2501
|
+
/**
|
|
2502
|
+
* Euclidean (2-)norm that does **not** overflow or underflow — BLAS's `dnrm2` scaling.
|
|
2503
|
+
*
|
|
2504
|
+
* The obvious `sqrt(Σxᵢ²)` squares before it adds, so it dies well inside the representable
|
|
2505
|
+
* range: `‖[1e200, 1e200, 1e200, 1e200]‖` overflows to `Infinity` (the true answer, 2e200, is
|
|
2506
|
+
* perfectly representable), and `‖[1e-200] × 4‖` **flushes to 0** — a silent wrong answer, which
|
|
2507
|
+
* is worse.
|
|
2508
|
+
*
|
|
2509
|
+
* NumPy has this bug too: `np.linalg.norm([1e200]*4)` returns `inf` with an overflow warning.
|
|
2510
|
+
* LAPACK does not, and neither do we.
|
|
2511
|
+
*
|
|
2512
|
+
* The fix is to carry a running scale: keep the largest magnitude seen out of the sum of squares,
|
|
2513
|
+
* so the accumulator only ever holds ratios in [0, 1].
|
|
2514
|
+
*/
|
|
2515
|
+
declare function norm2(xs: ArrayLike<number>): number;
|
|
2516
|
+
|
|
2448
2517
|
/**
|
|
2449
2518
|
* @danielsimonjr/mathts-core - Core types and utilities for MathTS
|
|
2450
2519
|
* @packageDocumentation
|
|
@@ -2452,4 +2521,4 @@ declare const math: {
|
|
|
2452
2521
|
|
|
2453
2522
|
declare const VERSION = "0.1.0";
|
|
2454
2523
|
|
|
2455
|
-
export { ALL_UNITS, BASE_UNITS, BEST_PREFIXES, BIGNUMBER_E, BIGNUMBER_LN10, BIGNUMBER_LN2, BIGNUMBER_NEG_ONE, BIGNUMBER_ONE, BIGNUMBER_PI, BIGNUMBER_TEN, BIGNUMBER_ZERO, type BackendType, BigNumber, type BigNumberConfig, COMPLEX_NEG_ONE, COMPLEX_ONE, COMPLEX_ZERO, Complex, type ConversionDef, DEFAULT_CONFIG, DERIVED_UNITS, DIMENSIONLESS, DUAL_UNARY_RULES, DimensionMismatchError, type Dimensions, Dual, type DualUnaryRule, type DualUnaryRuleName, E, FRACTION_HALF, FRACTION_NEG_ONE, FRACTION_ONE, FRACTION_QUARTER, FRACTION_THIRD, FRACTION_ZERO, type FactoryDependencies, type FactoryFunction, type FactoryImport, Fraction, FunctionRegistry, I, type IBigNumber, type IComplex, type IFraction, type IMatrix, LN10, LN2, LOG10E, LOG2E, MATHTS_CONVERSIONS, MATHTS_TYPES, type MathTSConfig, type MathTSValue, type MatrixBackend, type MatrixDimensions, type NumericScalar, type NumericType, PHI, PI, Range, type RangeForEachCallback, type RangeFormatOptions, type RangeJSON, type RangeMapCallback, type RoundingMode, SI_PREFIXES, SQRT1_2, SQRT2, type Scalar, TAU, type TypeDef, TypeRegistry, UNIT_ALIASES, type UnitDef, UnitParseError, VERSION, abs, addScalar, createFactory, createMathTSTyped, createRangeClass, createTypedFunction, dim, divideScalar, equal, fix, getPrefix, getUnitDef, initTypedWasm, isArray, isBigInt, isBigNumber, isBoolean, isComplex, isDenseMatrix, isDual, isFraction, isFunction, isMatrix, isNull, isNumber, isNumeric, isObject, isSparseMatrix, isString, isTypedWasmAvailable, isUndefined, isUnit, math, mathTyped, multiplyScalar, number, pow, registerNativeTypes, registry, round, subtractScalar };
|
|
2524
|
+
export { ALL_UNITS, BASE_UNITS, BEST_PREFIXES, BIGNUMBER_E, BIGNUMBER_LN10, BIGNUMBER_LN2, BIGNUMBER_NEG_ONE, BIGNUMBER_ONE, BIGNUMBER_PI, BIGNUMBER_TEN, BIGNUMBER_ZERO, type BackendType, BigNumber, type BigNumberConfig, COMPLEX_NEG_ONE, COMPLEX_ONE, COMPLEX_ZERO, Complex, type ConversionDef, DEFAULT_CONFIG, DERIVED_UNITS, DIMENSIONLESS, DUAL_UNARY_RULES, DimensionMismatchError, type Dimensions, Dual, type DualUnaryRule, type DualUnaryRuleName, E, FRACTION_HALF, FRACTION_NEG_ONE, FRACTION_ONE, FRACTION_QUARTER, FRACTION_THIRD, FRACTION_ZERO, type FactoryDependencies, type FactoryFunction, type FactoryImport, Fraction, FunctionRegistry, I, type IBigNumber, type IComplex, type IFraction, type IMatrix, LN10, LN2, LOG10E, LOG2E, MATHTS_CONVERSIONS, MATHTS_TYPES, type MathTSConfig, type MathTSValue, type MatrixBackend, type MatrixDimensions, type NumericScalar, type NumericType, PHI, PI, Range, type RangeForEachCallback, type RangeFormatOptions, type RangeJSON, type RangeMapCallback, type RoundingMode, SI_PREFIXES, SQRT1_2, SQRT2, type Scalar, TAU, type TypeDef, TypeRegistry, UNIT_ALIASES, type UnitDef, UnitParseError, VERSION, abs, addScalar, createFactory, createMathTSTyped, createRangeClass, createTypedFunction, dim, divideScalar, equal, fix, getPrefix, getUnitDef, initTypedWasm, isArray, isBigInt, isBigNumber, isBoolean, isComplex, isDenseMatrix, isDual, isFraction, isFunction, isMatrix, isNull, isNumber, isNumeric, isObject, isSparseMatrix, isString, isTypedWasmAvailable, isUndefined, isUnit, math, mathTyped, multiplyScalar, neumaierSum, norm2, number, pairwiseSum, pow, registerNativeTypes, registry, round, subtractScalar };
|
package/dist/index.js
CHANGED
|
@@ -1186,6 +1186,69 @@ var math = {
|
|
|
1186
1186
|
configure: (config) => registry.updateConfig(config)
|
|
1187
1187
|
};
|
|
1188
1188
|
|
|
1189
|
+
// src/numeric/stable.ts
|
|
1190
|
+
var PAIRWISE_BLOCK = 128;
|
|
1191
|
+
function pairwiseSum(xs, start = 0, end = xs.length) {
|
|
1192
|
+
const n = end - start;
|
|
1193
|
+
if (n <= PAIRWISE_BLOCK) {
|
|
1194
|
+
let s0 = 0;
|
|
1195
|
+
let s1 = 0;
|
|
1196
|
+
let s2 = 0;
|
|
1197
|
+
let s3 = 0;
|
|
1198
|
+
let s4 = 0;
|
|
1199
|
+
let s5 = 0;
|
|
1200
|
+
let s6 = 0;
|
|
1201
|
+
let s7 = 0;
|
|
1202
|
+
let i = start;
|
|
1203
|
+
const limit = start + (n - n % 8);
|
|
1204
|
+
for (; i < limit; i += 8) {
|
|
1205
|
+
s0 += xs[i];
|
|
1206
|
+
s1 += xs[i + 1];
|
|
1207
|
+
s2 += xs[i + 2];
|
|
1208
|
+
s3 += xs[i + 3];
|
|
1209
|
+
s4 += xs[i + 4];
|
|
1210
|
+
s5 += xs[i + 5];
|
|
1211
|
+
s6 += xs[i + 6];
|
|
1212
|
+
s7 += xs[i + 7];
|
|
1213
|
+
}
|
|
1214
|
+
let tail = 0;
|
|
1215
|
+
for (; i < end; i++) tail += xs[i];
|
|
1216
|
+
return s0 + s1 + (s2 + s3) + (s4 + s5 + (s6 + s7)) + tail;
|
|
1217
|
+
}
|
|
1218
|
+
const half = (n >> 1) - (n >> 1) % 8;
|
|
1219
|
+
return pairwiseSum(xs, start, start + half) + pairwiseSum(xs, start + half, end);
|
|
1220
|
+
}
|
|
1221
|
+
function neumaierSum(xs) {
|
|
1222
|
+
let sum = 0;
|
|
1223
|
+
let c = 0;
|
|
1224
|
+
for (let i = 0; i < xs.length; i++) {
|
|
1225
|
+
const x = xs[i];
|
|
1226
|
+
const t = sum + x;
|
|
1227
|
+
c += Math.abs(sum) >= Math.abs(x) ? sum - t + x : x - t + sum;
|
|
1228
|
+
sum = t;
|
|
1229
|
+
}
|
|
1230
|
+
return sum + c;
|
|
1231
|
+
}
|
|
1232
|
+
function norm2(xs) {
|
|
1233
|
+
let scale = 0;
|
|
1234
|
+
let ssq = 1;
|
|
1235
|
+
for (let i = 0; i < xs.length; i++) {
|
|
1236
|
+
const x = xs[i];
|
|
1237
|
+
if (x === 0) continue;
|
|
1238
|
+
if (Number.isNaN(x)) return NaN;
|
|
1239
|
+
const ax = Math.abs(x);
|
|
1240
|
+
if (scale < ax) {
|
|
1241
|
+
const r = scale / ax;
|
|
1242
|
+
ssq = 1 + ssq * r * r;
|
|
1243
|
+
scale = ax;
|
|
1244
|
+
} else {
|
|
1245
|
+
const r = ax / scale;
|
|
1246
|
+
ssq += r * r;
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
return scale === 0 ? 0 : scale * Math.sqrt(ssq);
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1189
1252
|
// src/index.ts
|
|
1190
1253
|
var VERSION = "0.1.0";
|
|
1191
1254
|
export {
|
|
@@ -1276,7 +1339,10 @@ export {
|
|
|
1276
1339
|
math,
|
|
1277
1340
|
mathTyped,
|
|
1278
1341
|
multiplyScalar,
|
|
1342
|
+
neumaierSum,
|
|
1343
|
+
norm2,
|
|
1279
1344
|
number,
|
|
1345
|
+
pairwiseSum,
|
|
1280
1346
|
pow,
|
|
1281
1347
|
registerNativeTypes,
|
|
1282
1348
|
registry,
|
package/package.json
CHANGED
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@danielsimonjr/mathts-core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Core types, utilities, and configuration for MathTS",
|
|
5
|
-
"author": "Daniel Simon Jr.",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"type": "module",
|
|
8
|
-
"main": "./dist/index.js",
|
|
9
|
-
"module": "./dist/index.js",
|
|
10
|
-
"types": "./dist/index.d.ts",
|
|
11
|
-
"exports": {
|
|
12
|
-
".": {
|
|
13
|
-
"import": "./dist/index.js",
|
|
14
|
-
"types": "./dist/index.d.ts"
|
|
15
|
-
},
|
|
16
|
-
"./internal": {
|
|
17
|
-
"import": "./dist/internal.js",
|
|
18
|
-
"types": "./dist/internal.d.ts"
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
"files": [
|
|
22
|
-
"dist",
|
|
23
|
-
"README.md"
|
|
24
|
-
],
|
|
25
|
-
"scripts": {
|
|
26
|
-
"build": "tsup src/index.ts src/internal.ts --format esm --dts --clean",
|
|
27
|
-
"dev": "tsup src/index.ts src/internal.ts --format esm --dts --watch",
|
|
28
|
-
"test": "vitest run",
|
|
29
|
-
"test:watch": "vitest",
|
|
30
|
-
"test:coverage": "vitest run --coverage",
|
|
31
|
-
"typecheck": "tsc --noEmit",
|
|
32
|
-
"lint": "eslint src --ext .ts",
|
|
33
|
-
"lint:fix": "eslint src --ext .ts --fix",
|
|
34
|
-
"clean": "rm -rf dist",
|
|
35
|
-
"build:prod": "tsup src/index.ts --format esm --dts --clean --minify --treeshake"
|
|
36
|
-
},
|
|
37
|
-
"dependencies": {
|
|
38
|
-
"typed-function": "github:danielsimonjr/typed-function"
|
|
39
|
-
},
|
|
40
|
-
"devDependencies": {
|
|
41
|
-
"@types/node": "^25.5.2",
|
|
42
|
-
"tsup": "^8.0.0",
|
|
43
|
-
"typescript": "^5.3.0",
|
|
44
|
-
"vitest": "^4.1.5"
|
|
45
|
-
},
|
|
46
|
-
"publishConfig": {
|
|
47
|
-
"access": "public"
|
|
48
|
-
},
|
|
49
|
-
"repository": {
|
|
50
|
-
"type": "git",
|
|
51
|
-
"url": "https://github.com/danielsimonjr/mathts",
|
|
52
|
-
"directory": "core"
|
|
53
|
-
},
|
|
54
|
-
"keywords": [
|
|
55
|
-
"math",
|
|
56
|
-
"typescript",
|
|
57
|
-
"core"
|
|
58
|
-
]
|
|
59
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@danielsimonjr/mathts-core",
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"description": "Core types, utilities, and configuration for MathTS",
|
|
5
|
+
"author": "Daniel Simon Jr.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts"
|
|
15
|
+
},
|
|
16
|
+
"./internal": {
|
|
17
|
+
"import": "./dist/internal.js",
|
|
18
|
+
"types": "./dist/internal.d.ts"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsup src/index.ts src/internal.ts --format esm --dts --clean",
|
|
27
|
+
"dev": "tsup src/index.ts src/internal.ts --format esm --dts --watch",
|
|
28
|
+
"test": "vitest run",
|
|
29
|
+
"test:watch": "vitest",
|
|
30
|
+
"test:coverage": "vitest run --coverage",
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
32
|
+
"lint": "eslint src --ext .ts",
|
|
33
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
34
|
+
"clean": "rm -rf dist",
|
|
35
|
+
"build:prod": "tsup src/index.ts --format esm --dts --clean --minify --treeshake"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"typed-function": "github:danielsimonjr/typed-function"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^25.5.2",
|
|
42
|
+
"tsup": "^8.0.0",
|
|
43
|
+
"typescript": "^5.3.0",
|
|
44
|
+
"vitest": "^4.1.5"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "https://github.com/danielsimonjr/mathts",
|
|
52
|
+
"directory": "core"
|
|
53
|
+
},
|
|
54
|
+
"keywords": [
|
|
55
|
+
"math",
|
|
56
|
+
"typescript",
|
|
57
|
+
"core"
|
|
58
|
+
]
|
|
59
|
+
}
|