Skip to content

Instantly share code, notes, and snippets.

@giordi91
Created September 29, 2018 20:39
Show Gist options
  • Save giordi91/ae258be869fec7e8c27c3d8357d09a3d to your computer and use it in GitHub Desktop.
Save giordi91/ae258be869fec7e8c27c3d8357d09a3d to your computer and use it in GitHub Desktop.
#pragma once
#include <limits>
namespace cpp_tools {
namespace numerical {
template <typename T> using singleVariableFunction = float (*)(T xValue);
struct ErrorReport {};
template <typename T>
inline bool ensureRangeSign(T startRange, T endRange,
singleVariableFunction<T> function) {
T yStart = function(startRange);
T yEnd = function(endRange);
return (!((yStart > 0) & (yEnd > 0))) & (!((yStart < 0) & (yEnd < 0)));
}
template <typename T>
inline bool rootValueMeetsAccuracyRequirements(T startRange, T endRange,
int accuracy) {
float denominator = powf(10.0f, accuracy);
float thresholdFloat = 1.0f / denominator;
return abs(endRange - startRange) < thresholdFloat;
}
template <typename T>
inline T processFinalResultRounding(T startRange, T endRange,
singleVariableFunction<T> function,
ErrorReport *report) {
T midRange = (startRange + endRange) * 0.5f;
T midRangeFloor = (std::floorf(midRange*1000.0f)) / 1000.0f;
T midRangeCeil= (std::ceilf(midRange*1000.0f)) / 1000.0f;
T midRangeFloorCeil = (midRangeFloor+ midRangeCeil) * 0.5f;
bool lowSplit = ensureRangeSign(midRangeFloor, midRangeFloorCeil, function);
return lowSplit ? startRange : endRange;
}
template <typename T>
T singleBisectRootFinder(T startRange, T endRange, singleVariableFunction<T> function,
int accuracy, int maxIteration = 100,
ErrorReport *errorReport = nullptr) {
const T nanValue = std::numeric_limits<T>::quiet_NaN();
if (!ensureRangeSign<T>(startRange, endRange, function)) {
return nanValue;
}
T midRange = (startRange + endRange) * 0.5f;
// lets start the iteration
T currentValue = function(midRange);
if (rootValueMeetsAccuracyRequirements(startRange, endRange, accuracy)) {
return processFinalResultRounding(startRange, endRange, function, errorReport);
}
bool lowSplit = ensureRangeSign(startRange, midRange, function);
bool highSplit = ensureRangeSign(midRange, endRange, function);
startRange = lowSplit ? startRange : midRange;
endRange = highSplit ? endRange : midRange;
int iteration = 1;
while (true & (iteration < maxIteration)) {
if (rootValueMeetsAccuracyRequirements(startRange, endRange, accuracy)) {
return processFinalResultRounding(startRange, endRange, function, errorReport);
}
midRange = (startRange + endRange) * 0.5f;
// lets start the iteration
currentValue = function(midRange);
bool lowSplit = ensureRangeSign(startRange, midRange, function);
bool highSplit = ensureRangeSign(midRange, endRange, function);
startRange = lowSplit ? startRange : midRange;
endRange = highSplit ? endRange : midRange;
iteration++;
}
T returnValue = midRange;
return returnValue;
}
} // namespace numerical
} // namespace cpp_tools
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment