Conversation
added 2 commits
June 26, 2026 17:35
cmpute
commented
Jun 26, 2026
AbsEq was folded into AbsOrd and removed in Phase 1 (not merely deprecated); reword the §5.3 parenthetical to match. Co-Authored-By: Claude <noreply@anthropic.com>
TODO-v05.md: - Note the full C <tgmath.h> type-generic math surface as a long-term goal, explicitly out of scope for 0.5 and 0.5.x. TODO-cmplx.md: - unwrap_cfp: define dashu-cmplx's own Context::unwrap_cfp (the float unwrap_fp is pub but typed for FpResult<FBig>, unusable for CfpResult). - Conversions: replace from_real/from_int with From<FBig>/From<UBig>/ From<IBig> and add TryFrom<CBig> for FBig/IBig, mirroring FBig's "Convert from/to UBig/IBig" pattern. - hypot: make FBig::hypot (overflow-safe scaled sum-of-squares) a prerequisite dashu-float step; CBig::abs becomes a thin composition. Co-Authored-By: Claude <noreply@anthropic.com>
Add the new `dashu-cmplx` crate (the headline 0.5 feature) with the `CBig` arbitrary-precision complex type built on `dashu-float`'s `FBig`. Type & context model (§2): - `CBig<R: Round = Zero, const B: Word = 2>` — two `Repr<B>` parts over a single shared `dashu_cmplx::Context<R>` newtype, mirroring `FBig`'s `Repr`+`Context` layout (the uniform-precision invariant is structural). - `Context<R>` wraps `dashu_float::Context<R>` and hosts the context-layer ops; `CRounded`/`CfpResult` carry per-axis `(Rounding, Rounding)` inexactness. Construction/conversion (§5.1): `from_parts`/`re`/`imag`/`into_parts`, the `ZERO`/`ONE`/`I` constants, `From<FBig>`/`From<UBig>`/`From<IBig>`, and the lossy `TryFrom<CBig> for FBig`/`IBig` (composing CBig → FBig → IBig). Easy ops (single-pass rounding): add/sub (operators only, calling the context layer — matching `FBig`'s no-inherent-add pattern), `neg`/`conj`/`proj`/`mul_i` (exact), `norm` (squared modulus) and `arg` (Annex-G `atan2`). Comparison (§5.3): componentwise `Eq`, lexicographic `Ord`, `AbsOrd` via `|z|²`, and `NumOrd`/`NumHash` (behind `num-order`). I/O (§5.6): algebraic `a+bi` `Display`/`FromStr` (MPC's parenthesized form is rejected) and structured `Debug`. Workspace + meta-crate wiring: `complex/` added to the workspace, the meta-crate gains `dashu::complex` and the `dashu::Complex = CBig` alias, and `dashu-cmplx` is wired into the shared feature-forwarding lines. Co-Authored-By: Claude <noreply@anthropic.com>
dashu-float prerequisite: - `FBig::hypot` / `Context::hypot`: overflow-safe `sqrt(a²+b²)` via the scaled sum-of-squares (the larger operand is never squared; `m·sqrt(1+r²)` with `r=min/max ∈ [0,1]`). `hypot(±inf,·)=+inf`, `hypot(0,0)=+0`. This is the kernel `CBig::abs` composes, landed on FBig so it is a first-class real op too. CBig field arithmetic (near-correctly rounded via the §6.1 guard-digit recipe — evaluate each component at `p+g`, re-round to `p`; no Ziv retry): - `sqr` `(x²-y²)+i(2xy)`, `mul` `(xu-yv)+i(xv+yu)` (naive 4-mul), `div` (Smith's overflow-safe method, `|u|≥|v|` branch), `inv` `conj(z)/|z|²`. - `abs` = `ctx.hypot(re, im)` at guard precision. - Scalar mul/div by a real `FBig` via mixed-type operators (`z*r`, `z/r`, `r*z`, `r/z`) — no named methods (Decision 9). Annex-G special-value short-circuits: `0·∞`/`0/0`/`∞/∞` → `Indeterminate`; `z/0`/`∞·finite` → the Riemann point at infinity (`+∞+i·0`); `finite/∞`/`0/finite` → 0. (dashu's convention: complex infinity is the single Riemann point produced by `proj`.) Tests: - `tests/special_values.rs` — exact Annex-G vectors for mul/div/inv. - `tests/arith_prop.rs` — exact identity proptests (commutativity, z+0=z, z-z=0, z·1=z, z·0=0, mul_i⁴=id, conj²=id, proj idempotent, z+(-z)=0). - `tests/rounding_prop.rs` — correct-rounding self-oracle (mul/sqr/div/abs at `p` vs `2p` re-rounded, ≤1 ulp/component) and `z·conj(z)=norm`. Co-Authored-By: Claude <noreply@anthropic.com>
- `sqrt` (principal branch, cut `]−∞, 0]`): cancellation-free form — for `x ≥ 0`, `a = sqrt((r+x)/2)` and `b = y/(2a)`; for `x < 0`, `b` from `(r-x)/2` and `a = y/(2b)`. Avoids the `(r−x)` catastrophic cancellation when `|y|≪|x|`. Annex-G specials: `sqrt(±0)=±0`, `sqrt(+∞+iy)=+∞+i·0`, `sqrt(-∞+iy)=0+i·sign(y)∞`. - `exp(x+iy) = e^x·(cos y + i sin y)` reusing FBig `exp`/`sin_cos`; `exp(0)=1`, `exp(+∞+ifinite)=+∞`, `exp(-∞+ifinite)=0`, infinite imaginary → `Indeterminate`. - `log z = ln|z| + i·arg z` (Im ∈ `]−π,π]`); `log(0)=-∞`, `log(∞)=+∞`, cut `]−∞,0]`. - `powi` (integer exponent, repeated squaring, branch-cut-free) and `powf` (`exp(w·log z)` at `p+POWF_GUARD`, re-rounded); `powf(z,0)=1` incl. `powf(0,0)=1`. The transcendental context ops (`exp`/`log`/`powf`/`arg`) now carry `cache: Option<&mut ConstCache>` (threaded via a centralized `reborrow_cache` helper), matching the spec so the deferred `CachedCBig` needs no signature change. Tests: - `tests/transcendental_prop.rs` — sqrt/exp/log self-oracles (p vs 2p, ≤2 ulp), `sqrt(conj z)=conj(sqrt z)`, and `log z = ln|z| + i·arg z`. - `tests/special_values.rs` — extended with sqrt/exp/log special-value vectors. Co-Authored-By: Claude <noreply@anthropic.com>
Forward trig via the real–imaginary decomposition, reusing `dashu-float`'s real `sin`/`cos` and cancellation-free `sinh`/`cosh` (avoids the `exp(±iz)` blow-up for large `|Im z|`): - `sin(x+iy) = sin x·cosh y + i·cos x·sinh y` - `cos(x+iy) = cos x·cosh y − i·sin x·sinh y` - `sin_cos` (shared reduction), `tan = sin/cos`. Infinite input → `Indeterminate`. Inverse trig (Kahan log forms; the inner `log` argument always has positive real part, so the cut comes from the `sqrt`): - `asin z = -i·log(iz + sqrt(1-z²))`, `acos z = -i·log(z + i·sqrt(1-z²))`, `atan z = (i/2)·(log(1-iz) - log(1+iz))`. dashu-float: `FBig::from_repr`'s debug assert now accepts the documented single guard digit (`precision + 1`), so `CBig::into_parts` doesn't panic on a guard-digit part produced by an inexact add. Tests: `transcendental_prop.rs` extended with sin/cos/asin/atan self-oracles (p vs 2p) and the pythagorean identity (modest-range strategy, since `cosh²y`/ `sinh²y` cancel for large `|Im z|`). Co-Authored-By: Claude <noreply@anthropic.com>
…MPC oracle
- `tests/special_values.rs`: expanded Annex-G coverage — `proj` (Riemann collapse),
`conj` with infinities, `arg` of imaginary infinities, the signed-zero
`log(-r ± i0) = ln r ± iπ` branch cut, and `sqrt(-∞) = 0 + i·∞`.
- `benches/` (criterion, `required-features = ["rand"]`, not run in CI): `arith`
(`mul`/`div`/`sqr` over precisions {53,113,256,1024}), `transcendental`
(`exp`/`log`/`sin`/`cos`/`sqrt`/`abs`/`arg`), and `io` (`Display`/`FromStr`),
each with a `random_cbig` helper (log-scale sizing, `StdRng::seed_from_u64(1)`).
- `fuzz/tests/cmplx_random.rs`: a `rug::Complex` (GNU MPC) differential oracle for
field arithmetic at 53-bit precision — `mul`/`div`/`sqr` match MPC within a few
ulps over 8192 random cases (manual: `--ignored`). `dashu-cmplx` added to fuzz deps.
The pre-existing fuzz tests (`add_random`, `trig_random`) are stale against the
post-#83 `FpResult` (unchanged here); the new oracle compiles and passes standalone.
Co-Authored-By: Claude <noreply@anthropic.com>
cbig! literal macro (dashu-macros): - `cbig!` / `static_cbig!` (+ `cbig_embedded` / `static_cbig_embedded`) accepting the algebraic `a+bi` form or a `re, im` pair; each coefficient reuses the `fbig!` base-2 parser. The static variant builds via a new `CBig::from_repr_parts` const constructor (each Repr via `from_static_words`/`Repr::zero()`), gated on Rust 1.64+ like the other static macros. Exposed as `dashu::cbig!` in the meta-crate. Guide: a "Complex Numbers" chapter (construction, two-layer API, no-NaN special-value model, near-correct rounding), linked from SUMMARY.md. Version sync (Phase 5): all crates bumped to 0.5.0 (base/int/float/ratio/macros 0.4.x → 0.5.0; complex already 0.5.0) and every inter-crate dependency version string updated; changelels consolidated (Unreleased → 0.5.0). Co-Authored-By: Claude <noreply@anthropic.com>
The MSRV (1.68) job strips rand 0.9/0.10 (which need newer Rust) from the manifests before `cargo check --features rand`. The new `dashu-cmplx` crate wasn't in that list, and it forwards `rand_v09 → dashu-float/rand_v09`, while the meta-crate's `rand` feature still pointed at `dashu-cmplx/rand` — so after the strip, resolution failed with "dashu-float does not have feature rand_v09". Mirror the existing handling: strip `rand_v09`/`rand_v010` (and complex's `rand` alias + the `required-features = ["rand"]` benches) for the MSRV build, and drop the `dashu-cmplx/rand` forwarding from the meta-crate's `rand` line. Stable/1.85 still exercise the full rand surface via `--all-features`. Verified by running the script + the exact MSRV check command locally (`cargo check --workspace --exclude dashu-python --features "std,num-order,serde,zeroize,rand,num-traits_v02"` builds cleanly). Co-Authored-By: Claude <noreply@anthropic.com>
The inline Display/FromStr unit tests use format!, which is not in the prelude under no_std. The fmt/parse test modules now `use alloc::format;` (the same fix dashu-ratio uses), so `cargo test --no-default-features --features rand` compiles. Verified: `cargo test --no-default-features --features rand --workspace --exclude dashu-python` passes; the all-features (std) build and clippy are unchanged. Co-Authored-By: Claude <noreply@anthropic.com>
Add random generation for CBig, mirroring dashu-float/ratio: - Features: `rand = ["rand_v08"]` (default alias), with `rand_v09`/`rand_v010` opt-in — matching integer/float/rational, and MSRV-compatible (rand 0.8 runs on 1.68, so the MSRV `rand` build no longer needs a complex-specific carve-out). - `third_party/rand.rs`: `UniformCBig<R,B>` samples the box `[low, high)` (each part an independent `UniformFBig` range). `rand_v08`/`rand_v09`/`rand_v010` add the `Distribution<CBig>` impls; `Standard`/`StandardUniform`/`Open01`/ `OpenClosed01` sample the unit square `[0,1)²` (each part uniform in `[0,1)`). No bespoke sampling algorithm — it reuses `dashu_float::rand::UniformFBig`. - No single-axis `Uniform`/`SampleUniform` (complex has no interval order); the box `UniformCBig::new(low, high, precision)` is the ranged sampler. The MSRV dep-drop script is simplified back to just adding `complex/Cargo.toml` to the existing rand_v09/rand_v010 strip loop (complex now keeps `rand = rand_v08`). Tests: `tests/random.rs` (the `Standard` unit square, the `UniformCBig` box, and `Open01` excludes zero). Verified across rand 0.8/0.9/0.10, `no_std`, and the MSRV check command. Co-Authored-By: Claude <noreply@anthropic.com>
The old CBig NumHash hashed re and im sequentially (tuple-style), inconsistent with num-order's native Complex<f64> hashing (algebraic combination of the per-part field elements). CBig NumHash now mirrors num-order's "Case 4": treat z = a + b·i and write hash(a + bterm) where bterm = ∓PROOT²·b² (sign of b), with a, b the per-part residues. This keeps a CBig and a num-complex Complex<f64> of the same value in sync. dashu-float changes (behind `num-order`): - `Repr::num_hash_residue(&self) -> i128`: the numeric-hash field element (mod 2¹²⁷−1), extracted from `Repr::num_hash` so composite types can reuse it. For base-2 uses the same `absm(&127)` exponent reduction as num-order's f64 fhash. - ±∞ now map to `HASH_INF`/`HASH_NEGINF` (= ±M127), matching num-order's f64 fhash. The subsequent `i128::num_hash` still reduces these to 0 (since M127 ≡ 0 mod M127), so the *final* hash of a real ±∞ is unchanged — but the *residue* now distinguishes them so CBig's algebraic combination is correct for complex numbers with infinite parts. ±0 still maps to 0. - `test_fbig_num_hash_matches_f64` verifies FBig↔f64 consistency including ±∞ and -0. dashu-cmplx changes: - `_num-modular` added to the `num-order` feature. - `CBig::num_hash` rewritten to the algebraic formula. - `cbig_num_hash_matches_num_complex` cross-checks against the transcribed num-order Complex<f64> formula for 7 sample values. Co-Authored-By: Claude <noreply@anthropic.com>
Align dashu-cmplx's module layout and operator-impl style with dashu-float.
Pure restructuring; no behavioral change.
- Merge `sub.rs` into `add.rs` and `power.rs` into `exp.rs`, matching float's
single-file grouping: add+sub share one sign-parameterized kernel
(`signed_add`, sub = add with negated rhs), and `exp` hosts the power family.
- Rewrite the `CBig·CBig` `Mul`/`MulAssign` impls (and `add.rs`'s
`AddAssign`/`SubAssign`) as explicit ref/val impls plus a new
`impl_binop_assign_by_taking!` macro, mirroring float's `mul.rs`/`add.rs`
instead of the one-shot `impl_cbig_binop!` mega-macro.
- Promote `trig.rs` to a `math/` submodule (`math/{mod,trig}`), matching
float's `pub mod math`.
- Rename `context.rs` to `repr.rs` (float keeps `Context` in `repr.rs`),
updating every `crate::context::` path to `crate::repr::`.
Co-Authored-By: Claude <noreply@anthropic.com>
- Phase 3 (dashu-cmplx): mark ✅ Implemented (M1–M6); fold the detailed TODO-cmplx.md design doc into a consolidated §3.4 deferred-to-0.5.x list (Ziv, hyperbolics, fma, CachedCBig forward-compat note, CRound, etc.). TODO-cmplx.md is removed. - Phase 0: drop the "record baseline benchmark" item — results are hardware-dependent and won't be committed; note the decision inline. - Phase 1 §1.5: replace vague prose with four concrete checkboxes (guide prose migration + the pow/div/exp algorithm TODOs), line refs updated. - Remove the "Open Decisions" section — all four (CBig scope, serde padding, proptest, MSRV) are resolved and documented in their phases. Co-Authored-By: Claude <noreply@anthropic.com>
The `Context::sin` 49-digit-significand rounding regression (found during
fuzzing) lived only in the workspace-excluded `fuzz/` crate, so it never ran in
CI. Move it into float's inline trig tests as
`test_sin_many_digit_rounding_no_panic` (rewritten to the current
`Context::sin` API), and consolidate the pythagorean identity proptest to sweep
precisions {20, 50, 100} — a strict superset of the former single-precision
version, replacing the complementary fuzz sweep that was deleted.
Co-Authored-By: Claude <noreply@anthropic.com>
…d.yml The workspace-excluded `fuzz/` crate had not compiled since the #83 FpResult change (its tests targeted the pre-#83 `Context::sin(f)`/`FpResult::Normal` API). Restore it and convert the differentials to proptest. Fuzz crate (step 1): - Port every test to the current `Context`/`FpResult` API (`ctx.sin::<B>(&x, None).unwrap().value()`; `FpResult` is `Result<Rounded<_>, FpError>`). - Replace the `for _ in 0..N { rng… }` loops with proptest strategies (`fuzz_config` = 1024 cases, overridable via `PROPTEST_CASES`) so a mismatch shrinks to a minimal counterexample. Shared strategies live in `fuzz/src/lib.rs`. - `add_random`: dispatches all six rounding modes per case, precision biased toward 1/2/3. `trig_random`: five broad differentials (sin/cos/tan/atan2/ inv-trig) in proptest + three deterministic sweeps (pi/asin-near-1/large-exp tan) ported; `atan2(0,0)` indeterminate handled by skipping. `cmplx_random`: MPC mul/div/sqr over f64 pairs. Trig tests use `HalfAway` to match `DBig`. All remain `#[ignore]`d (manual, release-time — they link `rug` and run long). CI (step 2): - New `.github/workflows/build.yml` for compile-only checks: a `fuzz-check` job (cargo check the fuzz crate so it can't silently rot again — tests stay manual), plus `build-benchmark` and `build-aarch64` moved out of `tests.yml`, plus the `check` (cargo check, stable/1.85/1.68 MSRV matrix) job. - `tests.yml` now runs only the test matrix + x86/x86_64/no-std tests + fmt + clippy. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Four new proptest-driven test files in the workspace-excluded `fuzz/` crate, differential against `rug` (GMP/MPFR/MPC) to complete the correctness-oracle coverage: - `transcendental.rs` — all 17 non-trig FBig transcendetals (exp/exp_m1, ln/ln_1p/sqrt/cbrt/nth_root/hypot/atan/powf/powi + the hyperbolic family), compared vs `rug::Float` (MPFR) with a `within_k_ulps(k=2)` tolerance (dashu near-correct, MPFR Ziv-correct → ≤1 ulp is legitimate). - `cmplx_transcendental.rs` — 10 CBig transcendetals (exp/log/sqrt/ sin/cos/tan/asin/acos/atan/powf) vs `rug::Complex` (MPC) at 53-bit, reusing the shared `close()` helpers. - `integer.rs` — 15 UBig/IBig ops (mul/sqr/gcd/div_rem/pow/sqrt/nth_root/ bit-ops/shifts) vs `rug::Integer` (GMP) via exact decimal-string round-trip. - `ratio.rs` — 8 RBig ops (add/sub/mul/div/sqr/pow/inv/reduce) vs `rug::Rational` (GMP mpq) via exact canonical-form comparison. Shared infra: `fuzz/src/lib.rs` gains `ubig_strategy`, `pos_dbig_strategy`, `unit_dbig` (promoted from trig_random), and a `cmplx` module holding the 53-bit build/compare helpers (moved from cmplx_random). The fuzz crate now depends on `dashu-ratio`. Bug fix discovered by the integer oracle: - `UBig/IBig::nth_root(0, n)` (and `cbrt(0)`) returned 1 instead of 0: the `bits <= n` shortcut in `integer/src/root_ops.rs` fired for the zero input (bit_len == 0). Fixed with a zero guard. Regression test added. Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.