@woosh/meep-engine 3.63.3 → 3.64.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/CHANGELOG.md +51 -0
- package/package.json +1 -1
- package/src/core/color/xyz/m3_chromatic_adaptation_bradford.d.ts +14 -0
- package/src/core/color/xyz/m3_chromatic_adaptation_bradford.d.ts.map +1 -0
- package/src/core/color/xyz/m3_chromatic_adaptation_bradford.js +51 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.d.ts +2 -1
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.d.ts.map +1 -1
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.js +51 -70
- package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.d.ts.map +1 -1
- package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.js +8 -64
- package/src/core/math/linalg/eigen/matrix_symmetric_jacobi_rotate_in_place.d.ts +17 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_jacobi_rotate_in_place.d.ts.map +1 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_jacobi_rotate_in_place.js +64 -0
- package/src/core/math/linalg/solve_box_constrained_qp.d.ts +30 -0
- package/src/core/math/linalg/solve_box_constrained_qp.d.ts.map +1 -0
- package/src/core/math/linalg/solve_box_constrained_qp.js +205 -0
- package/src/engine/physics/constraint/soft_spring_coefficients.d.ts +24 -0
- package/src/engine/physics/constraint/soft_spring_coefficients.d.ts.map +1 -0
- package/src/engine/physics/constraint/soft_spring_coefficients.js +38 -0
- package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
- package/src/engine/physics/constraint/solve_constraints.js +16 -8
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +54 -0
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +192 -7
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts +3 -5
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -1
- package/src/engine/physics/inertia/world_inverse_inertia.js +3 -5
- package/src/engine/physics/vehicle/RaycastVehicle.d.ts +183 -12
- package/src/engine/physics/vehicle/RaycastVehicle.d.ts.map +1 -1
- package/src/engine/physics/vehicle/RaycastVehicle.js +1046 -121
- package/src/shade/playground/tonemap_sdr/README.md +11 -8
- package/src/shade/playground/tonemap_sdr/ToneMapCompare.js +2 -2
- package/src/shade/renderer/Renderer.d.ts +5 -6
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +15 -88
- package/src/shade/renderer/animation/chunk_animation_curve_evaluate_keys.d.ts +14 -0
- package/src/shade/renderer/animation/chunk_animation_curve_evaluate_keys.d.ts.map +1 -0
- package/src/shade/renderer/animation/chunk_animation_curve_evaluate_keys.js +62 -0
- package/src/shade/renderer/deferred/tonemap/ColorGrade.d.ts +158 -0
- package/src/shade/renderer/deferred/tonemap/ColorGrade.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/ColorGrade.js +337 -0
- package/src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.d.ts +9 -0
- package/src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.js +15 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.d.ts +6 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.js +84 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.d.ts +10 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.js +25 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.d.ts +9 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.js +20 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.d.ts +14 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.js +30 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapOperator.d.ts +54 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapOperator.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapOperator.js +63 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapper.d.ts +106 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapper.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapper.js +474 -0
- package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.d.ts +5 -13
- package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.d.ts.map +1 -1
- package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.js +5 -44
- package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.d.ts +7 -25
- package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.d.ts.map +1 -1
- package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.js +11 -51
- package/src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.d.ts +20 -0
- package/src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.js +103 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_lut.d.ts +9 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_lut.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/{shader_tonemap_HDR_none.js → shader_tonemap_HDR_lut.js} +22 -18
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_lut.d.ts +9 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_lut.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/{shader_tonemap_LDR_aces.js → shader_tonemap_LDR_lut.js} +24 -24
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.d.ts +23 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.js +92 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.d.ts +15 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.js +73 -0
- package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
- package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
- package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
- package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
- package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +1 -1
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.d.ts +22 -0
- package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.js +62 -0
- package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.d.ts +13 -0
- package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.js +140 -0
- package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.d.ts +11 -0
- package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.js +65 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.d.ts +14 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.js +38 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_lut.d.ts +16 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_lut.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_lut.js +41 -0
- package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +8 -8
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +2 -0
- package/src/shade/renderer/ShadeToneMappingMode.d.ts +0 -15
- package/src/shade/renderer/ShadeToneMappingMode.d.ts.map +0 -1
- package/src/shade/renderer/ShadeToneMappingMode.js +0 -41
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.d.ts +0 -9
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.js +0 -79
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.d.ts +0 -17
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.js +0 -101
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_none.d.ts +0 -9
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_none.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.d.ts +0 -10
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.js +0 -80
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.d.ts +0 -9
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.js +0 -80
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_aces.d.ts +0 -10
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_aces.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.d.ts +0 -9
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.js +0 -71
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.d.ts +0 -10
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.js +0 -76
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_hdr_bt2390.d.ts +0 -3
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_hdr_bt2390.d.ts.map +0 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_hdr_bt2390.js +0 -44
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,57 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
### Colour grading in the tone-mapping LUT
|
|
6
|
+
|
|
7
|
+
- **Added:** `ColorGrade`, as `renderer.tone_mapper.grade`, neutral by default and baked into the tone mapper's LUTs
|
|
8
|
+
ahead of the operator, so it costs nothing per pixel. Any change bakes both LUTs again; a LUT the user supplies is
|
|
9
|
+
not graded. In order:
|
|
10
|
+
- white balance: Unreal's temperature white balance (`white_temperature`, `white_tint`), Planckian and daylight
|
|
11
|
+
loci, Bradford to D65;
|
|
12
|
+
- primaries: Unreal's `ColorCorrectAll` in AP1, saturation, contrast, gamma, gain and offset for `global`,
|
|
13
|
+
`shadows`, `midtones` and `highlights` (`ColorGradeZone`, each a `Vector4` of RGB and master), blended by
|
|
14
|
+
`shadows_max`, `highlights_min` and `highlights_max`. Values from an Unreal project give the same result;
|
|
15
|
+
- hue curves: `hue_shift` (degrees), `hue_saturation` (chroma multiplier) and `hue_lightness` (stops), each an
|
|
16
|
+
`AnimationCurve` over the OkLCh hue in degrees. Lightness is exposure at the colour's chromaticity, weighted by
|
|
17
|
+
its saturation against the Rec.709 gamut's edge at its hue, so greys never move.
|
|
18
|
+
- **Added:** `chunk_animation_curve_evaluate_keys`, `AnimationCurve.evaluate` on the GPU over a plain keyframe array;
|
|
19
|
+
`chunk_color_grade`; `chunk_CRM_REC709_AP1` (Rec.709↔AP1 and AP1 luminance, derived from the chromaticities);
|
|
20
|
+
`chunk_oklab_compute_max_saturation`; `m3_chromatic_adaptation_bradford`; `m3_white_balance_rec709`. The WGSL
|
|
21
|
+
emulator gains `degrees` and `radians`.
|
|
22
|
+
- **Changed:** a bake reads the grade. On an RTX 4090 (volumetrics_froxel, 1258 × 646) the ACES bake at 32³ costs
|
|
23
|
+
4–6 µs neutral and 6–7 µs with a full grade on SDR, 10–14 µs and 12–14 µs on HDR at 1000 cd/m²; 9 and 13 µs at
|
|
24
|
+
64³ on SDR, 24 and 28 µs on HDR. The apply pass is unchanged.
|
|
25
|
+
- **Changed:** a LUT's error against direct evaluation grows with the grade's detail. With three 20°-wide hue bands
|
|
26
|
+
and a full primary grade, ACES at 32³ has a p99 of 6.3 8-bit codes on SDR (2.5 neutral) and 15.5 10-bit PQ codes
|
|
27
|
+
on HDR (5.8 neutral); 64³ brings them to 2.4 and 5.4. Raise `lut_resolution` for such a grade.
|
|
28
|
+
|
|
29
|
+
### Tone mapping through a baked 3D LUT
|
|
30
|
+
|
|
31
|
+
- **Added:** `ToneMapper`, owned by the renderer as `renderer.tone_mapper`, made by `initialize`. It bakes its
|
|
32
|
+
`operator` into a 3D LUT per output, at `lut_resolution` (default 32, as in Unreal; at least 2, at most the
|
|
33
|
+
device's `maxTextureDimension3D`), and draws every frame through one trilinear fetch. A LUT is baked again only
|
|
34
|
+
when the operator, the resolution or, for HDR, the display's peak (`tone_mapper.display.peak_nits`) changes. A
|
|
35
|
+
LUT maps the PQ signal of exposed scene-linear Rec.709 to the PQ signal of linear Rec.2020 display light, 1 at
|
|
36
|
+
the paper white on both sides; scene colour past 10000 cd/m² (49.3 × SDR white) clamps there, as Unreal's does.
|
|
37
|
+
- **Added:** `ToneMapOperator` (a `CodeChunk` defining `tone_map_operator(scene, peak_nits)`, plus `declare`
|
|
38
|
+
and `bind` for bindings of its own), and the built-ins `TONE_MAP_OPERATOR_ACES` (the default),
|
|
39
|
+
`TONE_MAP_OPERATOR_GT7`, `TONE_MAP_OPERATOR_PBR_NEUTRAL` and `TONE_MAP_OPERATOR_NONE`, unchanged in what
|
|
40
|
+
they compute.
|
|
41
|
+
- **Added:** user LUTs: `set_lut_sdr(resolution, data)`, `set_lut_hdr(resolution, data, peak_nits)`,
|
|
42
|
+
`clear_lut_sdr()`, `clear_lut_hdr()`, and `build_lut_sdr_from_hdr()`, which maps the HDR LUT down to the paper
|
|
43
|
+
white through the BT.2390 EETF on the GPU, keeping hue. `chunk_bt2390_eetf` and `chunk_tonemap_lut`.
|
|
44
|
+
- **Changed:** the ACES HDR pass cost 51–68 µs at 1258 × 646 on an RTX 4090 and now costs 7–12 µs; SDR 11–22 µs,
|
|
45
|
+
now 9–10 µs. A bake costs 7 µs at 32³ (ACES HDR, both ACES 2.0 transforms per texel), 20 µs at 64³. At 32³ the
|
|
46
|
+
picture moves by a mean of +0.13 8-bit codes on SDR, under the frame-to-frame noise of a live scene.
|
|
47
|
+
- **Breaking:** `renderer.tone_mapping_mode` and `ShadeToneMappingMode` are removed. Set
|
|
48
|
+
`renderer.tone_mapper.operator` to one of the built-in operators instead.
|
|
49
|
+
- **Breaking:** the eight `shader_tonemap_{LDR,HDR}[_aces|_none|_pbr_neutral]` passes are removed, replaced by
|
|
50
|
+
`shader_tonemap_LDR_lut` and `shader_tonemap_HDR_lut`. `chunk_tonemap_hdr_bt2390` is removed;
|
|
51
|
+
`chunk_bt2390_eetf` is the EETF itself. `TonemapDisplaySettings` keeps only the Rec.2020 columns, and
|
|
52
|
+
`TONEMAP_SETTINGS_REC709`, `TONEMAP_SETTINGS_REC709_PEAK`, `TONEMAP_SETTINGS_REC2020` and
|
|
53
|
+
`TONEMAP_SETTINGS_REC2020_PEAK` become `TONEMAP_SETTINGS`. `TonemapAces2Tables` holds the tables only; the
|
|
54
|
+
operator uploads them when it bakes.
|
|
55
|
+
|
|
5
56
|
### Outlines: a spec per entity, drawn where the entity is hidden too
|
|
6
57
|
|
|
7
58
|
- **Added:** `Outline` (`visible`, `hidden`, each an `OutlineSpec`, by default the frozen `OutlineSpec.NONE`, which
|
package/package.json
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The von Kries adaptation in Bradford cone space that takes the `source` white to the `destination` white, as a
|
|
3
|
+
* matrix on CIE XYZ. Row-major. A colour seen under the source white maps to the colour that looks the same under the
|
|
4
|
+
* destination white.
|
|
5
|
+
*
|
|
6
|
+
* @param {Float64Array|number[]} out 9 elements, row-major
|
|
7
|
+
* @param {number} source_x chromaticity of the source white
|
|
8
|
+
* @param {number} source_y
|
|
9
|
+
* @param {number} destination_x chromaticity of the destination white
|
|
10
|
+
* @param {number} destination_y
|
|
11
|
+
* @see http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
|
|
12
|
+
*/
|
|
13
|
+
export function m3_chromatic_adaptation_bradford(out: Float64Array | number[], source_x: number, source_y: number, destination_x: number, destination_y: number): void;
|
|
14
|
+
//# sourceMappingURL=m3_chromatic_adaptation_bradford.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"m3_chromatic_adaptation_bradford.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/xyz/m3_chromatic_adaptation_bradford.js"],"names":[],"mappings":"AAkBA;;;;;;;;;;;GAWG;AACH,sDAPW,YAAY,GAAC,MAAM,EAAE,YACrB,MAAM,YACN,MAAM,iBACN,MAAM,iBACN,MAAM,QAuBhB"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { m3_invert } from "../../geom/mat3/m3_invert.js";
|
|
2
|
+
import { m3_multiply } from "../../geom/mat3/m3_multiply.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Bradford cone response, XYZ to LMS. Row-major.
|
|
6
|
+
* @type {number[]}
|
|
7
|
+
*/
|
|
8
|
+
const BRADFORD = [
|
|
9
|
+
0.8951, 0.2664, -0.1614,
|
|
10
|
+
-0.7502, 1.7135, 0.0367,
|
|
11
|
+
0.0389, -0.0685, 1.0296,
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const BRADFORD_INVERSE = new Float64Array(9);
|
|
15
|
+
m3_invert(BRADFORD_INVERSE, BRADFORD);
|
|
16
|
+
|
|
17
|
+
const scratch = new Float64Array(9);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The von Kries adaptation in Bradford cone space that takes the `source` white to the `destination` white, as a
|
|
21
|
+
* matrix on CIE XYZ. Row-major. A colour seen under the source white maps to the colour that looks the same under the
|
|
22
|
+
* destination white.
|
|
23
|
+
*
|
|
24
|
+
* @param {Float64Array|number[]} out 9 elements, row-major
|
|
25
|
+
* @param {number} source_x chromaticity of the source white
|
|
26
|
+
* @param {number} source_y
|
|
27
|
+
* @param {number} destination_x chromaticity of the destination white
|
|
28
|
+
* @param {number} destination_y
|
|
29
|
+
* @see http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
|
|
30
|
+
*/
|
|
31
|
+
export function m3_chromatic_adaptation_bradford(out, source_x, source_y, destination_x, destination_y) {
|
|
32
|
+
// each white's cone response, at Y = 1
|
|
33
|
+
const sX = source_x / source_y;
|
|
34
|
+
const sZ = (1 - source_x - source_y) / source_y;
|
|
35
|
+
const dX = destination_x / destination_y;
|
|
36
|
+
const dZ = (1 - destination_x - destination_y) / destination_y;
|
|
37
|
+
|
|
38
|
+
for (let row = 0; row < 3; row++) {
|
|
39
|
+
const r0 = BRADFORD[row * 3];
|
|
40
|
+
const r1 = BRADFORD[row * 3 + 1];
|
|
41
|
+
const r2 = BRADFORD[row * 3 + 2];
|
|
42
|
+
|
|
43
|
+
const gain = (r0 * dX + r1 + r2 * dZ) / (r0 * sX + r1 + r2 * sZ);
|
|
44
|
+
|
|
45
|
+
scratch[row * 3] = r0 * gain;
|
|
46
|
+
scratch[row * 3 + 1] = r1 * gain;
|
|
47
|
+
scratch[row * 3 + 2] = r2 * gain;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
m3_multiply(out, BRADFORD_INVERSE, scratch);
|
|
51
|
+
}
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Only the upper triangle of `m` is read (the matrix is assumed symmetric);
|
|
5
5
|
* the input is not modified. Eigenpairs are emitted sorted by **ascending
|
|
6
6
|
* eigenvalue**, so index 0 is the smallest — convenient for proxy-plane fits,
|
|
7
|
-
* where the plane normal is the eigenvector of the smallest variance.
|
|
7
|
+
* where the plane normal is the eigenvector of the smallest variance. Equal
|
|
8
|
+
* eigenvalues keep their column order.
|
|
8
9
|
*
|
|
9
10
|
* Eigenvector sign is arbitrary (an eigenvector and its negation are both
|
|
10
11
|
* valid); callers that need a consistent orientation must fix the sign
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matrix_symmetric_3x3_eigen.d.ts","sourceRoot":"","sources":["../../../../../../src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"matrix_symmetric_3x3_eigen.d.ts","sourceRoot":"","sources":["../../../../../../src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.js"],"names":[],"mappings":"AA4BA;;;;;;;;;;;;;;;;;GAiBG;AACH,uDALW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,eAClC,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,KAElC,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,QAqD5C"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { matrix_symmetric_jacobi_rotate_in_place } from "./matrix_symmetric_jacobi_rotate_in_place.js";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Maximum number of cyclic Jacobi sweeps. A symmetric 3x3 reaches full double
|
|
3
5
|
* precision in ~5-6 sweeps (Jacobi converges quadratically); 50 is a generous
|
|
@@ -7,58 +9,22 @@
|
|
|
7
9
|
const MAX_SWEEPS = 50;
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* `a` is the symmetric working matrix; `v` accumulates the rotations so its
|
|
13
|
-
* columns become the eigenvectors.
|
|
14
|
-
*
|
|
15
|
-
* @param {number[]} a symmetric 3x3, mutated in place
|
|
16
|
-
* @param {number[]} v 3x3 rotation accumulator, mutated in place
|
|
17
|
-
* @param {number} p
|
|
18
|
-
* @param {number} q
|
|
12
|
+
* Working copy of the input, row-major (index = row*3 + col).
|
|
13
|
+
* @type {Float64Array}
|
|
19
14
|
*/
|
|
20
|
-
|
|
21
|
-
const apq = a[p * 3 + q];
|
|
22
|
-
|
|
23
|
-
if (apq === 0) {
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const app = a[p * 3 + p];
|
|
28
|
-
const aqq = a[q * 3 + q];
|
|
29
|
-
|
|
30
|
-
// tan of the rotation angle (Numerical Recipes form, |angle| <= pi/4).
|
|
31
|
-
const theta = (aqq - app) / (2 * apq);
|
|
32
|
-
const t = (theta >= 0)
|
|
33
|
-
? 1 / (theta + Math.sqrt(theta * theta + 1))
|
|
34
|
-
: -1 / (-theta + Math.sqrt(theta * theta + 1));
|
|
35
|
-
const c = 1 / Math.sqrt(t * t + 1);
|
|
36
|
-
const s = t * c;
|
|
37
|
-
|
|
38
|
-
// The third (untouched) index.
|
|
39
|
-
const r = 3 - p - q;
|
|
40
|
-
const arp = a[r * 3 + p];
|
|
41
|
-
const arq = a[r * 3 + q];
|
|
15
|
+
const scratch_a = new Float64Array(9);
|
|
42
16
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const new_rp = c * arp - s * arq;
|
|
49
|
-
const new_rq = s * arp + c * arq;
|
|
50
|
-
a[r * 3 + p] = new_rp;
|
|
51
|
-
a[p * 3 + r] = new_rp;
|
|
52
|
-
a[r * 3 + q] = new_rq;
|
|
53
|
-
a[q * 3 + r] = new_rq;
|
|
17
|
+
/**
|
|
18
|
+
* Rotation accumulator, row-major; its columns become the eigenvectors.
|
|
19
|
+
* @type {Float64Array}
|
|
20
|
+
*/
|
|
21
|
+
const scratch_v = new Float64Array(9);
|
|
54
22
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
}
|
|
23
|
+
/**
|
|
24
|
+
* Column index of each eigenpair, sorted by ascending eigenvalue.
|
|
25
|
+
* @type {Uint8Array}
|
|
26
|
+
*/
|
|
27
|
+
const scratch_order = new Uint8Array(3);
|
|
62
28
|
|
|
63
29
|
/**
|
|
64
30
|
* Eigendecomposition of a symmetric 3x3 matrix via cyclic Jacobi rotations.
|
|
@@ -66,7 +32,8 @@ function jacobi_rotate(a, v, p, q) {
|
|
|
66
32
|
* Only the upper triangle of `m` is read (the matrix is assumed symmetric);
|
|
67
33
|
* the input is not modified. Eigenpairs are emitted sorted by **ascending
|
|
68
34
|
* eigenvalue**, so index 0 is the smallest — convenient for proxy-plane fits,
|
|
69
|
-
* where the plane normal is the eigenvector of the smallest variance.
|
|
35
|
+
* where the plane normal is the eigenvector of the smallest variance. Equal
|
|
36
|
+
* eigenvalues keep their column order.
|
|
70
37
|
*
|
|
71
38
|
* Eigenvector sign is arbitrary (an eigenvector and its negation are both
|
|
72
39
|
* valid); callers that need a consistent orientation must fix the sign
|
|
@@ -78,16 +45,19 @@ function jacobi_rotate(a, v, p, q) {
|
|
|
78
45
|
* @param {Float64Array|Float32Array|number[]} m symmetric 3x3, row-major (index = row*3 + col)
|
|
79
46
|
*/
|
|
80
47
|
export function matrix_symmetric_3x3_eigen(out_values, out_vectors, m) {
|
|
81
|
-
const a =
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
48
|
+
const a = scratch_a;
|
|
49
|
+
const v = scratch_v;
|
|
50
|
+
|
|
51
|
+
for (let row = 0; row < 3; row++) {
|
|
52
|
+
for (let col = row; col < 3; col++) {
|
|
53
|
+
const value = m[row * 3 + col];
|
|
54
|
+
a[row * 3 + col] = value;
|
|
55
|
+
a[col * 3 + row] = value;
|
|
56
|
+
|
|
57
|
+
v[row * 3 + col] = row === col ? 1 : 0;
|
|
58
|
+
v[col * 3 + row] = row === col ? 1 : 0;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
91
61
|
|
|
92
62
|
for (let sweep = 0; sweep < MAX_SWEEPS; sweep++) {
|
|
93
63
|
const scale = Math.abs(a[0]) + Math.abs(a[4]) + Math.abs(a[8]);
|
|
@@ -97,21 +67,32 @@ export function matrix_symmetric_3x3_eigen(out_values, out_vectors, m) {
|
|
|
97
67
|
break;
|
|
98
68
|
}
|
|
99
69
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
70
|
+
matrix_symmetric_jacobi_rotate_in_place(a, v, 0, 1, 3);
|
|
71
|
+
matrix_symmetric_jacobi_rotate_in_place(a, v, 0, 2, 3);
|
|
72
|
+
matrix_symmetric_jacobi_rotate_in_place(a, v, 1, 2, 3);
|
|
103
73
|
}
|
|
104
74
|
|
|
105
75
|
// Eigenvalues live on the diagonal; eigenvector k is column k of V.
|
|
106
|
-
|
|
107
|
-
const order =
|
|
108
|
-
|
|
76
|
+
// Stable insertion sort of the three column indices by eigenvalue.
|
|
77
|
+
const order = scratch_order;
|
|
78
|
+
|
|
79
|
+
for (let k = 0; k < 3; k++) {
|
|
80
|
+
const value = a[k * 4];
|
|
81
|
+
let slot = k;
|
|
82
|
+
|
|
83
|
+
while (slot > 0 && a[order[slot - 1] * 4] > value) {
|
|
84
|
+
order[slot] = order[slot - 1];
|
|
85
|
+
slot--;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
order[slot] = k;
|
|
89
|
+
}
|
|
109
90
|
|
|
110
91
|
for (let k = 0; k < 3; k++) {
|
|
111
92
|
const col = order[k];
|
|
112
|
-
out_values[k] =
|
|
113
|
-
out_vectors[k * 3
|
|
114
|
-
out_vectors[k * 3 + 1] = v[
|
|
115
|
-
out_vectors[k * 3 + 2] = v[
|
|
93
|
+
out_values[k] = a[col * 4];
|
|
94
|
+
out_vectors[k * 3] = v[col];
|
|
95
|
+
out_vectors[k * 3 + 1] = v[3 + col];
|
|
96
|
+
out_vectors[k * 3 + 2] = v[6 + col];
|
|
116
97
|
}
|
|
117
98
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matrix_symmetric_4x4_eigen.d.ts","sourceRoot":"","sources":["../../../../../../src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"matrix_symmetric_4x4_eigen.d.ts","sourceRoot":"","sources":["../../../../../../src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.js"],"names":[],"mappings":"AA8BA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,uDALW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,eAClC,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,KAElC,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,QA0D5C"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { matrix_symmetric_jacobi_rotate_in_place } from "./matrix_symmetric_jacobi_rotate_in_place.js";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Maximum number of cyclic Jacobi sweeps. A symmetric 4x4 reaches full double
|
|
3
5
|
* precision in 3-6 sweeps (Jacobi converges quadratically, whatever the gaps
|
|
@@ -26,64 +28,6 @@ const scratch_v = new Float64Array(16);
|
|
|
26
28
|
*/
|
|
27
29
|
const scratch_order = new Uint8Array(4);
|
|
28
30
|
|
|
29
|
-
/**
|
|
30
|
-
* One Jacobi rotation in the (p, q) plane that zeroes the off-diagonal entry
|
|
31
|
-
* a[p][q]. `a` and `v` are 4x4 matrices stored row-major (index = row*4 + col).
|
|
32
|
-
* `a` is the symmetric working matrix; `v` accumulates the rotations so its
|
|
33
|
-
* columns become the eigenvectors.
|
|
34
|
-
*
|
|
35
|
-
* @param {Float64Array} a symmetric 4x4, mutated in place
|
|
36
|
-
* @param {Float64Array} v 4x4 rotation accumulator, mutated in place
|
|
37
|
-
* @param {number} p
|
|
38
|
-
* @param {number} q
|
|
39
|
-
*/
|
|
40
|
-
function jacobi_rotate(a, v, p, q) {
|
|
41
|
-
const apq = a[p * 4 + q];
|
|
42
|
-
|
|
43
|
-
if (apq === 0) {
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const app = a[p * 4 + p];
|
|
48
|
-
const aqq = a[q * 4 + q];
|
|
49
|
-
|
|
50
|
-
// tan of the rotation angle (Numerical Recipes form, |angle| <= pi/4).
|
|
51
|
-
const theta = (aqq - app) / (2 * apq);
|
|
52
|
-
const t = (theta >= 0)
|
|
53
|
-
? 1 / (theta + Math.sqrt(theta * theta + 1))
|
|
54
|
-
: -1 / (-theta + Math.sqrt(theta * theta + 1));
|
|
55
|
-
const c = 1 / Math.sqrt(t * t + 1);
|
|
56
|
-
const s = t * c;
|
|
57
|
-
|
|
58
|
-
a[p * 4 + p] = app - t * apq;
|
|
59
|
-
a[q * 4 + q] = aqq + t * apq;
|
|
60
|
-
a[p * 4 + q] = 0;
|
|
61
|
-
a[q * 4 + p] = 0;
|
|
62
|
-
|
|
63
|
-
for (let r = 0; r < 4; r++) {
|
|
64
|
-
if (r === p || r === q) {
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const arp = a[r * 4 + p];
|
|
69
|
-
const arq = a[r * 4 + q];
|
|
70
|
-
|
|
71
|
-
const new_rp = c * arp - s * arq;
|
|
72
|
-
const new_rq = s * arp + c * arq;
|
|
73
|
-
a[r * 4 + p] = new_rp;
|
|
74
|
-
a[p * 4 + r] = new_rp;
|
|
75
|
-
a[r * 4 + q] = new_rq;
|
|
76
|
-
a[q * 4 + r] = new_rq;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
for (let row = 0; row < 4; row++) {
|
|
80
|
-
const vrp = v[row * 4 + p];
|
|
81
|
-
const vrq = v[row * 4 + q];
|
|
82
|
-
v[row * 4 + p] = c * vrp - s * vrq;
|
|
83
|
-
v[row * 4 + q] = s * vrp + c * vrq;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
31
|
/**
|
|
88
32
|
* Eigendecomposition of a symmetric 4x4 matrix via cyclic Jacobi rotations.
|
|
89
33
|
*
|
|
@@ -131,12 +75,12 @@ export function matrix_symmetric_4x4_eigen(out_values, out_vectors, m) {
|
|
|
131
75
|
break;
|
|
132
76
|
}
|
|
133
77
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
78
|
+
matrix_symmetric_jacobi_rotate_in_place(a, v, 0, 1, 4);
|
|
79
|
+
matrix_symmetric_jacobi_rotate_in_place(a, v, 0, 2, 4);
|
|
80
|
+
matrix_symmetric_jacobi_rotate_in_place(a, v, 0, 3, 4);
|
|
81
|
+
matrix_symmetric_jacobi_rotate_in_place(a, v, 1, 2, 4);
|
|
82
|
+
matrix_symmetric_jacobi_rotate_in_place(a, v, 1, 3, 4);
|
|
83
|
+
matrix_symmetric_jacobi_rotate_in_place(a, v, 2, 3, 4);
|
|
140
84
|
}
|
|
141
85
|
|
|
142
86
|
// Eigenvalues live on the diagonal; eigenvector k is column k of V.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One Jacobi rotation in the (p, q) plane that zeroes the off-diagonal entry
|
|
3
|
+
* a[p][q]. `a` and `v` are d x d matrices stored row-major (index = row*d + col).
|
|
4
|
+
* `a` is the symmetric working matrix; `v` accumulates the rotations so its
|
|
5
|
+
* columns become the eigenvectors.
|
|
6
|
+
*
|
|
7
|
+
* Callers pass `d` as a literal from an unrolled sweep, so the index arithmetic
|
|
8
|
+
* folds once this is inlined.
|
|
9
|
+
*
|
|
10
|
+
* @param {Float64Array|number[]} a symmetric d x d, mutated in place
|
|
11
|
+
* @param {Float64Array|number[]} v d x d rotation accumulator, mutated in place
|
|
12
|
+
* @param {number} p row of the entry to zero, p < q
|
|
13
|
+
* @param {number} q column of the entry to zero
|
|
14
|
+
* @param {number} d dimension of the square matrices
|
|
15
|
+
*/
|
|
16
|
+
export function matrix_symmetric_jacobi_rotate_in_place(a: Float64Array | number[], v: Float64Array | number[], p: number, q: number, d: number): void;
|
|
17
|
+
//# sourceMappingURL=matrix_symmetric_jacobi_rotate_in_place.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matrix_symmetric_jacobi_rotate_in_place.d.ts","sourceRoot":"","sources":["../../../../../../src/core/math/linalg/eigen/matrix_symmetric_jacobi_rotate_in_place.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,2DANW,YAAY,GAAC,MAAM,EAAE,KACrB,YAAY,GAAC,MAAM,EAAE,KACrB,MAAM,KACN,MAAM,KACN,MAAM,QAkDhB"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One Jacobi rotation in the (p, q) plane that zeroes the off-diagonal entry
|
|
3
|
+
* a[p][q]. `a` and `v` are d x d matrices stored row-major (index = row*d + col).
|
|
4
|
+
* `a` is the symmetric working matrix; `v` accumulates the rotations so its
|
|
5
|
+
* columns become the eigenvectors.
|
|
6
|
+
*
|
|
7
|
+
* Callers pass `d` as a literal from an unrolled sweep, so the index arithmetic
|
|
8
|
+
* folds once this is inlined.
|
|
9
|
+
*
|
|
10
|
+
* @param {Float64Array|number[]} a symmetric d x d, mutated in place
|
|
11
|
+
* @param {Float64Array|number[]} v d x d rotation accumulator, mutated in place
|
|
12
|
+
* @param {number} p row of the entry to zero, p < q
|
|
13
|
+
* @param {number} q column of the entry to zero
|
|
14
|
+
* @param {number} d dimension of the square matrices
|
|
15
|
+
*/
|
|
16
|
+
export function matrix_symmetric_jacobi_rotate_in_place(a, v, p, q, d) {
|
|
17
|
+
const pd = p * d;
|
|
18
|
+
const qd = q * d;
|
|
19
|
+
const apq = a[pd + q];
|
|
20
|
+
|
|
21
|
+
if (apq === 0) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const app = a[pd + p];
|
|
26
|
+
const aqq = a[qd + q];
|
|
27
|
+
|
|
28
|
+
// tan of the rotation angle (Numerical Recipes form, |angle| <= pi/4).
|
|
29
|
+
const theta = (aqq - app) / (2 * apq);
|
|
30
|
+
const t = (theta >= 0)
|
|
31
|
+
? 1 / (theta + Math.sqrt(theta * theta + 1))
|
|
32
|
+
: -1 / (-theta + Math.sqrt(theta * theta + 1));
|
|
33
|
+
const c = 1 / Math.sqrt(t * t + 1);
|
|
34
|
+
const s = t * c;
|
|
35
|
+
|
|
36
|
+
a[pd + p] = app - t * apq;
|
|
37
|
+
a[qd + q] = aqq + t * apq;
|
|
38
|
+
a[pd + q] = 0;
|
|
39
|
+
a[qd + p] = 0;
|
|
40
|
+
|
|
41
|
+
for (let r = 0; r < d; r++) {
|
|
42
|
+
if (r === p || r === q) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const rd = r * d;
|
|
47
|
+
const arp = a[rd + p];
|
|
48
|
+
const arq = a[rd + q];
|
|
49
|
+
|
|
50
|
+
const new_rp = c * arp - s * arq;
|
|
51
|
+
const new_rq = s * arp + c * arq;
|
|
52
|
+
a[rd + p] = new_rp;
|
|
53
|
+
a[pd + r] = new_rp;
|
|
54
|
+
a[rd + q] = new_rq;
|
|
55
|
+
a[qd + r] = new_rq;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
for (let rd = 0; rd < d * d; rd += d) {
|
|
59
|
+
const vrp = v[rd + p];
|
|
60
|
+
const vrq = v[rd + q];
|
|
61
|
+
v[rd + p] = c * vrp - s * vrq;
|
|
62
|
+
v[rd + q] = s * vrp + c * vrq;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Solve the bound-constrained quadratic program
|
|
3
|
+
*
|
|
4
|
+
* minimise ½·xᵀ·A·x − bᵀ·x subject to lo ≤ x ≤ hi
|
|
5
|
+
*
|
|
6
|
+
* for a symmetric positive-definite `A`; equivalently the box LCP: `x` within `[lo, hi]` where
|
|
7
|
+
* `w = A·x − b` is zero for every `x_i` strictly between its bounds, non-negative where `x_i = lo_i`
|
|
8
|
+
* and non-positive where `x_i = hi_i`. The solution is unique.
|
|
9
|
+
*
|
|
10
|
+
* Primal active-set method (Nocedal & Wright, *Numerical Optimization*, 2nd ed., §16.5). It starts
|
|
11
|
+
* from the point of the box nearest the origin, with every variable free. Each pass solves for the
|
|
12
|
+
* free variables with the held ones at their bounds, and steps toward that solution as far as the box
|
|
13
|
+
* allows; a variable that cuts the step short is held at the bound it reached. A full step is the
|
|
14
|
+
* minimum over the variables currently free: then the held variable whose `w` has the wrong sign by
|
|
15
|
+
* the most is freed, or, when none has, `x` is the solution. The objective falls from each such
|
|
16
|
+
* minimum to the next, so no set of held variables repeats and the search ends; it also ends where
|
|
17
|
+
* rounding stops the objective falling. When no bound is reached it is one factorisation of `A`.
|
|
18
|
+
*
|
|
19
|
+
* @param {ArrayLike<number>} A n×n, column-major (`A[j·n + i]` is row `i`, column `j`); being symmetric,
|
|
20
|
+
* row-major reads the same. Not modified.
|
|
21
|
+
* @param {ArrayLike<number>} b length n
|
|
22
|
+
* @param {ArrayLike<number>} lo lower bounds, length n; `-Infinity` where there is none
|
|
23
|
+
* @param {ArrayLike<number>} hi upper bounds, length n, none below its `lo`; `Infinity` where there is none
|
|
24
|
+
* @param {Float64Array|number[]} x receives the solution, length n
|
|
25
|
+
* @param {number} n
|
|
26
|
+
* @returns {boolean} true when solved; false when `A` did not factor as positive definite, `x` then
|
|
27
|
+
* holding the last point reached, within the bounds
|
|
28
|
+
*/
|
|
29
|
+
export function solve_box_constrained_qp(A: ArrayLike<number>, b: ArrayLike<number>, lo: ArrayLike<number>, hi: ArrayLike<number>, x: Float64Array | number[], n: number): boolean;
|
|
30
|
+
//# sourceMappingURL=solve_box_constrained_qp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solve_box_constrained_qp.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/linalg/solve_box_constrained_qp.js"],"names":[],"mappings":"AAiBA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,4CAVW,UAAU,MAAM,CAAC,KAEjB,UAAU,MAAM,CAAC,MACjB,UAAU,MAAM,CAAC,MACjB,UAAU,MAAM,CAAC,KACjB,YAAY,GAAC,MAAM,EAAE,KACrB,MAAM,GACJ,OAAO,CAkKnB"}
|