feat: log_approx_f32 polynomial natural log intrinsic - #31
Merged
Conversation
9 tasks
petlukk
force-pushed
the
feat/v1.14-log-approx-f32
branch
2 times, most recently
from
May 19, 2026 07:07
2c2c24b to
cb7119a
Compare
Eigen/Cephes-family approach — bit-level decomposition of x = m·2^e (frexp convention, m in [0.5, 1)), √2/2 rebalance to center the polynomial range, degree-8 Eigen-coefficient Horner in (m - 1), Cody-Waite recombine with e·ln(2). Avoids @llvm.log which LLVM scalarizes to per-lane libm logf. Verbatim Eigen MathFunctionsImpl.h coefficients (MPL2) kept at upstream's published double precision for diff-friendliness; the compiler truncates each to f32 at compile time. LN2_HI is exact in f32 (binary 0.10110001 1, 9 mantissa bits); LN2_LO carries the residual so e·ln(2) preserves precision for large e. Cody-Waite recombine order matters: small-magnitude terms first (-u²/2, then e·LN2_LO), dominant terms last (+u, then e·LN2_HI). Same discipline exp_poly_f32 uses for ldexp. Max abs error ~3e-6 across (0, +∞). Same f32-vector-only typeck shape as exp_poly_f32 and tanh_approx_f32. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
13 tests mirroring phase14_exp_poly.rs / phase14_tanh_approx.rs:
- at_one: smoke that log(1) = 0 in all 4 lanes.
- boundary_points (x4 + x8): powers of 2 across the f32 exponent
range (1/1024 to 1e9), transcendental constants (e, π), and the
rebalance boundary [√2/2, √2]. Absolute (not relative) error
≤ 3e-6 because log(x) → 0 as x → 1 makes relative error explode
near 1.
- random (x4 + x8): 256 log-uniform samples over [exp(-4.6),
exp(4.6)] ≈ [0.01, 100] — covers the dense middle of the input
distribution.
- then_exp_poly_roundtrip: exp_poly_f32(log_approx_f32(x)) ≈ x to
1e-4 relative. Pins composition of the two intrinsics — they
share the Cody-Waite ln(2) discipline, so an order-of-operations
regression in either would surface here.
- does_not_emit_llvm_log: IR guard against future simplification
that delegates to @llvm.log (which LLVM scalarizes).
- emits_expected_pattern (x4 + x8): IR has ≥8 FMAs + lshr + float
↔ int bitcasts + sitofp.
- Four typeck rejections: scalar f32, f64x2, i32x4, wrong arity.
Boundary point constants use std::f32::consts::{FRAC_1_SQRT_2,
SQRT_2} per clippy's approx_constant lint.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CHANGELOG entry under v1.14.0 Added. ROADMAP gets a Shipped entry; the Future API consistency line is rewritten from a three-item bullet (tanh/log/sin_cos) to just sin_cos_approx_f32 — the remaining transcendental in the original trio, kept as speculative until a real consumer asks (angle range, periodicity strategy, and sin-vs-cos-vs-pair API shape are all open design questions). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
petlukk
force-pushed
the
feat/v1.14-log-approx-f32
branch
from
May 19, 2026 08:45
cb7119a to
c1dd6a1
Compare
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.
Summary
log_approx_f32(v: f32xN) -> f32xNintrinsic — Eigen/Cephes-family polynomial natural log. Bit-level decomposition ofx = m · 2^e(frexp convention,m ∈ [0.5, 1)), √2/2 rebalance, degree-8 Horner in(m - 1), Cody-Waite recombine withe · ln(2).(0, +∞). Composes cleanly withexp_poly_f32— pin-tested via a roundtrip kernel at ~1e-4 relative.@llvm.log.v*f32, which LLVM scalarizes to per-lane libmlogf.Family progress
exp_poly_f32tanh_approx_f32log_approx_f32sin_cos_approx_f32ROADMAP "Future API consistency" line trimmed accordingly — only
sin_cos_approx_f32remains, with open design questions on angle range, periodicity strategy, and API shape.Cody-Waite ln(2) discipline
The recombine order matters: small-magnitude terms first (
-u²/2, thene · LN2_LO), dominant terms last (+u, thene · LN2_HI). Same disciplineexp_poly_f32uses for ldexp; thethen_exp_poly_roundtriptest pins that both intrinsics keep this contract.Test plan
cargo test --features llvm --release— 937 tests pass (924 baseline + 13 new)cargo clippy --features llvm --all-targets— cleancargo fmt --check— cleanlog_approx_f32(splat(1.0))returns 0 (smoke)logf: powers of 2 from 1/1024 to 1e9,e,π, the √2/2 rebalance boundary; abs error ≤ 3e-6[0.01, 100]for f32x4 and f32x8exp_poly_f32(log_approx_f32(x)) ≈ xto 1e-4 relative (composition guard)@llvm.log; ≥8 FMAs;lshr <N x i32>; float↔int bitcasts;sitofp🤖 Generated with Claude Code