int main() { StructEquationSolve equationSolver; StructEquationSolve* pSolver; pSolver = &equationSolver; //equationSolver.solveEquation(); //pSolver->solveEquation(); StructEquationSolve& citeSolver = equationSolver; citeSolver.solveEquation(); StructEquationParameter equationParamIn; StructEquationSolution equationSolutionOut; string message = "Project Lesson08_Module_Function: print q to quit!"; showPromptMessage( message ); solveEquation(equationParamIn, equationSolutionOut); /* inputParameter(equationParamIn); bool bValid = validateParameter(equationParamIn); if (bValid) { solveEquation(equationParamIn, equationSolutionOut); outputResult(equationSolutionOut); } else { showPromptMessage("No Solutions!"); } */ return 0; }
void addBitangent( const real_t l, const real_t r, bool overestimate, const real_t epsilon ) { bitangent bitan; bitan.start = a; bool start_fixed = b - a <= epsilon; real_t end = r; bool end_fixed = r - l <= epsilon; if( start_fixed && end_fixed ) // if both fixed the secant will be used { real_t y1 = ( *this )( bitan.start ); real_t y2 = curve( end ); real_t slope = ( y2 - y1 ) / ( end - bitan.start ); //this case happens when the function is concave and should be underestimated //or it is convex and should be overestimated. Then the secant of the endpoints is //used as estimator bitan.line.setCoeff( 1, slope ); bitan.line.setCoeff( 0, y2 - slope * r ); addBitangent( end, bitan ); return; } auto curveDeriv = differentiate<1>( curve ); SimplePolynomial< 0, real_t > rhs; real_t y1 = ( *this )( bitan.start ); real_t y2 = curve( end ); //compute slope of line connecting the function values real_t slope = ( y2 - y1 ) / ( end - bitan.start ); while( 1 ) { //check for termination, i.e. slope matches curve slope at both parts //or one of the parts is fixed if( ( start_fixed || std::abs( curveDeriv( bitan.start ) - slope ) <= epsilon ) && ( end_fixed || std::abs( curveDeriv( end ) - slope ) <= epsilon ) ) { bitan.line.setCoeff( 1, slope ); // use current slope bitan.line.setCoeff( 0, y2 - end * slope ); // compute constant value using y2 = end*slope+c <=> c = y2 - end*slope //add tangent addBitangent( end, bitan ); return; } //if not terminating compute new endpoints for tangent rhs.setCoeff( 0, slope ); if( !start_fixed ) { bool changed = false; std::vector<real_t> sol = curveDeriv.solveEquation( rhs, a, b, epsilon ); bool nosol = true; //filter out solutions that are cut off by current tangents //after that there should be 1 solution or 0. for( auto i = sol.begin(); i != sol.end(); ++i ) { interval_t interv = this->findInterval( *i ); if( interv == bitangents.end() ) { nosol = false; if( bitan.start != *i ) { bitan.start = *i; changed = true; } break; } } if( nosol ) // if there was no solution, i.e. all solutions were cut off by current tagents we choose an interval endpoint { real_t newstart; if( curve( a ) - a * slope > curve( b ) - b * slope ) newstart = overestimate ? a : b; else newstart = overestimate ? b : a; if( newstart != bitan.start ) { changed = true; bitan.start = newstart; } } if( changed ) { y1 = ( *this )( bitan.start ); slope = ( y2 - y1 ) / ( end - bitan.start ); } else { start_fixed = true; } } if( !end_fixed ) { bool changed = false; //should always have size 1 or 0 since curve is convex/concave in [l,r] std::vector<real_t> sol = curveDeriv.solveEquation( rhs, l, r, epsilon ); if( sol.empty() ) { real_t newend; if( curve( l ) - slope * l > curve( r ) - slope * r ) newend = overestimate ? l : r; else newend = overestimate ? r : l; if( newend != end ) { end = newend; changed = true; } } else { if( end != sol[0] ) { end = sol[0]; changed = true; } } if( changed ) { y2 = curve( end ); slope = ( y2 - y1 ) / ( end - bitan.start ); } else { end_fixed = true; } } } }