basegfx/source/color/bcolormodifier.cxx | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-)
New commits: commit 23e158e4c35a9f548010827adfccccd70d1928f6 Author: Noel Grandin <noelgran...@gmail.com> AuthorDate: Fri Apr 25 08:06:05 2025 +0200 Commit: Noel Grandin <noelgran...@gmail.com> CommitDate: Fri Apr 25 09:35:36 2025 +0200 tdf#165595 speedup BColorModifier_gamma which shows up heavily on this profile. In this case we don't need perfection and we can use a fast approximation for std::pow. Thanks to the binary representation of float numbers, this new code reduces to some basic bit-twiddling. Change-Id: I064588f65cf8f5973ba45545fba9c5fe66500e37 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184602 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/basegfx/source/color/bcolormodifier.cxx b/basegfx/source/color/bcolormodifier.cxx index e0e0ebbd6203..360a41db9285 100644 --- a/basegfx/source/color/bcolormodifier.cxx +++ b/basegfx/source/color/bcolormodifier.cxx @@ -324,14 +324,39 @@ namespace basegfx return mfValue == pCompare->mfValue; } + /** + A fast and approximate std::pow(), good enough for gamma calculations. + + std::pow() is basically implemented using log's: + pow(a,b) = x^(logx(a) * b) + So we need a fast log and fast exponent - it doesn't matter what x is so we use 2. + pow(a,b) = 2^(log2(a) * b) + The trick is that a floating point number is already in a log style format: + a = M * 2^E + Taking the log of both sides gives: + log2(a) = log2(M) + E + or more simply: + log2(a) ~= E + In other words if we take the floating point representation of a number, + and extract the Exponent we've got something that's a good starting point as its log. + And then we can do: + pow(a,b) = 2^(E * b) + */ + static double fast_pow(double a, double b) + { + int a_exp; + std::frexp(a, &a_exp); + return std::exp2(a_exp * b); + } + ::basegfx::BColor BColorModifier_gamma::getModifiedColor(const ::basegfx::BColor& aSourceColor) const { if(mbUseIt) { ::basegfx::BColor aRetval( - pow(aSourceColor.getRed(), mfInvValue), - pow(aSourceColor.getGreen(), mfInvValue), - pow(aSourceColor.getBlue(), mfInvValue)); + fast_pow(aSourceColor.getRed(), mfInvValue), + fast_pow(aSourceColor.getGreen(), mfInvValue), + fast_pow(aSourceColor.getBlue(), mfInvValue)); aRetval.clamp(); return aRetval;