Created
September 29, 2018 20:39
-
-
Save giordi91/ae258be869fec7e8c27c3d8357d09a3d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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