void theta::fill_mode_support(theta::ParValues & mode, std::map<theta::ParId, std::pair<double, double> > & support, const theta::Distribution & d){ ParIds pids = d.get_parameters(); d.mode(mode); theta_assert(mode.contains_all(pids)); for(ParIds::const_iterator p_it=pids.begin(); p_it!=pids.end(); ++p_it){ support[*p_it] = d.support(*p_it); } }
double brent(const FT & f, double a, double b, double xtol, double fa, double fb, double f_accuracy = 1e-7, unsigned int limit = 10000){ if(fabs(fa) <= f_accuracy) return a; if(fabs(fb) <= f_accuracy) return b; theta_assert(fa * fb < 0.0); if(fabs(fa) < fabs(fb)){ std::swap(fa, fb); std::swap(a, b); } double d = 0.0; double c = a; double fc = fa; bool mflag = true; for(unsigned int i=0; i < limit; ++i){ if(fabs(a-b) <= xtol){ return (a + b) / 2; } if(fabs(fa) <= f_accuracy) return a; if(fabs(fb) <= f_accuracy) return b; double s; if(fabs(fa - fc) < f_accuracy && fabs(fb - fc) < f_accuracy){ s = a * fb * fc / (fa - fb) / (fa - fc) + b * fa * fc / (fb - fa) / (fb - fc) + c * fa * fb / (fc - fa) / (fc - fb); } else{ s = b - fb * (b - a) / (fb - fa); } double tmp2 = (3 * a + b) / 4; if (!((s > tmp2 && s < b) || (s < tmp2 && s > b)) || (mflag && fabs(s - b) >= fabs(b - c) / 2) || (!mflag && fabs(s - b) >= fabs(c - d) / 2) || (mflag && fabs(b - c) < xtol) || (!mflag && (fabs(c - d) < xtol)) ){ s = (a + b) / 2; mflag = true; } else{ mflag = false; } double fs = f(s); d = c; c = b; fc = fb; if (fa * fs < 0) { b = s; fb = fs; } else { a = s; fa = fs; } if(fabs(fa) < fabs(fb)){ std::swap(fa, fb); std::swap(a, b); } } throw theta::Exception("brent: Too many iterations"); }
double secant(double x_low, double x_high, double x_accuracy, double f_x_low, double f_x_high, double f_accuracy, const T & function, int limit_depth = 500){ theta_assert(std::isfinite(x_low) && std::isfinite(x_high)); theta_assert(x_low <= x_high); theta_assert(std::isfinite(f_x_low) && std::isfinite(f_x_high)); theta_assert(limit_depth > 0); if(f_x_low * f_x_high >= 0) throw std::invalid_argument("secant: function values have the same sign!"); if(std::fabs(f_x_low) <= f_accuracy) return x_low; if(std::fabs(f_x_high) <= f_accuracy) return x_high; const double old_interval_length = x_high - x_low; //calculate intersection point for secant method: double x_intersect = x_low - (x_high - x_low) / (f_x_high - f_x_low) * f_x_low; theta_assert(x_intersect >= x_low); theta_assert(x_intersect <= x_high); if(old_interval_length < x_accuracy){ return x_intersect; } double f_x_intersect = function(x_intersect); double f_mult = f_x_low * f_x_intersect; //fall back to bisection if the new interval would not be much smaller: double new_interval_length = f_mult < 0 ? x_intersect - x_low : x_high - x_intersect; if(new_interval_length > 0.5 * old_interval_length){ x_intersect = 0.5*(x_low + x_high); f_x_intersect = function(x_intersect); f_mult = f_x_low * f_x_intersect; } if(f_mult < 0){ return secant(x_low, x_intersect, x_accuracy, f_x_low, f_x_intersect, f_accuracy, function, limit_depth - 1); } else if(f_mult > 0.0){ return secant(x_intersect, x_high, x_accuracy, f_x_intersect, f_x_high, f_accuracy, function, limit_depth - 1); } //it can actually happen that we have 0.0. In this case, return the x value for // the smallest absolute function value: else{ f_x_intersect = fabs(f_x_intersect); f_x_low = fabs(f_x_low); f_x_high = fabs(f_x_high); if(f_x_low < f_x_high && f_x_low < f_x_intersect) return x_low; if(f_x_high < f_x_intersect) return x_high; return x_intersect; } }
virtual void operator()(const T& t) const { theta_assert(h0.get_nbins() == t.get_nbins()); h0.add_with_coeff(coeff, t); }