summaryrefslogtreecommitdiffstats
path: root/parameter
diff options
context:
space:
mode:
authorDavid Wagner <david.wagner@intel.com>2014-03-11 14:20:53 +0100
committerMattijs Korpershoek <mattijsx.korpershoek@intel.com>2014-06-25 10:52:26 +0200
commit59cc1e33810c55e6fa1e3bd320e1cf29e24d23be (patch)
tree632b95d1026ff684b3b37627a17db2922c0f74e7 /parameter
parent8ef87a1fe5d2f05557856efa6faf070bb9b03337 (diff)
downloadexternal_parameter-framework-59cc1e33810c55e6fa1e3bd320e1cf29e24d23be.zip
external_parameter-framework-59cc1e33810c55e6fa1e3bd320e1cf29e24d23be.tar.gz
external_parameter-framework-59cc1e33810c55e6fa1e3bd320e1cf29e24d23be.tar.bz2
Correct FixedPointParameter display precision
BZ: 176178 Explain the precision computation (m * log10(2)): For a Qn.m number, the step between each storable number is 2^(-m). Hence, on a decimal representation, the Dth digit after the decimal point can take all possible values (1..9) - meaning that it is significant - only if 2^(-m) <= 10^(-D) -m <= log2(10^(-D)) -m <= log10(10^(-D)) / log10(2) -m <= -D / log10(2) m * log10(2) >= D Conversly, the Dth digit can be represented if D <= m * log10(2) We add 1 to the precision in order to display the digit right after the last significant digit. This will lead to oddities such as: $ setParameter /Test/test/f32_Q8.23 0.1234569 $ getParameter /Test/test/f32_Q8.23 > 0.1234570 but it will avoid modifying raw values when converting from string to Q-format and back to string. Also, use std::setprecision() on the stream instead of manually truncating the displayed number. Change-Id: Ief2a7daabf4505ae4312e79036b0374f53368cac Signed-off-by: David Wagner <david.wagner@intel.com>
Diffstat (limited to 'parameter')
-rw-r--r--parameter/FixedPointParameterType.cpp27
1 files changed, 24 insertions, 3 deletions
diff --git a/parameter/FixedPointParameterType.cpp b/parameter/FixedPointParameterType.cpp
index 6a873b3..0f9369d 100644
--- a/parameter/FixedPointParameterType.cpp
+++ b/parameter/FixedPointParameterType.cpp
@@ -197,9 +197,27 @@ bool CFixedPointParameterType::fromBlackboard(string& strValue, const uint32_t&
double dData = asDouble(iData);
// Set up the precision of the display and notation type
+ // For a Qn.m number, the step between each storable number is 2^(-m).
+ // Hence, on a decimal representation, the Dth digit after the decimal
+ // point can take all possible values (1..9) - meaning that it is
+ // significant - only if
+ //
+ // 2^(-m) <= 10^(-D)
+ // -m <= log2(10^(-D))
+ // -m <= log10(10^(-D)) / log10(2)
+ // -m <= -D / log10(2)
+ // m * log10(2) >= D
+ //
+ // Conversly, the Dth digit can be represented if
+ //
+ // D <= m * log10(2)
+ //
+ // Since floor(x) <= x, we can write (replacing D with iPrecision and m
+ // with _uiFractional) this next line.
+ // (we add 1 to avoid losing precision even though this last digit is
+ // not 100% significant)
int iPrecision = (_uiFractional * log10(2.0)) + 1;
- int iFactor = pow(10.0, iPrecision);
- strStream << fixed << ((int64_t)(dData * iFactor)) / (double)iFactor;
+ strStream << fixed << setprecision(iPrecision) << dData;
}
strValue = strStream.str();
@@ -316,8 +334,11 @@ bool CFixedPointParameterType::checkValueAgainstRange(double dValue) const
int32_t CFixedPointParameterType::asInteger(double dValue) const
{
// Do the conversion
- int32_t iData = (int32_t)(dValue * (1UL << _uiFractional) + 0.5F - (double)(dValue < 0));
+ // For Qn.m number, multiply by 2^n and round to the nearest integer
+ int32_t iData = (int32_t)(round(dValue * (1UL << _uiFractional)));
// Left justify
+ // For a Qn.m number, shift 32 - (n + m + 1) bits to the left (the rest of
+ // the bits aren't used)
iData <<= getSize() * 8 - getUtilSizeInBits();
return iData;