Skip to content

Deck reader: accept fractional .freq ndec (documented), plus compat sweep edge cases #154

Description

@rjwalters

Problem

User's Guide §1.3.6: "ndec need not be an integer". Its own example fmin=1e3 fmax=1e7 ndec=0.5 solves 10³, 10⁵, 10⁷ Hz. We reject any non-integer ndec ('0.05' is not a valid ndec), which stops 4 of the 19 runnable example decks.

Measured rule (FastHenry, self-authored decks): solve f_k = fmin·10^(k/ndec) for k = 0, 1, … while f_k ≤ 1.001·fmax. The last point is the stepped value and is not clamped to fmax.

fmin..fmax, ndec solved
1e3..1e7, 0.5 1e3, 1e5, 1e7
1e3..1e7, 0.3333333 1e3, 1e6
1e3..1e7, 0.3 1e3, 2.15443e6
1e3..1e7, 0.2 1e3
1e3..1e7, 1.5 1e3, 4641.59, 21544.3, 1e5, 464159, 2.15443e6, 1e7
1e3..1e4, 2.5 1e3, 2511.89, 6309.57
2e3..1e7, 1 2e3, 2e4, 2e5, 2e6
1e-1..1e19, 0.05 0.1, 1e19
fmin = fmax one point

Edge cases: an omitted ndec acts as 1. ndec=0 warns and becomes 0.01. A negative ndec loops forever. fmin > 1.001·fmax gives an empty sweep. fmin=0 is DC only (already supported). The 0.1% slack also differs from us for integer ndec: 1..9.995 ndec=1 is 2 points in FastHenry and 1 in ours.

Expected

  • All modes (documented): accept ndec > 0, including fractions, generating fmin·10^(k/ndec). Keep exact 10^q snapping where k/ndec is an integer. ndec < 0 is a line-numbered error.
  • --fasthenry-compat only (undocumented quirks): the f ≤ 1.001·fmax inclusion rule; ndec=0 → 0.01 + warning; omitted ndec → 1 + warning; fmin > fmax → empty sweep + warning. These stay errors in native mode.

Acceptance criteria

  • The table above is reproduced as unit tests on the generated frequency list (compat mode for the slack-dependent rows).
  • ndec < 0 errors in both modes; compat edge cases warn with line numbers.
  • docs/fasthenry-compat.md .freq rows updated.

Clean-room provenance

Specified from the public FastHenry User's Guide / nonuniform ground-plane manual and from black-box runs of a locally built FastHenry on self-authored decks (2026-10-05, research for #74). No FastHenry source or distributed example deck was consulted or quoted; implement from this spec and the public docs only (CONTRIBUTING.md). Found by tools/fasthenry_compare.py over the FastHenry example corpus (#74).

Part of #76.

Activity

  1. added
    loom:issueApproved for work. Applied by: humans, Champion, or sweep Approval gate — see curator.md for rule.
    on Oct 5, 2026
  2. added
    loom:buildingBuilder is implementing this issue. Applied by: Builder only (claim label).
    and removed
    loom:issueApproved for work. Applied by: humans, Champion, or sweep Approval gate — see curator.md for rule.
    on Oct 5, 2026
  3. loom-fleet-dispatch commented on Oct 5, 2026

    @loom-fleet-dispatch
    Contributor

    This issue's loom:building claim was acquired by sweep sweep-issue-154-1791243629 on host host-34209a6e at 2026-10-05T23:40:32.357611+00:00. This comment is a lease record (Issue #6179, Epic #6165) — its liveness signal is this comment's own forge-assigned updated_at, never a timestamp embedded in this text. See defaults/docs/lease-record.md for the format contract this establishes, and defaults/docs/lease-renewal.md for how the owning sweep keeps it fresh for the lifetime of its claim. Nothing reads this record yet (write-only, Phase 1) — a future phase will use it to decide reclamation of an abandoned claim.

    loom dashboard

  4. added
    loom:issueApproved for work. Applied by: humans, Champion, or sweep Approval gate — see curator.md for rule.
    loom:curatingCurator is enhancing this issue. Applied by: Curator only (claim label).
    and removed
    loom:buildingBuilder is implementing this issue. Applied by: Builder only (claim label).
    on Oct 6, 2026
  5. loom-fleet-dispatch commented on Oct 6, 2026

    @loom-fleet-dispatch
    Contributor

    Curator enhancement — 2026-10-06

    The existing problem, measured table, and acceptance criteria are retained. PR #161 is the implementation already in progress; coordinate follow-up there rather than starting a second implementation. PR #159 cross-references this issue from a repository documentation pass. Duplicate/cross-reference checking found those two open PRs and no duplicate issue. The other intake/approved deck-reader issues address different directives; no sibling consolidation is warranted. This remains part of #76, with no prerequisite implementation issue identified.

    Verified corrections

    • 2026-10-06, verified against origin/main at e5d924abb67d149f1f3a066678078c36af2c3e7e (git show and symbol search): Builder::apply_freq in fasterhenry-cli/src/inp.rs reads ndec using parse_count, and its frequency_sweep takes usize. decade_frequencies in fasterhenry-cli/src/main.rs separately rejects fractional density for unequal endpoints. Both paths need the documented fractional-density rule; exact source line numbers differ from the local checkout.

    Implementation Guidance

    • Parse .freq density as a finite floating-point value, validating negative density before single-frequency/DC early returns. Preserve integer-only validation for unrelated subdivision counts.
    • Keep native and compatibility policies explicit: compatibility changes endpoint inclusion and supplies the documented issue defaults with line-numbered warnings; native mode retains its errors. Preserve exact whole-decade points without clamping the last generated point.
    • Distinguish a successfully parsed empty compatibility sweep from a missing .freq directive. Check the existing CLI behavior when there are no frequencies and when --freq supplies an override.
    • Share the documented positive-density generation rule with --freq to avoid maintaining divergent formulas. Keep compatibility-only deck warnings in the deck parser.
    • Implement from this issue's clean-room specification. The original measured FastHenry behavior is supplied evidence, not independently remeasured during this curation.

    Affected Files

    All paths below exist on the fetched origin/main commit named above.

    • fasterhenry-cli/src/inp.rs — density parsing, native/compat sweep policy, diagnostics, empty-sweep handling, and parser unit tests.
    • fasterhenry-cli/src/main.rs — duplicated command-line decade generation and empty/overridden sweep behavior.
    • fasterhenry-cli/src/cli.rs — --freq help text if it currently requires integer density.
    • fasterhenry-cli/tests/cli.rs — command-line fractional-density and sweep override regression coverage.
    • fasterhenry-cli/README.md — document fractional command-line density.
    • docs/fasthenry-compat.md — update .freq compatibility rows as required by the existing acceptance criteria.

    Test Plan

    • Automated parser tests reproduce every supplied frequency-table row; use numerical tolerance for nonintegral exponents and exact equality for whole-decade points. Assert the last point is stepped rather than clamped.
    • Test 1..9.995 ndec=1 in both modes, equal endpoints, and the existing zero-frequency/DC behavior.
    • Test negative, zero, omitted, malformed, and nonfinite density values in both modes; verify errors/warnings carry the .freq line number. Include equal endpoints so early returns cannot bypass invalid-density checks.
    • Test reversed bounds within and outside the compatibility slack, missing .freq, empty compatibility sweeps, and --freq overriding an empty sweep.
    • Exercise fractional --freq in CLI tests and verify it follows the native positive-density rule.
    • Run the CLI test suite plus workspace formatting/lint checks. Review updated docs/help against the tested mode behavior.
    • Manual verification: use a self-authored minimal deck with fmin=1e3 fmax=1e7 ndec=0.5; confirm the output lists 1e3, 1e5, and 1e7 Hz and compatibility warnings appear only for the specified exceptional inputs.

    Curation is specification preparation, not approval of PR #161 or verification of its reported test results.

    loom dashboard

  6. added
    loom:curatedCurator-enriched, awaiting approval. Additive; coexists with loom:issue. Applied by: Curator only.
    tier:goal-advancingDirectly implements a milestone deliverable or unblocks goal work
    and removed
    loom:curatingCurator is enhancing this issue. Applied by: Curator only (claim label).
    on Oct 6, 2026
  7. added a commit that references this issue on Oct 7, 2026
    56a4940
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    loom:curatedCurator-enriched, awaiting approval. Additive; coexists with loom:issue. Applied by: Curator only.loom:issueApproved for work. Applied by: humans, Champion, or sweep Approval gate — see curator.md for rule.tier:goal-advancingDirectly implements a milestone deliverable or unblocks goal work

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions