[poincare/zoom] Accelerate normal range search

Change-Id: I4a7f2e024ca82a3996ad3e395c8f62ca4170ec9e
This commit is contained in:
Gabriel Ozouf
2020-10-16 15:06:49 +02:00
committed by Émilie Feral
parent 31e694f41a
commit f491be2db5
2 changed files with 10 additions and 5 deletions

View File

@@ -22,7 +22,7 @@ public:
static bool InterestingRangesForDisplay(ValueAtAbscissa evaluation, float * xMin, float * xMax, float * yMin, float * yMax, float tMin, float tMax, Context * context, const void * auxiliary);
/* Find the best Y range to display the function on [xMin, xMax], but crop
* the values that are outside of the function's order of magnitude. */
static void RefinedYRangeForDisplay(ValueAtAbscissa evaluation, float xMin, float xMax, float * yMin, float * yMax, Context * context, const void * auxiliary);
static void RefinedYRangeForDisplay(ValueAtAbscissa evaluation, float xMin, float xMax, float * yMin, float * yMax, Context * context, const void * auxiliary, int sampleSize = k_sampleSize);
/* Find the best window to display functions, with a specified ratio
* between X and Y. Usually used to find the most fitting orthonormal range. */
static void RangeWithRatioForDisplay(ValueAtAbscissa evaluation, float yxRatio, float * xMin, float * xMax, float * yMin, float * yMax, Context * context, const void * auxiliary);

View File

@@ -167,19 +167,19 @@ bool Zoom::InterestingRangesForDisplay(ValueAtAbscissa evaluation, float * xMin,
return true;
}
void Zoom::RefinedYRangeForDisplay(ValueAtAbscissa evaluation, float xMin, float xMax, float * yMin, float * yMax, Context * context, const void * auxiliary) {
void Zoom::RefinedYRangeForDisplay(ValueAtAbscissa evaluation, float xMin, float xMax, float * yMin, float * yMax, Context * context, const void * auxiliary, int sampleSize) {
/* This methods computes the Y range that will be displayed for cartesian
* functions and sequences, given an X range (xMin, xMax) and bounds yMin and
* yMax that must be inside the Y range.*/
assert(yMin && yMax);
float sampleYMin = FLT_MAX, sampleYMax = -FLT_MAX;
const float step = (xMax - xMin) / (k_sampleSize - 1);
const float step = (xMax - xMin) / (sampleSize - 1);
float x, y;
float sum = 0.f;
int pop = 0;
for (int i = 1; i < k_sampleSize; i++) {
for (int i = 1; i < sampleSize; i++) {
x = xMin + i * step;
y = evaluation(x, context, auxiliary);
if (!std::isfinite(y)) {
@@ -222,13 +222,18 @@ void Zoom::RangeWithRatioForDisplay(ValueAtAbscissa evaluation, float yxRatio, f
constexpr float rangeMagnitudeWeight = 0.2f;
constexpr float maxMagnitudeDifference = 2.f;
/* RefinedYRange for display, by default, evaluates the function 80 times,
* and we call it 21 times. As we only need a rough estimate of the range to
* compare it to the others, we save some time by only sampling the function
* 20 times. */
constexpr int sampleSize = k_sampleSize / 4;
float bestGrade = FLT_MAX;
float xMagnitude = k_minimalDistance;
float yMinRange = FLT_MAX, yMaxRange = -FLT_MAX;
while (xMagnitude < k_maximalDistance) {
for(const float unit : units) {
const float xRange = unit * xMagnitude;
RefinedYRangeForDisplay(evaluation, -xRange, xRange, &yMinRange, &yMaxRange, context, auxiliary);
RefinedYRangeForDisplay(evaluation, -xRange, xRange, &yMinRange, &yMaxRange, context, auxiliary, sampleSize);
float currentRatio = (yMaxRange - yMinRange) / (2 * xRange);
float grade = std::fabs(std::log(currentRatio / yxRatio));
/* When in doubt, favor ranges between [-1, 1] and [-10, 10] */