Repository navigation
Fix Log precision and Pow returning 1 for a zero base - #10
Merged
Merged
Conversation
- Log multiplied y by the e * -2.12194440e-4 term instead of adding it, which discarded the polynomial correction. Max error vs std::log drops from 615826 ULP to 1 ULP - Log masks inputs <= 0 to 0, so Pow( 0, p ) returned Exp( 0 ) = 1. Pow now returns 0 for value <= 0 - Add "f32 pow zero base" test
Auburn
added a commit
to Auburn/FastNoise2
that referenced
this pull request
Oct 14, 2026
FS::Pow now returns 0 for a zero base (Auburn/FastSIMD#10), so the local PowNonNegative workaround is no longer needed. The Log fix in the same bump also removes most of the remaining Minkowski error.
Auburn
added a commit
to Auburn/FastNoise2
that referenced
this pull request
Oct 14, 2026
* Fix Minkowski distance P sampling and zero components Minkowski P was sampled at the per-cell offset vector rather than the input position, so a connected generator lost its spatial variation and was evaluated for every cell distance calculation. Sample it once at the input position, only when Minkowski is selected. FS::Pow( 0, p ) returns 1, so zero distance components contributed 1 instead of 0, mask those out. * Bump FastSIMD for the Pow and Log fixes, drop PowNonNegative FS::Pow now returns 0 for a zero base (Auburn/FastSIMD#10), so the local PowNonNegative workaround is no longer needed. The Log fix in the same bump also removes most of the remaining Minkowski error.
This was referenced Oct 14, 2026
Merged
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.
Problem
Two bugs in the generic
FS::LogandFS::Pow(ToolSet/Generic/Functions.h). Every feature set uses this code except relaxed SCALAR, which callsstd::logandstd::pow.Logmultiplied a term in instead of adding it. The Cepheslogfstep isy += e * -2.12194440e-4f, but the code hady *= .... That scaled away the polynomial correction, so the result was roughlyx - x²/2 + e·ln2. The error is worst for inputs near 1.Pow( 0, p )returned 1.PowisExp( pow * Log( value ) ), andLogmasks inputs ≤ 0 to 0, so a zero base gaveExp( 0 ) = 1instead of 0.FastNoise2's Minkowski distance hit both bugs. A zero distance component added 1 instead of 0, and P=2 differed from Euclidean by up to 0.7% even after that was worked around. This change lets Auburn/FastNoise2#193 drop its local
PowNonNegativeworkaround after a pin bump.Fix
Log:y *= e * -2.12194440e-4f→y += e * -2.12194440e-4f, matching Cepheslogfandsse_mathfun'slog_ps.Pow:Masked( value > 0, Exp( pow * Log( value ) ) ), sovalue <= 0returns 0. This is correct for0^pwhenp > 0.Behaviour change
Logoutput changes for all inputs, towards the correct value.Powwithvalue <= 0now returns 0 instead of 1. This also makes0^0and0^pwithp < 0return 0, wherestd::powgives 1 and inf. Previously everyvalue <= 0case returned 1, which was wrong forp > 0.Testing
I added an
f32 pow zero basetest. It sets half the bases to 0, usespin [0.1, 8], and keeps ranges insideExp's clamp. Its relaxed scalar variant usesstd::pow, which is what catches the bug.I ran the test suite on a Ryzen 9 7950X (SCALAR, SSE2, SSE4.1, AVX2, AVX512, plus RELAXED variants) with MSVC 17.14 and clang-cl. The relaxed scalar build uses
std::logandstd::pow; this table compares it against the generic code (MSVC):f32 logf32 pow zero base(new)f32 powExpclampThe non-relaxed SIMD feature sets match scalar exactly, before and after.
Not changed
These failures already exist on
masterand are unrelated to this PR:f32 powstill fails where results go paste^±88.38.Expclamps there, whilestd::powreturns inf or a denormal. Every remainingf32 powfailure is in that region.f32 log2(theTrig.himplementation, which is separate) is inaccurate near 1.f32 modulusfailures.