@woosh/meep-engine 2.134.5 → 2.135.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/build/bundle-worker-image-decoder.js +1 -1
- package/build/bundle-worker-terrain.js +1 -1
- package/editor/tools/v2/TransformControlsGizmo.js +1 -1
- package/editor/view/node-graph/NodeGraphEditorView.js +2 -2
- package/package.json +1 -1
- package/src/core/assert.d.ts +0 -2
- package/src/core/assert.d.ts.map +1 -1
- package/src/core/assert.js +0 -6
- package/src/core/color/Color.d.ts +0 -5
- package/src/core/color/Color.d.ts.map +1 -1
- package/src/core/color/Color.js +1 -7
- package/src/core/geom/2d/hash-grid/SpatialHashGrid.js +386 -386
- package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_2d.js +1 -1
- package/src/core/geom/2d/quad-tree-binary/QuadTree.js +714 -714
- package/src/core/geom/3d/triangle/computeTriangleRayIntersection.js +160 -160
- package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentric.js +96 -96
- package/src/core/geom/packing/max-rect/MaxRectanglesPacker.js +1 -1
- package/src/core/geom/packing/max-rect/findBestContainer.js +4 -4
- package/src/core/geom/packing/max-rect/packOneBox.js +2 -2
- package/src/core/geom/vec3/v3_rigid_align_paired_unit_vectors.js +1 -1
- package/src/core/graph/layout/box/BoxLayouter.js +7 -7
- package/src/core/graph/layout/box/position_box_next_to_box.js +6 -6
- package/src/core/math/computeWholeDivisorLow.js +33 -33
- package/src/core/math/linalg/eigen/eigen_values_find_spectral_gap.d.ts.map +1 -0
- package/src/core/math/linalg/eigen/matrix_eigenvalues_in_place.d.ts +10 -0
- package/src/core/math/linalg/eigen/matrix_eigenvalues_in_place.d.ts.map +1 -0
- package/src/core/{graph → math/linalg}/eigen/matrix_eigenvalues_in_place.js +8 -7
- package/src/core/math/linalg/eigen/matrix_householder_in_place.d.ts.map +1 -0
- package/src/core/{graph → math/linalg}/eigen/matrix_householder_in_place.js +11 -5
- package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts +15 -0
- package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts.map +1 -0
- package/src/core/{graph → math/linalg}/eigen/matrix_qr_in_place.js +8 -2
- package/src/core/{graph → math/linalg}/eigen/matrix_top_eigenvector_power_iteration.d.ts +0 -3
- package/src/core/math/linalg/eigen/matrix_top_eigenvector_power_iteration.d.ts.map +1 -0
- package/src/core/{graph → math/linalg}/eigen/matrix_top_eigenvector_power_iteration.js +0 -3
- package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.d.ts +19 -0
- package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.d.ts.map +1 -0
- package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.js +161 -0
- package/src/core/math/linalg/polynomial_real_roots_in_interval.d.ts +15 -0
- package/src/core/math/linalg/polynomial_real_roots_in_interval.d.ts.map +1 -0
- package/src/core/math/linalg/polynomial_real_roots_in_interval.js +200 -0
- package/src/core/math/solveCubic.d.ts +15 -0
- package/src/core/math/solveCubic.d.ts.map +1 -0
- package/src/core/math/solveCubic.js +82 -0
- package/src/core/math/spline/spline3_hermite_bounds_t.d.ts +23 -0
- package/src/core/math/spline/spline3_hermite_bounds_t.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_bounds_t.js +109 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite.d.ts +25 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite.js +44 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.d.ts +16 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.js +120 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.d.ts +11 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.js +451 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.d.ts +12 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.js +339 -0
- package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.d.ts +15 -0
- package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.js +21 -0
- package/src/core/math/spline/spline3_hermite_to_monomial.d.ts +24 -0
- package/src/core/math/spline/spline3_hermite_to_monomial.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_to_monomial.js +37 -0
- package/src/core/math/spline/v3_computeCatmullRomSplineUniformDistance.js +1 -1
- package/src/core/model/node-graph/visual/NodeGraphVisualData.js +1 -1
- package/src/core/model/reactive/model/util/createRandomReactiveExpression.js +185 -185
- package/src/core/process/delay.js +16 -16
- package/src/engine/animation/async/TimeSeries.js +300 -300
- package/src/engine/animation/curve/AnimationCurve.d.ts +0 -4
- package/src/engine/animation/curve/AnimationCurve.d.ts.map +1 -1
- package/src/engine/animation/curve/AnimationCurve.js +1 -6
- package/src/engine/animation/curve/draw/position_canvas_to_curve.js +2 -2
- package/src/engine/animation/curve/draw/position_curve_to_canvas.js +2 -2
- package/src/engine/ecs/fow/shader/FogOfWarRenderer.js +145 -145
- package/src/engine/ecs/gui/position/ViewportPositionSystem.js +2 -2
- package/src/engine/ecs/parent/entity_node_compute_bounding_box.js +1 -1
- package/src/engine/ecs/transform/Transform.d.ts +0 -10
- package/src/engine/ecs/transform/Transform.d.ts.map +1 -1
- package/src/engine/ecs/transform/Transform.js +0 -12
- package/src/engine/graphics/composit/CompositLayer.js +254 -254
- package/src/engine/graphics/ecs/mesh-v2/sg_hierarchy_compute_bounding_box_via_parent_entity.js +1 -1
- package/src/engine/graphics/ecs/path/tube/build/build_geometry_linear.js +2 -2
- package/src/engine/graphics/material/optimization/MaterialOptimizationContext.js +3 -3
- package/src/engine/graphics/particles/particular/engine/utils/volume/AttributeValue.js +201 -201
- package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +1 -1
- package/src/engine/graphics/render/buffer/slot/parameter/ProgramValueSlotParameterSet.js +2 -2
- package/src/engine/graphics/render/forward_plus/LightManager.js +1226 -1226
- package/src/engine/graphics/render/forward_plus/model/PointLight.js +1 -1
- package/src/engine/graphics/sh3/lpv/lpv_obtain_storage_cached_volume.js +1 -1
- package/src/engine/graphics/sh3/path_tracer/texture/sample_material.js +2 -2
- package/src/engine/graphics/texture/atlas/TextureAtlasDebugger.js +1 -1
- package/src/engine/graphics/texture/sampler/HarmonicDiffusionGrid.js +145 -145
- package/src/engine/graphics/texture/sampler/serialization/TextureBinaryBufferSerializer.js +2 -2
- package/src/engine/intelligence/behavior/ecs/BehaviorComponent.d.ts +2 -6
- package/src/engine/intelligence/behavior/ecs/BehaviorComponent.d.ts.map +1 -1
- package/src/engine/intelligence/behavior/ecs/BehaviorComponent.js +0 -10
- package/src/engine/intelligence/mcts/MonteCarlo.js +275 -275
- package/src/engine/navigation/ecs/path_following/PathFollower.js +222 -222
- package/src/generation/grid/GridData.js +220 -220
- package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.js +385 -385
- package/src/view/elements/image/SvgImageView.js +1 -1
- package/src/view/elements/windrose/WindRoseDiagram.js +369 -369
- package/src/view/minimap/gl/MinimapFogOfWar.js +3 -3
- package/src/view/util/DomSizeObserver.js +1 -1
- package/src/core/binary/clz32.d.ts +0 -6
- package/src/core/binary/clz32.d.ts.map +0 -1
- package/src/core/binary/clz32.js +0 -5
- package/src/core/binary/type/dataTypeFromTypedArray.d.ts +0 -8
- package/src/core/binary/type/dataTypeFromTypedArray.d.ts.map +0 -1
- package/src/core/binary/type/dataTypeFromTypedArray.js +0 -11
- package/src/core/collection/array/computeHashIntegerArray.d.ts +0 -1
- package/src/core/collection/array/computeHashIntegerArray.d.ts.map +0 -1
- package/src/core/collection/array/computeHashIntegerArray.js +0 -7
- package/src/core/collection/array/typed/typedArrayToDataType.d.ts +0 -6
- package/src/core/collection/array/typed/typedArrayToDataType.d.ts.map +0 -1
- package/src/core/collection/array/typed/typedArrayToDataType.js +0 -6
- package/src/core/geom/3d/mat4/MATRIX_4_IDENTITY.d.ts +0 -6
- package/src/core/geom/3d/mat4/MATRIX_4_IDENTITY.d.ts.map +0 -1
- package/src/core/geom/3d/mat4/MATRIX_4_IDENTITY.js +0 -7
- package/src/core/graph/eigen/eigen_values_find_spectral_gap.d.ts.map +0 -1
- package/src/core/graph/eigen/matrix_eigenvalues_in_place.d.ts +0 -8
- package/src/core/graph/eigen/matrix_eigenvalues_in_place.d.ts.map +0 -1
- package/src/core/graph/eigen/matrix_householder_in_place.d.ts.map +0 -1
- package/src/core/graph/eigen/matrix_qr_in_place.d.ts +0 -9
- package/src/core/graph/eigen/matrix_qr_in_place.d.ts.map +0 -1
- package/src/core/graph/eigen/matrix_top_eigenvector_power_iteration.d.ts.map +0 -1
- package/src/core/math/spline/cubicCurve.d.ts +0 -6
- package/src/core/math/spline/cubicCurve.d.ts.map +0 -1
- package/src/core/math/spline/cubicCurve.js +0 -6
- package/src/core/math/spline/spline_bezier2.d.ts +0 -6
- package/src/core/math/spline/spline_bezier2.d.ts.map +0 -1
- package/src/core/math/spline/spline_bezier2.js +0 -6
- package/src/core/math/spline/spline_bezier3.d.ts +0 -6
- package/src/core/math/spline/spline_bezier3.d.ts.map +0 -1
- package/src/core/math/spline/spline_bezier3.js +0 -6
- package/src/core/math/spline/spline_bezier3_bounds.d.ts +0 -6
- package/src/core/math/spline/spline_bezier3_bounds.d.ts.map +0 -1
- package/src/core/math/spline/spline_bezier3_bounds.js +0 -6
- package/src/core/math/spline/spline_hermite3.d.ts +0 -6
- package/src/core/math/spline/spline_hermite3.d.ts.map +0 -1
- package/src/core/math/spline/spline_hermite3.js +0 -6
- package/src/core/math/spline/spline_hermite3_bounds.d.ts +0 -6
- package/src/core/math/spline/spline_hermite3_bounds.d.ts.map +0 -1
- package/src/core/math/spline/spline_hermite3_bounds.js +0 -6
- package/src/core/math/spline/spline_hermite3_to_bezier.d.ts +0 -2
- package/src/core/math/spline/spline_hermite3_to_bezier.d.ts.map +0 -1
- package/src/core/math/spline/spline_hermite3_to_bezier.js +0 -6
- package/src/engine/intelligence/behavior/decorator/RepeatUntilFailureBehavior.d.ts +0 -37
- package/src/engine/intelligence/behavior/decorator/RepeatUntilFailureBehavior.d.ts.map +0 -1
- package/src/engine/intelligence/behavior/decorator/RepeatUntilFailureBehavior.js +0 -70
- /package/src/core/{graph → math/linalg}/eigen/eigen_values_find_spectral_gap.d.ts +0 -0
- /package/src/core/{graph → math/linalg}/eigen/eigen_values_find_spectral_gap.js +0 -0
- /package/src/core/{graph → math/linalg}/eigen/matrix_householder_in_place.d.ts +0 -0
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import { assert } from "../assert.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Compute the largest positive integer divisor of a given "product" value
|
|
5
|
-
* @param {number} product
|
|
6
|
-
* @param {number} limit
|
|
7
|
-
* @returns {number}
|
|
8
|
-
*/
|
|
9
|
-
export function computeWholeDivisorLow(product, limit) {
|
|
10
|
-
|
|
11
|
-
assert.isNumber(product, 'product');
|
|
12
|
-
assert.isInteger(product, 'product');
|
|
13
|
-
|
|
14
|
-
assert.isNumber(limit, 'limit');
|
|
15
|
-
assert.isInteger(limit, 'limit');
|
|
16
|
-
|
|
17
|
-
assert.
|
|
18
|
-
assert.
|
|
19
|
-
|
|
20
|
-
let i = limit;
|
|
21
|
-
|
|
22
|
-
while (i > 1) {
|
|
23
|
-
|
|
24
|
-
if (product % i === 0) {
|
|
25
|
-
break;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
i--;
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return i;
|
|
33
|
-
}
|
|
1
|
+
import { assert } from "../assert.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Compute the largest positive integer divisor of a given "product" value
|
|
5
|
+
* @param {number} product
|
|
6
|
+
* @param {number} limit
|
|
7
|
+
* @returns {number}
|
|
8
|
+
*/
|
|
9
|
+
export function computeWholeDivisorLow(product, limit) {
|
|
10
|
+
|
|
11
|
+
assert.isNumber(product, 'product');
|
|
12
|
+
assert.isInteger(product, 'product');
|
|
13
|
+
|
|
14
|
+
assert.isNumber(limit, 'limit');
|
|
15
|
+
assert.isInteger(limit, 'limit');
|
|
16
|
+
|
|
17
|
+
assert.isFinite(limit,'limit');
|
|
18
|
+
assert.isFinite(product,'product');
|
|
19
|
+
|
|
20
|
+
let i = limit;
|
|
21
|
+
|
|
22
|
+
while (i > 1) {
|
|
23
|
+
|
|
24
|
+
if (product % i === 0) {
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
i--;
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return i;
|
|
33
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eigen_values_find_spectral_gap.d.ts","sourceRoot":"","sources":["../../../../../../src/core/math/linalg/eigen/eigen_values_find_spectral_gap.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,uDAHW,MAAM,EAAE,GACN,MAAM,CAoBlB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* list of eigen values square matrix (allow non-symmetric)
|
|
3
|
+
* NOTE: Modifies input matrix
|
|
4
|
+
* @template T extends ArrayLike<number>
|
|
5
|
+
* @param {T} out
|
|
6
|
+
* @param {SquareMatrix} mat
|
|
7
|
+
* @return {T}
|
|
8
|
+
*/
|
|
9
|
+
export function matrix_eigenvalues_in_place<T>(out: T, mat: SquareMatrix): T;
|
|
10
|
+
//# sourceMappingURL=matrix_eigenvalues_in_place.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matrix_eigenvalues_in_place.d.ts","sourceRoot":"","sources":["../../../../../../src/core/math/linalg/eigen/matrix_eigenvalues_in_place.js"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,6EASC"}
|
|
@@ -3,19 +3,20 @@ import { matrix_qr_in_place } from "./matrix_qr_in_place.js";
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* list of eigen values square matrix (allow non
|
|
6
|
+
* list of eigen values square matrix (allow non-symmetric)
|
|
7
7
|
* NOTE: Modifies input matrix
|
|
8
|
+
* @template T extends ArrayLike<number>
|
|
9
|
+
* @param {T} out
|
|
8
10
|
* @param {SquareMatrix} mat
|
|
9
|
-
* @return {
|
|
11
|
+
* @return {T}
|
|
10
12
|
*/
|
|
11
|
-
export function matrix_eigenvalues_in_place(mat) {
|
|
13
|
+
export function matrix_eigenvalues_in_place(out, mat) {
|
|
12
14
|
const n = mat.size;
|
|
15
|
+
|
|
13
16
|
matrix_householder_in_place(mat.data, n);
|
|
14
17
|
matrix_qr_in_place(mat.data, n);
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
mat.readDiagonal(result);
|
|
19
|
+
mat.readDiagonal(out);
|
|
19
20
|
|
|
20
|
-
return
|
|
21
|
+
return out;
|
|
21
22
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matrix_householder_in_place.d.ts","sourceRoot":"","sources":["../../../../../../src/core/math/linalg/eigen/matrix_householder_in_place.js"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,+CAHW,MAAM,EAAE,KACR,MAAM,QA0FhB"}
|
|
@@ -32,14 +32,20 @@ export function matrix_householder_in_place(a, n) {
|
|
|
32
32
|
sum = sum + u[i] * u[i];
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const u_k_1_abs = Math.abs(u_k_1);
|
|
38
|
-
if (u_k_1_abs < EPSILON) {
|
|
35
|
+
if (sum < EPSILON * EPSILON) {
|
|
36
|
+
// sub-column already zero — nothing to reduce at this k
|
|
39
37
|
continue;
|
|
40
38
|
}
|
|
41
39
|
|
|
42
|
-
const
|
|
40
|
+
const u_k_1 = u[k + 1];
|
|
41
|
+
const u_k_1_abs = Math.abs(u_k_1);
|
|
42
|
+
|
|
43
|
+
// sigma = sign(u[k+1]) · ‖u‖. When u[k+1] = 0 the sign is arbitrary
|
|
44
|
+
// (entries below are still nonzero by the `sum` check above), so pick
|
|
45
|
+
// +‖u‖.
|
|
46
|
+
const sigma = u_k_1_abs < EPSILON
|
|
47
|
+
? Math.sqrt(sum)
|
|
48
|
+
: Math.sqrt(sum) * u_k_1 / u_k_1_abs;
|
|
43
49
|
|
|
44
50
|
u[k + 1] += sigma;
|
|
45
51
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Perform QR factorization in-place.
|
|
3
|
+
* Subfunction that analyzes eigenvalues by QR decomposition.
|
|
4
|
+
*
|
|
5
|
+
* Single-shift Wilkinson iteration: deflates the trailing subdiagonal one row
|
|
6
|
+
* at a time as it converges. A complex eigenvalue pair leaves a 2×2 trailing
|
|
7
|
+
* block whose inner subdiagonal does not vanish, and this routine will spin
|
|
8
|
+
* on it indefinitely — only safe today for matrices with all-real eigenvalues.
|
|
9
|
+
*
|
|
10
|
+
* @see http://www-in.aut.ac.jp/~minemura/pub/Csimu/C/QRmethod.html
|
|
11
|
+
* @param {number[]} a Square matrix
|
|
12
|
+
* @param {number} n size of the matrix in single dimension
|
|
13
|
+
*/
|
|
14
|
+
export function matrix_qr_in_place(a: number[], n: number): void;
|
|
15
|
+
//# sourceMappingURL=matrix_qr_in_place.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matrix_qr_in_place.d.ts","sourceRoot":"","sources":["../../../../../../src/core/math/linalg/eigen/matrix_qr_in_place.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,sCAHW,MAAM,EAAE,KACR,MAAM,QA8GhB"}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
const EPSILON = 1e-10;
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Perform QR factorization in-place
|
|
5
|
-
* Subfunction that analyzes eigenvalues by QR decomposition
|
|
4
|
+
* Perform QR factorization in-place.
|
|
5
|
+
* Subfunction that analyzes eigenvalues by QR decomposition.
|
|
6
|
+
*
|
|
7
|
+
* Single-shift Wilkinson iteration: deflates the trailing subdiagonal one row
|
|
8
|
+
* at a time as it converges. A complex eigenvalue pair leaves a 2×2 trailing
|
|
9
|
+
* block whose inner subdiagonal does not vanish, and this routine will spin
|
|
10
|
+
* on it indefinitely — only safe today for matrices with all-real eigenvalues.
|
|
11
|
+
*
|
|
6
12
|
* @see http://www-in.aut.ac.jp/~minemura/pub/Csimu/C/QRmethod.html
|
|
7
13
|
* @param {number[]} a Square matrix
|
|
8
14
|
* @param {number} n size of the matrix in single dimension
|
|
@@ -7,9 +7,6 @@
|
|
|
7
7
|
* 3x3 covariance, etc.). Unsuitable when the top two eigenvalues have nearly
|
|
8
8
|
* equal magnitude — convergence stalls in that regime.
|
|
9
9
|
*
|
|
10
|
-
* NOTE: intended to live in @woosh/meep-engine under core/graph/eigen/. Kept
|
|
11
|
-
* local for now.
|
|
12
|
-
*
|
|
13
10
|
* @param {SquareMatrix} matrix Symmetric, column-major as per SquareMatrix
|
|
14
11
|
* @param {number[]|Float32Array|Float64Array} out Eigenvector is written here, length >= matrix.size
|
|
15
12
|
* @param {number} [max_iterations=64]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matrix_top_eigenvector_power_iteration.d.ts","sourceRoot":"","sources":["../../../../../../src/core/math/linalg/eigen/matrix_top_eigenvector_power_iteration.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;GAcG;AACH,kFALW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,mBAClC,MAAM,cACN,MAAM,GACJ,MAAM,CAoFlB"}
|
|
@@ -16,9 +16,6 @@ function ensure_scratch(n) {
|
|
|
16
16
|
* 3x3 covariance, etc.). Unsuitable when the top two eigenvalues have nearly
|
|
17
17
|
* equal magnitude — convergence stalls in that regime.
|
|
18
18
|
*
|
|
19
|
-
* NOTE: intended to live in @woosh/meep-engine under core/graph/eigen/. Kept
|
|
20
|
-
* local for now.
|
|
21
|
-
*
|
|
22
19
|
* @param {SquareMatrix} matrix Symmetric, column-major as per SquareMatrix
|
|
23
20
|
* @param {number[]|Float32Array|Float64Array} out Eigenvector is written here, length >= matrix.size
|
|
24
21
|
* @param {number} [max_iterations=64]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find all complex roots of a univariate polynomial via Aberth–Ehrlich.
|
|
3
|
+
*
|
|
4
|
+
* The polynomial is given in ascending-power coefficient form:
|
|
5
|
+
* p(x) = coeffs[0] + coeffs[1]·x + … + coeffs[degree]·x^degree
|
|
6
|
+
* The leading coefficient `coeffs[degree]` must be nonzero.
|
|
7
|
+
*
|
|
8
|
+
* Exactly `degree` complex numbers are written into `roots_re`/`roots_im` at
|
|
9
|
+
* index `offset`, `offset + 1`, …, `offset + degree - 1`. The order they
|
|
10
|
+
* appear in is not specified.
|
|
11
|
+
*
|
|
12
|
+
* @param {Float64Array|number[]} coeffs ascending-power, length ≥ degree + 1
|
|
13
|
+
* @param {number} degree polynomial degree, ≥ 1, ≤ 64
|
|
14
|
+
* @param {Float64Array|number[]} roots_re real parts, length ≥ offset + degree
|
|
15
|
+
* @param {Float64Array|number[]} roots_im imaginary parts, length ≥ offset + degree
|
|
16
|
+
* @param {number} offset
|
|
17
|
+
*/
|
|
18
|
+
export function polynomial_complex_roots_aberth_ehrlich(coeffs: Float64Array | number[], degree: number, roots_re: Float64Array | number[], roots_im: Float64Array | number[], offset: number): void;
|
|
19
|
+
//# sourceMappingURL=polynomial_complex_roots_aberth_ehrlich.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polynomial_complex_roots_aberth_ehrlich.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.js"],"names":[],"mappings":"AA6DA;;;;;;;;;;;;;;;;GAgBG;AACH,gEANW,YAAY,GAAC,MAAM,EAAE,UACrB,MAAM,YACN,YAAY,GAAC,MAAM,EAAE,YACrB,YAAY,GAAC,MAAM,EAAE,UACrB,MAAM,QAoFhB"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { assert } from "../../assert.js";
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Find all roots of a univariate polynomial in the complex plane via
|
|
5
|
+
Aberth–Ehrlich simultaneous iteration. Real and complex roots are isolated
|
|
6
|
+
together; the caller separates real ones by inspecting the imaginary parts.
|
|
7
|
+
|
|
8
|
+
Reference: Aberth (1973), "Iteration methods for finding all zeros of a
|
|
9
|
+
polynomial simultaneously", Math. Comp. 27.
|
|
10
|
+
|
|
11
|
+
The iteration is
|
|
12
|
+
|
|
13
|
+
z_k ← z_k − w_k / (1 − w_k · Σ_{j≠k} 1/(z_k − z_j))
|
|
14
|
+
|
|
15
|
+
with w_k = p(z_k) / p'(z_k). Initial points are placed on a circle of radius
|
|
16
|
+
= Cauchy bound, with a fixed phase offset so an initial guess never lands
|
|
17
|
+
exactly on a real root (which would make the pairwise sum singular at step
|
|
18
|
+
zero). Convergence is quadratic once close.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const MAX_SUPPORTED_DEGREE = 64;
|
|
22
|
+
|
|
23
|
+
const ABERTH_MAX_ITERATIONS = 80;
|
|
24
|
+
const ABERTH_CONVERGENCE_TOLERANCE = 1e-14;
|
|
25
|
+
|
|
26
|
+
const _DERIV = new Float64Array(MAX_SUPPORTED_DEGREE);
|
|
27
|
+
const _P_EVAL = new Float64Array(2);
|
|
28
|
+
const _DP_EVAL = new Float64Array(2);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Horner evaluation of polynomial p(z) at a complex z = (zr, zi).
|
|
32
|
+
* Writes [p(z).re, p(z).im] into `out`.
|
|
33
|
+
*/
|
|
34
|
+
function poly_eval_complex(coeffs, degree, zr, zi, out) {
|
|
35
|
+
let pr = coeffs[degree];
|
|
36
|
+
let pi = 0;
|
|
37
|
+
|
|
38
|
+
for (let i = degree - 1; i >= 0; i--) {
|
|
39
|
+
const new_pr = pr * zr - pi * zi + coeffs[i];
|
|
40
|
+
const new_pi = pr * zi + pi * zr;
|
|
41
|
+
pr = new_pr;
|
|
42
|
+
pi = new_pi;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
out[0] = pr;
|
|
46
|
+
out[1] = pi;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Cauchy bound: every root z of `coeffs` satisfies |z| ≤ this value.
|
|
51
|
+
*/
|
|
52
|
+
function cauchy_root_magnitude_bound(coeffs, degree) {
|
|
53
|
+
const lead = Math.abs(coeffs[degree]);
|
|
54
|
+
let m = 0;
|
|
55
|
+
for (let i = 0; i < degree; i++) {
|
|
56
|
+
const a = Math.abs(coeffs[i]);
|
|
57
|
+
if (a > m) m = a;
|
|
58
|
+
}
|
|
59
|
+
return 1 + m / lead;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Find all complex roots of a univariate polynomial via Aberth–Ehrlich.
|
|
64
|
+
*
|
|
65
|
+
* The polynomial is given in ascending-power coefficient form:
|
|
66
|
+
* p(x) = coeffs[0] + coeffs[1]·x + … + coeffs[degree]·x^degree
|
|
67
|
+
* The leading coefficient `coeffs[degree]` must be nonzero.
|
|
68
|
+
*
|
|
69
|
+
* Exactly `degree` complex numbers are written into `roots_re`/`roots_im` at
|
|
70
|
+
* index `offset`, `offset + 1`, …, `offset + degree - 1`. The order they
|
|
71
|
+
* appear in is not specified.
|
|
72
|
+
*
|
|
73
|
+
* @param {Float64Array|number[]} coeffs ascending-power, length ≥ degree + 1
|
|
74
|
+
* @param {number} degree polynomial degree, ≥ 1, ≤ 64
|
|
75
|
+
* @param {Float64Array|number[]} roots_re real parts, length ≥ offset + degree
|
|
76
|
+
* @param {Float64Array|number[]} roots_im imaginary parts, length ≥ offset + degree
|
|
77
|
+
* @param {number} offset
|
|
78
|
+
*/
|
|
79
|
+
export function polynomial_complex_roots_aberth_ehrlich(
|
|
80
|
+
coeffs, degree,
|
|
81
|
+
roots_re, roots_im, offset
|
|
82
|
+
) {
|
|
83
|
+
assert.greaterThanOrEqual(degree, 1, 'degree');
|
|
84
|
+
assert.greaterThanOrEqual(MAX_SUPPORTED_DEGREE, degree, 'degree exceeds MAX_SUPPORTED_DEGREE');
|
|
85
|
+
assert.isNonNegativeInteger(offset, 'offset');
|
|
86
|
+
|
|
87
|
+
// derivative: _DERIV[i] = (i + 1) * coeffs[i + 1], i = 0 .. degree - 1
|
|
88
|
+
for (let i = 0; i < degree; i++) {
|
|
89
|
+
_DERIV[i] = (i + 1) * coeffs[i + 1];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const radius = cauchy_root_magnitude_bound(coeffs, degree);
|
|
93
|
+
|
|
94
|
+
// Initial points around a circle, with a small phase offset to avoid
|
|
95
|
+
// landing exactly on a real root at iteration zero.
|
|
96
|
+
const phase_offset = 0.5;
|
|
97
|
+
const two_pi_over_n = (2 * Math.PI) / degree;
|
|
98
|
+
for (let k = 0; k < degree; k++) {
|
|
99
|
+
const angle = k * two_pi_over_n + phase_offset;
|
|
100
|
+
roots_re[offset + k] = radius * Math.cos(angle);
|
|
101
|
+
roots_im[offset + k] = radius * Math.sin(angle);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
for (let iter = 0; iter < ABERTH_MAX_ITERATIONS; iter++) {
|
|
105
|
+
let max_correction_sq = 0;
|
|
106
|
+
|
|
107
|
+
for (let k = 0; k < degree; k++) {
|
|
108
|
+
const zr = roots_re[offset + k];
|
|
109
|
+
const zi = roots_im[offset + k];
|
|
110
|
+
|
|
111
|
+
poly_eval_complex(coeffs, degree, zr, zi, _P_EVAL);
|
|
112
|
+
const pr = _P_EVAL[0];
|
|
113
|
+
const pi = _P_EVAL[1];
|
|
114
|
+
|
|
115
|
+
poly_eval_complex(_DERIV, degree - 1, zr, zi, _DP_EVAL);
|
|
116
|
+
const dpr = _DP_EVAL[0];
|
|
117
|
+
const dpi = _DP_EVAL[1];
|
|
118
|
+
|
|
119
|
+
// w = p / p'
|
|
120
|
+
const dp_norm_sq = dpr * dpr + dpi * dpi;
|
|
121
|
+
if (dp_norm_sq === 0) continue;
|
|
122
|
+
const inv_dp_sq = 1 / dp_norm_sq;
|
|
123
|
+
const wr = (pr * dpr + pi * dpi) * inv_dp_sq;
|
|
124
|
+
const wi = (pi * dpr - pr * dpi) * inv_dp_sq;
|
|
125
|
+
|
|
126
|
+
// S = Σ_{j≠k} 1/(z_k − z_j) in complex
|
|
127
|
+
let sr = 0, si = 0;
|
|
128
|
+
for (let j = 0; j < degree; j++) {
|
|
129
|
+
if (j === k) continue;
|
|
130
|
+
const dr = zr - roots_re[offset + j];
|
|
131
|
+
const di = zi - roots_im[offset + j];
|
|
132
|
+
const denom_sq = dr * dr + di * di;
|
|
133
|
+
if (denom_sq === 0) continue;
|
|
134
|
+
const inv_d_sq = 1 / denom_sq;
|
|
135
|
+
sr += dr * inv_d_sq;
|
|
136
|
+
si += -di * inv_d_sq;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// correction = w / (1 − w·S)
|
|
140
|
+
const ws_r = wr * sr - wi * si;
|
|
141
|
+
const ws_i = wr * si + wi * sr;
|
|
142
|
+
const denom_r = 1 - ws_r;
|
|
143
|
+
const denom_i = -ws_i;
|
|
144
|
+
const denom_sq2 = denom_r * denom_r + denom_i * denom_i;
|
|
145
|
+
if (denom_sq2 === 0) continue;
|
|
146
|
+
const inv_denom_sq2 = 1 / denom_sq2;
|
|
147
|
+
const corr_r = (wr * denom_r + wi * denom_i) * inv_denom_sq2;
|
|
148
|
+
const corr_i = (wi * denom_r - wr * denom_i) * inv_denom_sq2;
|
|
149
|
+
|
|
150
|
+
roots_re[offset + k] = zr - corr_r;
|
|
151
|
+
roots_im[offset + k] = zi - corr_i;
|
|
152
|
+
|
|
153
|
+
const corr_sq = corr_r * corr_r + corr_i * corr_i;
|
|
154
|
+
if (corr_sq > max_correction_sq) max_correction_sq = corr_sq;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (max_correction_sq < ABERTH_CONVERGENCE_TOLERANCE * ABERTH_CONVERGENCE_TOLERANCE) {
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find all real roots of a univariate polynomial that lie inside the closed
|
|
3
|
+
* interval [lo, hi]. Roots are written to `out[out_offset ..]` in ascending
|
|
4
|
+
* order; the count of roots written is returned.
|
|
5
|
+
*
|
|
6
|
+
* @param {Float64Array|number[]} coeffs ascending power order: coeffs[i] is the coefficient of x^i
|
|
7
|
+
* @param {number} degree polynomial degree (coeffs must have at least `degree + 1` entries)
|
|
8
|
+
* @param {number} lo
|
|
9
|
+
* @param {number} hi
|
|
10
|
+
* @param {Float64Array|number[]} out
|
|
11
|
+
* @param {number} out_offset
|
|
12
|
+
* @returns {number} number of roots written
|
|
13
|
+
*/
|
|
14
|
+
export function polynomial_real_roots_in_interval(coeffs: Float64Array | number[], degree: number, lo: number, hi: number, out: Float64Array | number[], out_offset: number): number;
|
|
15
|
+
//# sourceMappingURL=polynomial_real_roots_in_interval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polynomial_real_roots_in_interval.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/linalg/polynomial_real_roots_in_interval.js"],"names":[],"mappings":"AAsGA;;;;;;;;;;;;GAYG;AACH,0DARW,YAAY,GAAC,MAAM,EAAE,UACrB,MAAM,MACN,MAAM,MACN,MAAM,OACN,YAAY,GAAC,MAAM,EAAE,cACrB,MAAM,GACJ,MAAM,CAsFlB"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { assert } from "../../assert.js";
|
|
2
|
+
import { solveQuadratic } from "../solveQuadratic.js";
|
|
3
|
+
import { polynomial_complex_roots_aberth_ehrlich } from "./polynomial_complex_roots_aberth_ehrlich.js";
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
Find all real roots of a univariate polynomial that lie inside a closed interval [lo, hi].
|
|
7
|
+
Coefficient layout: coeffs[i] is the coefficient of x^i, so
|
|
8
|
+
|
|
9
|
+
p(x) = coeffs[0] + coeffs[1]*x + coeffs[2]*x^2 + ... + coeffs[degree]*x^degree
|
|
10
|
+
|
|
11
|
+
Approach:
|
|
12
|
+
1. Trim leading zeros (treat the polynomial at its effective degree).
|
|
13
|
+
2. Closed-form for degrees 1 and 2.
|
|
14
|
+
3. For degree ≥ 3, isolate all complex roots via
|
|
15
|
+
polynomial_complex_roots_aberth_ehrlich, then keep the ones whose
|
|
16
|
+
imaginary part is below a scale-relative threshold and whose real part
|
|
17
|
+
lies in [lo, hi]. Each survivor is Newton-polished against the real
|
|
18
|
+
polynomial as a sanity / precision pass.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const MAX_SUPPORTED_DEGREE = 64;
|
|
22
|
+
|
|
23
|
+
const SCRATCH_COEFF = new Float64Array(MAX_SUPPORTED_DEGREE + 1);
|
|
24
|
+
const SCRATCH_ROOTS_RE = new Float64Array(MAX_SUPPORTED_DEGREE);
|
|
25
|
+
const SCRATCH_ROOTS_IM = new Float64Array(MAX_SUPPORTED_DEGREE);
|
|
26
|
+
const SCRATCH_OUT_REAL = new Float64Array(MAX_SUPPORTED_DEGREE);
|
|
27
|
+
const SCRATCH_QUADRATIC = new Float64Array(2);
|
|
28
|
+
const SCRATCH_EVAL = new Float64Array(2);
|
|
29
|
+
|
|
30
|
+
const NEWTON_MAX_ITERATIONS = 32;
|
|
31
|
+
|
|
32
|
+
// Imaginary part below this fraction of root scale is treated as real.
|
|
33
|
+
const IMAG_PART_REAL_THRESHOLD = 1e-8;
|
|
34
|
+
|
|
35
|
+
const NEWTON_RELATIVE_RESIDUAL_TOLERANCE = 1e-10;
|
|
36
|
+
|
|
37
|
+
const DEDUPE_RELATIVE_TOLERANCE = 1e-7;
|
|
38
|
+
|
|
39
|
+
function poly_eval_with_derivative(coeffs, degree, x, out) {
|
|
40
|
+
let p = coeffs[degree];
|
|
41
|
+
let dp = 0;
|
|
42
|
+
|
|
43
|
+
for (let i = degree - 1; i >= 0; i--) {
|
|
44
|
+
dp = dp * x + p;
|
|
45
|
+
p = p * x + coeffs[i];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
out[0] = p;
|
|
49
|
+
out[1] = dp;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function max_abs_coefficient(coeffs, degree) {
|
|
53
|
+
let m = 0;
|
|
54
|
+
for (let i = 0; i <= degree; i++) {
|
|
55
|
+
const a = Math.abs(coeffs[i]);
|
|
56
|
+
if (a > m) m = a;
|
|
57
|
+
}
|
|
58
|
+
return m;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function root_scale_estimate(coeffs, degree) {
|
|
62
|
+
const lead = Math.abs(coeffs[degree]);
|
|
63
|
+
let m = 0;
|
|
64
|
+
for (let i = 0; i < degree; i++) {
|
|
65
|
+
const a = Math.abs(coeffs[i]);
|
|
66
|
+
if (a > m) m = a;
|
|
67
|
+
}
|
|
68
|
+
return 1 + m / lead;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function newton_polish_real(coeffs, degree, x_init) {
|
|
72
|
+
let x = x_init;
|
|
73
|
+
|
|
74
|
+
for (let i = 0; i < NEWTON_MAX_ITERATIONS; i++) {
|
|
75
|
+
poly_eval_with_derivative(coeffs, degree, x, SCRATCH_EVAL);
|
|
76
|
+
|
|
77
|
+
const p = SCRATCH_EVAL[0];
|
|
78
|
+
const dp = SCRATCH_EVAL[1];
|
|
79
|
+
|
|
80
|
+
if (dp === 0) break;
|
|
81
|
+
|
|
82
|
+
const step = p / dp;
|
|
83
|
+
x -= step;
|
|
84
|
+
|
|
85
|
+
if (Math.abs(step) <= Math.abs(x) * 1e-15) break;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return x;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function insert_sorted_unique(roots, count, value, dedupe_tolerance) {
|
|
92
|
+
let i = 0;
|
|
93
|
+
while (i < count && roots[i] < value) i++;
|
|
94
|
+
|
|
95
|
+
if (i > 0 && Math.abs(roots[i - 1] - value) <= dedupe_tolerance) return count;
|
|
96
|
+
if (i < count && Math.abs(roots[i] - value) <= dedupe_tolerance) return count;
|
|
97
|
+
|
|
98
|
+
for (let j = count; j > i; j--) roots[j] = roots[j - 1];
|
|
99
|
+
roots[i] = value;
|
|
100
|
+
return count + 1;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Find all real roots of a univariate polynomial that lie inside the closed
|
|
105
|
+
* interval [lo, hi]. Roots are written to `out[out_offset ..]` in ascending
|
|
106
|
+
* order; the count of roots written is returned.
|
|
107
|
+
*
|
|
108
|
+
* @param {Float64Array|number[]} coeffs ascending power order: coeffs[i] is the coefficient of x^i
|
|
109
|
+
* @param {number} degree polynomial degree (coeffs must have at least `degree + 1` entries)
|
|
110
|
+
* @param {number} lo
|
|
111
|
+
* @param {number} hi
|
|
112
|
+
* @param {Float64Array|number[]} out
|
|
113
|
+
* @param {number} out_offset
|
|
114
|
+
* @returns {number} number of roots written
|
|
115
|
+
*/
|
|
116
|
+
export function polynomial_real_roots_in_interval(
|
|
117
|
+
coeffs,
|
|
118
|
+
degree,
|
|
119
|
+
lo, hi,
|
|
120
|
+
out, out_offset
|
|
121
|
+
) {
|
|
122
|
+
assert.isNonNegativeInteger(degree, 'degree');
|
|
123
|
+
assert.isNonNegativeInteger(out_offset, 'out_offset');
|
|
124
|
+
assert.greaterThanOrEqual(MAX_SUPPORTED_DEGREE, degree, 'degree exceeds MAX_SUPPORTED_DEGREE');
|
|
125
|
+
|
|
126
|
+
if (degree === 0) return 0;
|
|
127
|
+
|
|
128
|
+
const coeff_norm = max_abs_coefficient(coeffs, degree);
|
|
129
|
+
if (coeff_norm === 0) return 0;
|
|
130
|
+
|
|
131
|
+
let effective_degree = degree;
|
|
132
|
+
const leading_zero_threshold = coeff_norm * 1e-14;
|
|
133
|
+
while (effective_degree > 0 && Math.abs(coeffs[effective_degree]) <= leading_zero_threshold) {
|
|
134
|
+
effective_degree--;
|
|
135
|
+
}
|
|
136
|
+
if (effective_degree === 0) return 0;
|
|
137
|
+
|
|
138
|
+
if (effective_degree === 1) {
|
|
139
|
+
const root = -coeffs[0] / coeffs[1];
|
|
140
|
+
if (root >= lo && root <= hi) {
|
|
141
|
+
out[out_offset] = root;
|
|
142
|
+
return 1;
|
|
143
|
+
}
|
|
144
|
+
return 0;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (effective_degree === 2) {
|
|
148
|
+
const root_count = solveQuadratic(SCRATCH_QUADRATIC, 0, coeffs[2], coeffs[1], coeffs[0]);
|
|
149
|
+
let written = 0;
|
|
150
|
+
for (let i = 0; i < root_count; i++) {
|
|
151
|
+
const r = SCRATCH_QUADRATIC[i];
|
|
152
|
+
if (r >= lo && r <= hi) {
|
|
153
|
+
if (written === 0 || Math.abs(out[out_offset + written - 1] - r) > 0) {
|
|
154
|
+
out[out_offset + written] = r;
|
|
155
|
+
written++;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return written;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
for (let i = 0; i <= effective_degree; i++) SCRATCH_COEFF[i] = coeffs[i];
|
|
163
|
+
|
|
164
|
+
polynomial_complex_roots_aberth_ehrlich(
|
|
165
|
+
SCRATCH_COEFF, effective_degree,
|
|
166
|
+
SCRATCH_ROOTS_RE, SCRATCH_ROOTS_IM, 0
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
const root_scale = root_scale_estimate(SCRATCH_COEFF, effective_degree);
|
|
170
|
+
const imag_threshold = IMAG_PART_REAL_THRESHOLD * Math.max(1, root_scale);
|
|
171
|
+
const residual_tolerance = NEWTON_RELATIVE_RESIDUAL_TOLERANCE * coeff_norm;
|
|
172
|
+
const dedupe_tolerance = DEDUPE_RELATIVE_TOLERANCE * Math.max(1, Math.max(Math.abs(lo), Math.abs(hi)));
|
|
173
|
+
|
|
174
|
+
let unique_count = 0;
|
|
175
|
+
|
|
176
|
+
for (let i = 0; i < effective_degree; i++) {
|
|
177
|
+
const re = SCRATCH_ROOTS_RE[i];
|
|
178
|
+
const im = SCRATCH_ROOTS_IM[i];
|
|
179
|
+
|
|
180
|
+
if (!Number.isFinite(re) || !Number.isFinite(im)) continue;
|
|
181
|
+
|
|
182
|
+
if (Math.abs(im) > imag_threshold) continue;
|
|
183
|
+
|
|
184
|
+
const polished = newton_polish_real(SCRATCH_COEFF, effective_degree, re);
|
|
185
|
+
if (!Number.isFinite(polished)) continue;
|
|
186
|
+
|
|
187
|
+
poly_eval_with_derivative(SCRATCH_COEFF, effective_degree, polished, SCRATCH_EVAL);
|
|
188
|
+
if (Math.abs(SCRATCH_EVAL[0]) > residual_tolerance) continue;
|
|
189
|
+
|
|
190
|
+
if (polished < lo || polished > hi) continue;
|
|
191
|
+
|
|
192
|
+
unique_count = insert_sorted_unique(SCRATCH_OUT_REAL, unique_count, polished, dedupe_tolerance);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
for (let i = 0; i < unique_count; i++) {
|
|
196
|
+
out[out_offset + i] = SCRATCH_OUT_REAL[i];
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return unique_count;
|
|
200
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Return real solutions for a cubic polynomial: ax³ + bx² + cx + d
|
|
3
|
+
* Repeated roots are written once each — multiplicity is not duplicated in the output.
|
|
4
|
+
* Imaginary roots are not provided.
|
|
5
|
+
*
|
|
6
|
+
* @param {number[]|Float32Array|Float64Array} result solutions are written here
|
|
7
|
+
* @param {number} result_offset offset into result array where solutions are written to
|
|
8
|
+
* @param {number} a
|
|
9
|
+
* @param {number} b
|
|
10
|
+
* @param {number} c
|
|
11
|
+
* @param {number} d
|
|
12
|
+
* @returns {number} number of real roots found (0, 1, 2, or 3)
|
|
13
|
+
*/
|
|
14
|
+
export function solveCubic(result: number[] | Float32Array | Float64Array, result_offset: number, a: number, b: number, c: number, d: number): number;
|
|
15
|
+
//# sourceMappingURL=solveCubic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solveCubic.d.ts","sourceRoot":"","sources":["../../../../src/core/math/solveCubic.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;GAYG;AACH,mCARW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,iBAClC,MAAM,KACN,MAAM,KACN,MAAM,KACN,MAAM,KACN,MAAM,GACJ,MAAM,CA+DlB"}
|