Commit Graph

10 Commits

Author SHA1 Message Date
Kinneyzhang
112b3a0e52 refactor!: overhaul KP core — correctness, C parity, performance, tests, docs
- fix: ekp-param-set silently reset after first justify (now persists;
  ekp-param-reset added)
- fix: narrow-width CJK returned empty string (data loss); two-pass
  emergency-break strategy guarantees output for any input
- fix: K-P penalties never synced to C module; space-box metrics
  divergence between C and Elisp engines
- fix: para cache ignored ekp-latin-lang (stale hyphenation after
  language switch) and used collision-prone sxhash keys
- fix: fullwidth letters/digits misclassified as CJK punctuation
- fix: combining chars split from their base char in the tokenizer
- fix: punctuation-wrapped words (word!/(word)/word;) never hyphenated
- fix: renderer double-counted stripped space widths; negative glue
  clamped; batch/tty font detection no longer crashes
- feat: real looseness support via (position × line-count) DP
- perf: O(1) line metrics and gap counts via prefix arrays (inner loop
  previously allocated O(n) subsequences → O(n³) total); box measurement
  dedupe; eq fast-path para lookup; prebuilt per-para glue arrays
  → zh justify 7547ms → 96ms (compiled elisp) / 57ms (C);
    range-justify 68.5s → 0.48s / 34ms; C module itself 3–19× faster
- test: 36 batch-safe ERT tests + 300-case property fuzz (C/elisp
  byte-identical output, zero content loss) replacing ad-hoc suite
- docs: readme/readme_zh/DEVELOPER/DEVELOPER_ZH/ekp_c-README rewritten
  to match the implementation; phase handoff in .phrase/phases/

BREAKING: requires Emacs 29.1+; C module must be rebuilt (v1.1, new
arities); ekp-threshold-factor / ekp-flagged-penalty /
ekp-forced-break-penalty removed; Rust module stubs removed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 18:44:02 +08:00
Kinneyzhang
136e53fe8e improve C module 2026-01-26 01:24:47 +08:00
copilot-swe-agent[bot]
a421926e91 Fix C module single-box line handling order to match Elisp
Bug: C module and Elisp produced different results for same text.

Root cause: Different condition checking order for single-box vs last-line:
- Elisp: single-box check comes BEFORE is-last check
- C: is_last check came BEFORE is_single_box check (now fixed)

When the last line has only one box, Elisp uses single-box calculation
while C was using last-line calculation, resulting in different demerits
and different final breakpoints.

Fix: Moved is_single_box check before is_last check in dp_process_position()
to match Elisp's ekp--dp-compute-line-demerits behavior.

Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-25 12:02:09 +00:00
copilot-swe-agent[bot]
4a84723181 Refactor C module to eliminate duplicate DP logic
Extracted shared DP core algorithm into dp_process_position() function:

1. Added dp_input_t struct - unified input interface for DP algorithm
   - Contains prefix arrays, glue arrays, hyphen info
   - Contains K-P parameters (penalties, ratios)

2. Added dp_is_hyphen() function - unified hyphen position detection
   - Uses O(log n) binary search
   - Replaces is_hyphen_pos() function

3. Added dp_process_position() function - core DP algorithm
   - Processes single start position i, tries all end positions k
   - Contains complete demerits calculation, fitness classification
   - Both entry functions now call this shared core

4. Refactored process_dp_range()
   - Builds temporary glue arrays from ekp_paragraph_t
   - Creates dp_input_t and calls dp_process_position()

5. Refactored ekp_break_with_prefixes()
   - Directly uses input arrays to create dp_input_t
   - Calls dp_process_position() for each position

Benefits:
- Single point of maintenance: DP bugs only need fixing once
- Consistency guaranteed: both paths use identical algorithm
- ~100 lines of duplicate code removed
- Better testability: core algorithm can be tested independently

Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-25 11:55:27 +00:00
copilot-swe-agent[bot]
b70affb9ef Optimize hyphen position lookup O(n)->O(log n) and add named constants
Performance:
- ekp--hyphenate-p: O(n) cl-find -> O(log n) binary search
- is_hyphen_break: O(n) linear -> O(log n) binary search
- is_hyphen_pos: O(n) linear -> O(log n) binary search

In O(n²) DP loop, this reduces worst-case complexity from O(n³) to O(n² log n)

Code quality:
- Add ekp-consecutive-hyphen-penalty (was hardcoded 100)
- Add ekp-forced-break-penalty (was hardcoded 10000)
- Add ekp-last-line-short-penalty (was hardcoded 50)
- Update ekp-looseness docstring noting partial implementation

Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-25 11:15:42 +00:00
copilot-swe-agent[bot]
fee05f769d Fix C module to match Elisp behavior for last-line overflow handling
When is_last && ideal > line_width, the C module now correctly
triggers force break logic, matching ekp--dp-cache-elisp behavior.
This ensures consistent results between C module and pure Elisp paths.

Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-25 10:32:06 +00:00
Kinneyzhang
68ca9b191a improve C module parallel 2026-01-25 17:28:04 +08:00
Kinneyzhang
6cf6f75f71 fix bugs of C moudule 2026-01-25 16:53:23 +08:00
Kinneyzhang
aaeea099c9 fix bug 2026-01-25 15:11:47 +08:00
Kinneyzhang
c88bbdd395 add dynamic moudle to improve prefermance 2026-01-25 13:50:46 +08:00