diff --git a/ROADMAP.md b/ROADMAP.md index eb127b3..931fd75 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -102,19 +102,40 @@ - [x] Raycasting utilities - [ ] Bounding volume hierarchy (BVH) builder **Data structures** - - [ ] Binary heap priority queue + - [x] Binary heap priority queue - [x] Disjoint set union (union-find) - - [ ] Bloom filter probabilistic membership - - [ ] Skip list sorted structure - - [ ] Segment tree range query helper + - [x] Bloom filter probabilistic membership + - [x] Skip list sorted structure + - [x] Segment tree range query helper **Compression & encoding** - - [ ] Run-length encoding (RLE) + - [x] Run-length encoding (RLE) - [ ] Huffman coding utilities - [ ] LZ77 dictionary compression helper - - [ ] Base64 encode/decode utilities + - [x] Base64 encode/decode utilities **Geometric & numeric utilities** - [ ] Closest pair of points solver for geometry toolkit +## Milestone 0.6.0 – Fold Barrier Physics Suite (Planned) +- [ ] Align Fold barrier scope with the paper and define shared constraint interfaces in `src/physics/fold` +- **Barrier primitives** (each item: runtime module + `docs/index.d.ts` entry + Vitest coverage + runnable example when feasible) + - [ ] Cubic barrier potential (energy, gradient, Hessian evaluation) + - [ ] Stiffness design principle for frozen barrier stiffness + - [ ] Contact barrier with extended direction handling + - [ ] Pin constraint barrier using cubic barrier formulation + - [ ] Wall constraint barrier for plane collisions + - [ ] Triangle strain-limiting barrier driven by deformation singular values +- **Integrator and solver** + - [ ] Inexact Newton integrator with beta accumulation + - [ ] Constraint-only line search with extended direction scaling + - [ ] Semi-implicit freeze schedule for barrier stiffness updates + - [ ] Error-reduction pass leveraging beta-delta time refinement + - [ ] Linear solver pipeline (PCG with 3x3 block-Jacobi preconditioner) +- **Contact and friction infrastructure** + - [ ] Friction potential tied to contact force magnitude + - [ ] Matrix assembly with cached contact index tables + - [ ] Gap evaluators for point/triangle, edge/edge, and wall constraints + - [ ] SPD enforcement pass for elasticity Hessian blocks + ### LLM‑Optimised Additions (Priority Rationale) These items offer the largest context and correctness savings for LLM users. Prioritize when bandwidth is limited: diff --git a/docs/fold_algorithm_list.md b/docs/fold_algorithm_list.md new file mode 100644 index 0000000..d4752c7 --- /dev/null +++ b/docs/fold_algorithm_list.md @@ -0,0 +1,120 @@ +# Full List of Algorithms from the Paper (Implementation Reference) + +This document lists all distinct algorithms and subroutines described in the research paper “Fold: A Dynamic Barrier Method for Robust Contact and Strain Limiting.” +Each algorithm is designed to be implemented independently in TypeScript (or another language) to reduce context dependency during code generation by an LLM. + +--- + +## 1. Cubic Barrier Potential +**Purpose:** Penetration-free inequality constraint, \(C^2\) continuous. +**Inputs:** gap \(g_i\), max gap \(\hat g_i\), frozen stiffness \(ar\kappa_i\). +**Output:** energy, gradient, Hessian. + +--- + +## 2. Stiffness Design Principle (Semi-Implicit, Elasticity-Inclusive) +**Purpose:** Compute frozen barrier stiffness. +**Formula:** \(ar\kappa = m/g^2 + \mathbf n \cdot (H \mathbf n)\). + +--- + +## 3. Contact Barrier & Extended Direction +**Purpose:** Handle point-triangle or edge-edge contact. +**Key:** Use extended direction \( \mathbf w_i = W_i^T (\mathbf p_i - \mathbf q_i) \). + +--- + +## 4. Pin (Point) Constraint Barrier +**Purpose:** Soft pinning using cubic barrier. +**Formula:** \( ar\kappa^{pin} = m/g^2 + \hat{w}^T H_{ii} \hat{w} \). + +--- + +## 5. Wall Constraint Barrier +**Purpose:** Apply wall or plane constraints using same cubic barrier scheme. +**Formula:** \( ar\kappa^{wall} = m/g^2 + n_{wall}^T H_{ii} n_{wall} \). + +--- + +## 6. Strain-Limiting Barrier (Triangle-Wise) +**Purpose:** Maintain deformation limits via singular values of the deformation gradient. +**Formula:** \( ar\kappa^{SL} = m_{face}/gap^2 + w_r^T H_{9x9} w_r \). + +--- + +## 7. Time Integration: Inexact Newton with β-Accumulation +**Purpose:** Main integrator (Algorithm 1). +**Process:** +1. Outer loop accumulates β. +2. Inner step solves \( H d = f \). +3. Constraint-only line search with 1.25× extended direction. +4. Final error-reduction pass using βΔt. + +--- + +## 8. Constraint-Only Line Search +**Purpose:** Feasibility-only backtracking search to find α ensuring \( g(x+1.25αd) ≤ \hat g \). + +--- + +## 9. Friction Potential (Optional) +**Purpose:** Tangential displacement penalty with stiffness tied to contact force. +**Formula:** \( ar\kappa^{fric} = μ f_{contact} / \max(ε, ||P_i W_i(x - x_{prev})||) \). + +--- + +## 10. Matrix Assembly with Cached Contact Index Tables +**Purpose:** Explicit assembly with CAMA-style caching to avoid duplicate fill-ins. +**Tiers:** +1. Block-diagonal +2. Mesh-fixed matrix +3. Contact matrix + +--- + +## 11. Linear Solver & Preconditioning +**Purpose:** Solve \( H d = f \). +**Method:** PCG with 3×3 block-Jacobi preconditioner. + +--- + +## 12. Gap Evaluators (Geometry Module) +**Purpose:** Compute geometric gaps and fixed normals for all constraint types. + +--- + +## 13. Semi-Implicit Freeze Schedule +**Purpose:** Refresh \(ar\kappa\) each Newton step, then keep frozen for derivative evaluation. + +--- + +## 14. Error-Reduction Pass +**Purpose:** Final Newton pass using βΔt to reduce integration error. + +--- + +## 15. SPD Enforcement for Elasticity Hessian +**Purpose:** Project local Hessians to SPD to ensure stable solves. + +--- + +### Dependency Map +| Category | Depends on | +|-----------|-------------| +| Barriers (1) | Stiffness (2–6), Gaps (12) | +| Integrator (7–8,14) | Barriers, Assembly (10), Solver (11), Freeze (13), Gaps (12) | +| Friction (9) | Contact forces from (3) | +| Assembly (10) | Independent infrastructure | +| Solver (11) | Infrastructure | + +--- + +### Implementation Notes +- Always **freeze** \(ar\kappa\) within each Newton step. +- Use **unit tests** to ensure gradients/Hessians match finite differences. +- Implement constraints (contact, pin, wall, strain) as subclasses of a common BarrierConstraint interface. +- Strain limiting is the mathematically hardest; friction and caching are engineering-heavy but modular. + +--- + +**End of File** \ No newline at end of file diff --git a/docs/index.d.ts b/docs/index.d.ts index 839a3e8..a86721a 100644 --- a/docs/index.d.ts +++ b/docs/index.d.ts @@ -103,6 +103,8 @@ export const examples: { readonly SkipList: 'examples/skipList.ts'; readonly runLengthEncode: 'examples/rle.ts'; readonly runLengthDecode: 'examples/rle.ts'; + readonly base64Encode: 'examples/base64.ts'; + readonly base64Decode: 'examples/base64.ts'; }; readonly performance: { readonly debounce: 'examples/requestDedup.ts'; @@ -3009,6 +3011,14 @@ export interface RlePair { char: string; count: number } export function runLengthEncode(input: string): RlePair[]; export function runLengthDecode(pairs: ReadonlyArray): string; +/** + * Base64 encode/decode utilities (UTF-8 strings and bytes). + * Use for: compact textual transport, data URIs, wire formats. + * Import: data/base64.ts + */ +export function base64Encode(input: string | Uint8Array): string; +export function base64Decode(b64: string): Uint8Array; + /** * Disjoint Set Union (Union-Find) with path compression and union by size. * Use for: connectivity queries, Kruskal MST, clustering. diff --git a/examples/base64.ts b/examples/base64.ts new file mode 100644 index 0000000..7f0a0f0 --- /dev/null +++ b/examples/base64.ts @@ -0,0 +1,7 @@ +import { base64Encode, base64Decode } from '../src/index.js'; + +const s = 'Hello, 世界! 🎉'; +const b64 = base64Encode(s); +console.log('b64:', b64); +console.log('utf8:', new TextDecoder().decode(base64Decode(b64))); + diff --git a/src/data/base64.ts b/src/data/base64.ts new file mode 100644 index 0000000..49f9e44 --- /dev/null +++ b/src/data/base64.ts @@ -0,0 +1,41 @@ +/** + * Base64 encode/decode utilities (UTF-8 strings and bytes). + */ +export function base64Encode(input: string | Uint8Array): string { + if (typeof input === 'string') { + const bytes = new TextEncoder().encode(input); + return encodeBytes(bytes); + } + return encodeBytes(input); +} + +export function base64Decode(b64: string): Uint8Array { + return decodeToBytes(b64); +} + +function encodeBytes(bytes: Uint8Array): string { + if (typeof Buffer !== 'undefined') { + // Node + // eslint-disable-next-line no-undef + return Buffer.from(bytes).toString('base64'); + } + // Browser + let binary = ''; + for (let i = 0; i < bytes.length; i += 1) binary += String.fromCharCode(bytes[i]); + const g = globalThis as unknown as { btoa?: (s: string) => string }; + if (!g.btoa) throw new Error('Base64 encode not available in this environment'); + return g.btoa(binary); +} + +function decodeToBytes(b64: string): Uint8Array { + if (typeof Buffer !== 'undefined') { + // eslint-disable-next-line no-undef + return new Uint8Array(Buffer.from(b64, 'base64')); + } + const g = globalThis as unknown as { atob?: (s: string) => string }; + if (!g.atob) throw new Error('Base64 decode not available in this environment'); + const binary: string = g.atob(b64); + const out = new Uint8Array(binary.length); + for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i); + return out; +} diff --git a/src/index.ts b/src/index.ts index 4ca3fd9..592918b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -101,6 +101,8 @@ export const examples = { SkipList: 'examples/skipList.ts', runLengthEncode: 'examples/rle.ts', runLengthDecode: 'examples/rle.ts', + base64Encode: 'examples/base64.ts', + base64Decode: 'examples/base64.ts', }, performance: { debounce: 'examples/requestDedup.ts', @@ -1052,6 +1054,12 @@ export { SkipList } from './data/skipList.js'; * Example file: examples/rle.ts */ export { runLengthEncode, runLengthDecode } from './data/rle.js'; +/** + * Base64 encode/decode helpers for strings and bytes. + * + * Example file: examples/base64.ts + */ +export { base64Encode, base64Decode } from './data/base64.js'; export type { TreeNode, diff --git a/tests/base64.test.ts b/tests/base64.test.ts new file mode 100644 index 0000000..7e40ebf --- /dev/null +++ b/tests/base64.test.ts @@ -0,0 +1,13 @@ +import { describe, it, expect } from 'vitest'; +import { base64Encode, base64Decode } from '../src/index.js'; + +describe('Base64', () => { + it('encodes and decodes UTF-8 strings', () => { + const s = 'Hello, 世界! 🎉'; + const b64 = base64Encode(s); + const bytes = base64Decode(b64); + const back = new TextDecoder().decode(bytes); + expect(back).toBe(s); + }); +}); + diff --git a/tests/index.test.ts b/tests/index.test.ts index 6a6ebb5..7513636 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -130,6 +130,8 @@ describe('package entry point', () => { | 'SkipList' | 'runLengthEncode' | 'runLengthDecode' + | 'base64Encode' + | 'base64Decode' >(); expectTypeOf>().toEqualTypeOf<