From 2aa92ecffa2122dd22530e751f1cfc61caade1cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 5 Dec 2018 15:09:29 +0100 Subject: [PATCH] [apps] Add a proof for CurveViewRange::computeGridUnit's algorithm --- apps/shared/curve_view_range.cpp | 92 ++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 4 deletions(-) diff --git a/apps/shared/curve_view_range.cpp b/apps/shared/curve_view_range.cpp index 031830fd7..b539f3e8a 100644 --- a/apps/shared/curve_view_range.cpp +++ b/apps/shared/curve_view_range.cpp @@ -27,15 +27,99 @@ float CurveViewRange::computeGridUnit(Axis axis, float min, float max) { constexpr int unitsCount = 3; float units[unitsCount] = {k_smallGridUnitMantissa, k_mediumGridUnitMantissa, k_largeGridUnitMantissa}; for (int k = 0; k < unitsCount; k++) { - float unit = units[k]; - int b1 = std::floor(std::log10(d/(unit*maxNumberOfUnits))); - int b2 = std::floor(std::log10(d/(unit*minNumberOfUnits))); + float currentA = units[k]; + int b1 = std::floor(std::log10(d/(currentA*maxNumberOfUnits))); + int b2 = std::floor(std::log10(d/(currentA*minNumberOfUnits))); if (b1 != b2) { b = b2; - a = unit; + a = currentA; } } return a*std::pow(10.0f,b); + + /* Proof of the algorithm: + * + * We want to find gridUnit = a*10^b, with a in {1; 2; 5} and b an integer + * We want: minNumberOfUnits <= range/gridUnit < maxNumberOfUnits + * + * A solution thus needs to verify: + * + * minNumberOfUnits/range <= 1/(a*10^b) < maxNumberOfUnits/range + * => range/minNumberOfUnits >= a*10^b > range/maxNumberOfUnits + * => range/(a*minNumberOfUnits) >= 10^b > range/(a*maxNumberOfUnits) + * => log10(range/(a*minNumberOfUnits)) >= b > log10(range/(a*maxNumberOfUnits)) + * => (1) log10(range/(a*maxNumberOfUnits)) < b <= log10(range/(a*minNumberOfUnits)) + * And, because b must be an integer, + * => floor(log10(range/(a*maxNumberOfUnits))) != floor(log10(range/(a*minNumberOfUnits))) + * The solution is then b = floor(log10(range/(a*minNumberOfUnits))) + * + * Is there always at least one solution ? + * + * (1) also gives: + * E1 = log10(range)-log10(a)-log10(maxNumberOfUnits) < b <= log10(range)-log10(a)-log10(maxNumberOfUnits) = E2 + * + * Let's compute E2-E1: + * E2-E1 = log10(maxNumberOfUnits) - log10(minNumberOfUnits) + * For minNumberOfUnits=7 and maxNumberOfUnits=18, E2-E1 = 0.41... + * For minNumberOfUnits=5 and maxNumberOfUnits=13, E2-E1 = 0.41... + * + * Let's compute the union of the [E1;E2] for a in {1; 2; 5}: + * [E1;E2 for a=1] U [E1;E2 for a=2] U [E1;E2 for a=5] + * = [e1;e2] U [e1-log10(2); e2-log10(2)] U [e1-log10(5); e2-log10(5)] + * = [e1;e2] U [e1-0.3; e2-0.3] U [e1-0.7; e2-0.7] + * = [e1-0.7; e2-0.7] U [e1-0.3; e2-0.3] U [e1;e2] + * = [e1-0.7; e2] because e2-0.7 > e1-0.3 as e2-e1 > 0.7-0.3 and e2-e1 = E2-E1 = 0.41... + * and e2-0.3 > e1 as e2-e1 > 0.3 + * + * The union of the [E1;E2] for a in {1; 2; 5} is an interval of size + * e2-e1+0.7 = 1.1 > 1. + * We will thus always have at least one a in {1; 2; 5} for which E1 and E2 + * are on each side of an integer. + * + * Let's make a drawing. + * + * n n+1 n+2 n+3 n+4 n+5 + * |.........|.........|.........|.........|.........|... + * E1^---^E2 + * 0.41 + * * + * To have a solution, we need E1 and E2 to be on each side of an integer. + * + * -------------------------------------------------------------------------------------------- + * -------------------------------------------------------------------------------------------- + * + * If e1 - floor(e1) > 1-(e2-e1) = 0.58..., a=1 is a solution + * + * n n+0.2 n+0.4 n+0.6 n+0.8 n+1 + * .........||....|....|....|....|....|....|....|....|....|....||... a=1 + * e1^--------------------^e2 + * + * -------------------------------------------------------------------------------------------- + * -------------------------------------------------------------------------------------------- + * + * If log10(5)-(e2-e1) = 0.29... < e1 - floor(e1) < log10(5) = 0.69..., a=5 is a solution + * + * n n+0.2 n+0.4 n+0.6 n+0.8 n+1 + * .........||....|....|....|....|....|....|....|....|....|....||... + * e1^--------------------^e2 + * + * n n+0.2 n+0.4 n+0.6 n+0.8 n+1 + * .........||....|....|....|....|....|....|....|....|....|....||... a=5 + * E1^--------------------^E2 <- shift by log10(5) = 0.7 + * + * -------------------------------------------------------------------------------------------- + * -------------------------------------------------------------------------------------------- + * + * If e1 - floor(e1) < log10(2) = 0.3..., a=2 is a solution + * n n+0.2 n+0.4 n+0.6 n+0.8 n+1 + * .........||....|....|....|....|....|....|....|....|....|....||... + * e1^--------------------^e2 + * + * n n+0.2 n+0.4 n+0.6 n+0.8 n+1 + * .........||....|....|....|....|....|....|....|....|....|....||... a=2 + * E1^--------------------^E2 <- shift by log10(2) = 0.3 + * + * */ } }