TEST(AgradFwdLog1pExp,Fvar) { using stan::agrad::fvar; using stan::math::log1p_exp; using std::exp; fvar<double> x(0.5,1.0); fvar<double> y(1.0,2.0); fvar<double> z(2.0,3.0); fvar<double> a = log1p_exp(x); EXPECT_FLOAT_EQ(log1p_exp(0.5), a.val_); EXPECT_FLOAT_EQ(exp(0.5) / (1 + exp(0.5)), a.d_); fvar<double> b = log1p_exp(y); EXPECT_FLOAT_EQ(log1p_exp(1.0), b.val_); EXPECT_FLOAT_EQ(2.0 * exp(1.0) / (1 + exp(1.0)), b.d_); fvar<double> a2 = log(1+exp(x)); EXPECT_FLOAT_EQ(a.d_, a2.d_); fvar<double> b2 = log(1+exp(y)); EXPECT_FLOAT_EQ(b.d_, b2.d_); }
TEST(AgradFwdLogDiffExp,Double_FvarFvarVar_1stDeriv) { using stan::agrad::fvar; using stan::agrad::var; using stan::math::log_diff_exp; using std::exp; double x(9.0); fvar<fvar<var> > y; y.val_.val_ = 6.0; y.d_.val_ = 1.0; fvar<fvar<var> > a = log_diff_exp(x,y); EXPECT_FLOAT_EQ(log_diff_exp(9.0,6.0), a.val_.val_.val()); EXPECT_FLOAT_EQ(0, a.val_.d_.val()); EXPECT_FLOAT_EQ(-exp(6.0) / (exp(9.0) - exp(6.0)), a.d_.val_.val()); EXPECT_FLOAT_EQ(0, a.d_.d_.val()); AVEC p = createAVEC(y.val_.val_); VEC g; a.val_.val_.grad(p,g); EXPECT_FLOAT_EQ(-exp(6.0) / (exp(9.0) - exp(6.0)), g[0]); }
TEST(AgradFvar, log1m_inv_logit){ using stan::agrad::fvar; using stan::math::log1m_inv_logit; using std::exp; fvar<double> x(0.5); fvar<double> y(-1.0); fvar<double> z(0.0); x.d_ = 1.0; y.d_ = 2.0; z.d_ = 3.0; fvar<double> a = log1m_inv_logit(x); EXPECT_FLOAT_EQ(log1m_inv_logit(0.5), a.val_); EXPECT_FLOAT_EQ(-1.0 * exp(0.5) / (1 + exp(0.5)), a.d_); fvar<double> b = log1m_inv_logit(y); EXPECT_FLOAT_EQ(log1m_inv_logit(-1.0), b.val_); EXPECT_FLOAT_EQ(-2.0 * exp(-1.0) / (1 + exp(-1.0)), b.d_); fvar<double> c = log1m_inv_logit(z); EXPECT_FLOAT_EQ(log1m_inv_logit(0.0), c.val_); EXPECT_FLOAT_EQ(-3.0 * exp(0.0) / (1 + exp(0.0)), c.d_); }
void test_exp(const int fuzzy_bits) { // Use at least 8 resolution bits. // Use at least 7 range bits. BOOST_STATIC_ASSERT(-FixedPointType::resolution >= 8); BOOST_STATIC_ASSERT( FixedPointType::range >= 7); const FixedPointType a1(+1L ); const FloatPointType b1(+1L ); const FixedPointType a2(+2L ); const FloatPointType b2(+2L ); const FixedPointType a3(+4.375L); const FloatPointType b3(+4.375L); const FixedPointType a4(+1.125L); const FloatPointType b4(+1.125L); const FixedPointType a5(-1.125L); const FloatPointType b5(-1.125L); const FixedPointType a6(+0.875L); const FloatPointType b6(+0.875L); const FixedPointType a7(FixedPointType( 1) / 3); const FloatPointType b7(FloatPointType( 1) / 3); const FixedPointType a8(FixedPointType(11) / 10); const FloatPointType b8(FloatPointType(11) / 10); const FixedPointType a9(boost::math::constants::phi<FixedPointType>()); const FloatPointType b9(boost::math::constants::phi<FloatPointType>()); using std::exp; BOOST_CHECK_CLOSE_FRACTION(exp(a1), FixedPointType(exp(b1)), tolerance_maker<FixedPointType>(fuzzy_bits)); BOOST_CHECK_CLOSE_FRACTION(exp(a2), FixedPointType(exp(b2)), tolerance_maker<FixedPointType>(fuzzy_bits)); BOOST_CHECK_CLOSE_FRACTION(exp(a3), FixedPointType(exp(b3)), tolerance_maker<FixedPointType>(fuzzy_bits)); BOOST_CHECK_CLOSE_FRACTION(exp(a4), FixedPointType(exp(b4)), tolerance_maker<FixedPointType>(fuzzy_bits)); BOOST_CHECK_CLOSE_FRACTION(exp(a5), FixedPointType(exp(b5)), tolerance_maker<FixedPointType>(fuzzy_bits)); BOOST_CHECK_CLOSE_FRACTION(exp(a6), FixedPointType(exp(b6)), tolerance_maker<FixedPointType>(fuzzy_bits)); BOOST_CHECK_CLOSE_FRACTION(exp(a7), FixedPointType(exp(b7)), tolerance_maker<FixedPointType>(fuzzy_bits)); BOOST_CHECK_CLOSE_FRACTION(exp(a8), FixedPointType(exp(b8)), tolerance_maker<FixedPointType>(fuzzy_bits)); BOOST_CHECK_CLOSE_FRACTION(exp(a9), FixedPointType(exp(b9)), tolerance_maker<FixedPointType>(fuzzy_bits)); }
inline fvar<T> expm1(const fvar<T>& x) { using std::exp; return fvar<T>(expm1(x.val_), x.d_ * exp(x.val_)); }
int test_cv_vib() { using std::exp; const Scalar Mm_N = 14.008e-3; //in SI kg/mol const Scalar Mm_O = 16e-3; //in SI kg/mol const Scalar Mm_N2 = 2.L * Mm_N; //in SI kg/mol const Scalar Mm_O2 = 2.L * Mm_O; //in SI kg/mol const Scalar Mm_NO = Mm_O + Mm_N; //in SI kg/mol std::vector<std::string> species_str_list; const unsigned int n_species = 5; species_str_list.reserve(n_species); species_str_list.push_back( "N2" ); species_str_list.push_back( "O2" ); species_str_list.push_back( "N" ); species_str_list.push_back( "O" ); species_str_list.push_back( "NO" ); Antioch::ChemicalMixture<Scalar> chem_mixture( species_str_list ); // Can we instantiate it? Antioch::StatMechThermodynamics<Scalar> sm_thermo( chem_mixture ); // Mass fractions std::vector<Scalar> mass_fractions( 5, 0.2 ); mass_fractions[0] = 0.5; mass_fractions[1] = 0.2; mass_fractions[2] = 0.1; mass_fractions[3] = 0.1; mass_fractions[4] = 0.1; const Scalar R_N2 = Antioch::Constants::R_universal<Scalar>() / Mm_N2; const Scalar R_O2 = Antioch::Constants::R_universal<Scalar>() / Mm_O2; const Scalar R_NO = Antioch::Constants::R_universal<Scalar>() / Mm_NO; const Scalar th0_N2 = 3.39500e+03; // degeneracy = 1 const Scalar th0_O2 = 2.23900e+03; // degeneracy = 1 const Scalar th0_NO = 2.81700e+03; // degeneracy = 1 // Tv const Scalar Tv = 1000.0; const Scalar tol = std::numeric_limits<Scalar>::epsilon() * 2; const Scalar ztol = std::numeric_limits<Scalar>::epsilon(); int return_flag = 0; Scalar cv_vib_mix = 0.0; // N2 { Scalar cv_vib_N2 = sm_thermo.cv_vib (0, Tv); const Scalar expv = exp(th0_N2/Tv); const Scalar expvmi = expv - Scalar(1.0); Scalar cv_vib_N2_true = R_N2*th0_N2*th0_N2*expv/expvmi/expvmi/Tv/Tv; if( !test_relative(cv_vib_N2, cv_vib_N2_true, tol) ) { std::cerr << std::scientific << std::setprecision(20); std::cerr << "Error: Mismatch in cv_vib for N2." << "\n Expected = " << cv_vib_N2_true << "\n Computed = " << cv_vib_N2 << "\n Diff = " << cv_vib_N2_true - cv_vib_N2 << std::endl; return_flag += 1; } cv_vib_mix += mass_fractions[0]*cv_vib_N2_true; } // O2 { Scalar cv_vib_O2 = sm_thermo.cv_vib (1, Tv); const Scalar expv = exp(th0_O2/Tv); const Scalar expvmi = expv - Scalar(1.0); Scalar cv_vib_O2_true = R_O2*th0_O2*th0_O2*expv/expvmi/expvmi/Tv/Tv; if( !test_relative(cv_vib_O2, cv_vib_O2_true, tol) ) { std::cerr << std::scientific << std::setprecision(20); std::cerr << "Error: Mismatch in cv_vib for O2." << "\n Expected = " << cv_vib_O2_true << "\n Computed = " << cv_vib_O2 << "\n Diff = " << cv_vib_O2_true - cv_vib_O2 << std::endl; return_flag += 1; } cv_vib_mix += mass_fractions[1]*cv_vib_O2_true; } // O { Scalar cv_vib_O = sm_thermo.cv_vib (2, Tv); if( !test_zero(cv_vib_O, ztol) ) { std::cerr << std::scientific << std::setprecision(20); std::cerr << "Error: Mismatch in cv_vib for O." << "\n Expected = " << Scalar(0.0) << "\n Computed = " << cv_vib_O << "\n Diff = " << cv_vib_O << std::endl; return_flag += 1; } // cv_vib_mix += 0.0; } // N { Scalar cv_vib_N = sm_thermo.cv_vib (3, Tv); if( !test_zero(cv_vib_N, ztol) ) { std::cerr << std::scientific << std::setprecision(20); std::cerr << "Error: Mismatch in cv_vib for N." << "\n Expected = " << Scalar(0.0) << "\n Computed = " << cv_vib_N << "\n Diff = " << cv_vib_N << std::endl; return_flag += 1; } // cv_vib_mix += 0.0; } // NO { Scalar cv_vib_NO = sm_thermo.cv_vib (4, Tv); const Scalar expv = exp(th0_NO/Tv); const Scalar expvmi = expv - Scalar(1.0); Scalar cv_vib_NO_true = R_NO*th0_NO*th0_NO*expv/expvmi/expvmi/Tv/Tv; if( !test_relative(cv_vib_NO, cv_vib_NO_true, tol*4) ) { std::cerr << std::scientific << std::setprecision(20); std::cerr << "Error: Mismatch in cv_vib for NO." << "\n Expected = " << cv_vib_NO_true << "\n Computed = " << cv_vib_NO << "\n Diff = " << cv_vib_NO_true - cv_vib_NO << std::endl; return_flag += 1; } cv_vib_mix += mass_fractions[4]*cv_vib_NO_true; } // mixture { Scalar cv = sm_thermo.cv_vib(Tv, mass_fractions); if( !test_relative(cv, cv_vib_mix, tol) ) { std::cerr << std::scientific << std::setprecision(20); std::cerr << "Error: Mismatch in mixture cv_vib." << "\n Expected = " << cv_vib_mix << "\n Computed = " << cv << "\n Diff = " << cv - cv_vib_mix << std::endl; return_flag += 1; } } return return_flag; }
typename return_type<T_y, T_loc, T_scale, T_shape>::type skew_normal_log(const T_y& y, const T_loc& mu, const T_scale& sigma, const T_shape& alpha) { static const char* function("skew_normal_log"); typedef typename stan::partials_return_type<T_y, T_loc, T_scale, T_shape>::type T_partials_return; using std::log; using stan::is_constant_struct; using std::exp; if (!(stan::length(y) && stan::length(mu) && stan::length(sigma) && stan::length(alpha))) return 0.0; T_partials_return logp(0.0); check_not_nan(function, "Random variable", y); check_finite(function, "Location parameter", mu); check_finite(function, "Shape parameter", alpha); check_positive(function, "Scale parameter", sigma); check_consistent_sizes(function, "Random variable", y, "Location parameter", mu, "Scale parameter", sigma, "Shape paramter", alpha); if (!include_summand<propto, T_y, T_loc, T_scale, T_shape>::value) return 0.0; OperandsAndPartials<T_y, T_loc, T_scale, T_shape> operands_and_partials(y, mu, sigma, alpha); using std::log; VectorView<const T_y> y_vec(y); VectorView<const T_loc> mu_vec(mu); VectorView<const T_scale> sigma_vec(sigma); VectorView<const T_shape> alpha_vec(alpha); size_t N = max_size(y, mu, sigma, alpha); VectorBuilder<true, T_partials_return, T_scale> inv_sigma(length(sigma)); VectorBuilder<include_summand<propto, T_scale>::value, T_partials_return, T_scale> log_sigma(length(sigma)); for (size_t i = 0; i < length(sigma); i++) { inv_sigma[i] = 1.0 / value_of(sigma_vec[i]); if (include_summand<propto, T_scale>::value) log_sigma[i] = log(value_of(sigma_vec[i])); } for (size_t n = 0; n < N; n++) { const T_partials_return y_dbl = value_of(y_vec[n]); const T_partials_return mu_dbl = value_of(mu_vec[n]); const T_partials_return sigma_dbl = value_of(sigma_vec[n]); const T_partials_return alpha_dbl = value_of(alpha_vec[n]); const T_partials_return y_minus_mu_over_sigma = (y_dbl - mu_dbl) * inv_sigma[n]; const double pi_dbl = pi(); if (include_summand<propto>::value) logp -= 0.5 * log(2.0 * pi_dbl); if (include_summand<propto, T_scale>::value) logp -= log(sigma_dbl); if (include_summand<propto, T_y, T_loc, T_scale>::value) logp -= y_minus_mu_over_sigma * y_minus_mu_over_sigma / 2.0; if (include_summand<propto, T_y, T_loc, T_scale, T_shape>::value) logp += log(erfc(-alpha_dbl * y_minus_mu_over_sigma / std::sqrt(2.0))); T_partials_return deriv_logerf = 2.0 / std::sqrt(pi_dbl) * exp(-alpha_dbl * y_minus_mu_over_sigma / std::sqrt(2.0) * alpha_dbl * y_minus_mu_over_sigma / std::sqrt(2.0)) / (1 + erf(alpha_dbl * y_minus_mu_over_sigma / std::sqrt(2.0))); if (!is_constant_struct<T_y>::value) operands_and_partials.d_x1[n] += -y_minus_mu_over_sigma / sigma_dbl + deriv_logerf * alpha_dbl / (sigma_dbl * std::sqrt(2.0)); if (!is_constant_struct<T_loc>::value) operands_and_partials.d_x2[n] += y_minus_mu_over_sigma / sigma_dbl + deriv_logerf * -alpha_dbl / (sigma_dbl * std::sqrt(2.0)); if (!is_constant_struct<T_scale>::value) operands_and_partials.d_x3[n] += -1.0 / sigma_dbl + y_minus_mu_over_sigma * y_minus_mu_over_sigma / sigma_dbl - deriv_logerf * y_minus_mu_over_sigma * alpha_dbl / (sigma_dbl * std::sqrt(2.0)); if (!is_constant_struct<T_shape>::value) operands_and_partials.d_x4[n] += deriv_logerf * y_minus_mu_over_sigma / std::sqrt(2.0); } return operands_and_partials.value(logp); }
typename return_type<T_y, T_scale_succ, T_scale_fail>::type beta_cdf_log(const T_y& y, const T_scale_succ& alpha, const T_scale_fail& beta) { typedef typename stan::partials_return_type<T_y, T_scale_succ, T_scale_fail>::type T_partials_return; // Size checks if ( !( stan::length(y) && stan::length(alpha) && stan::length(beta) ) ) return 0.0; // Error checks static const char* function("stan::math::beta_cdf"); using stan::math::check_positive_finite; using stan::math::check_not_nan; using stan::math::check_nonnegative; using stan::math::check_less_or_equal; using boost::math::tools::promote_args; using stan::math::check_consistent_sizes; using stan::math::value_of; T_partials_return cdf_log(0.0); check_positive_finite(function, "First shape parameter", alpha); check_positive_finite(function, "Second shape parameter", beta); check_not_nan(function, "Random variable", y); check_nonnegative(function, "Random variable", y); check_less_or_equal(function, "Random variable", y, 1); check_consistent_sizes(function, "Random variable", y, "First shape parameter", alpha, "Second shape parameter", beta); // Wrap arguments in vectors VectorView<const T_y> y_vec(y); VectorView<const T_scale_succ> alpha_vec(alpha); VectorView<const T_scale_fail> beta_vec(beta); size_t N = max_size(y, alpha, beta); OperandsAndPartials<T_y, T_scale_succ, T_scale_fail> operands_and_partials(y, alpha, beta); // Compute CDF and its gradients using stan::math::inc_beta; using stan::math::digamma; using stan::math::lbeta; using std::pow; using std::exp; using std::log; using std::exp; // Cache a few expensive function calls if alpha or beta is a parameter VectorBuilder<contains_nonconstant_struct<T_scale_succ, T_scale_fail>::value, T_partials_return, T_scale_succ, T_scale_fail> digamma_alpha_vec(max_size(alpha, beta)); VectorBuilder<contains_nonconstant_struct<T_scale_succ, T_scale_fail>::value, T_partials_return, T_scale_succ, T_scale_fail> digamma_beta_vec(max_size(alpha, beta)); VectorBuilder<contains_nonconstant_struct<T_scale_succ, T_scale_fail>::value, T_partials_return, T_scale_succ, T_scale_fail> digamma_sum_vec(max_size(alpha, beta)); if (contains_nonconstant_struct<T_scale_succ, T_scale_fail>::value) { for (size_t i = 0; i < N; i++) { const T_partials_return alpha_dbl = value_of(alpha_vec[i]); const T_partials_return beta_dbl = value_of(beta_vec[i]); digamma_alpha_vec[i] = digamma(alpha_dbl); digamma_beta_vec[i] = digamma(beta_dbl); digamma_sum_vec[i] = digamma(alpha_dbl + beta_dbl); } } // Compute vectorized CDFLog and gradient for (size_t n = 0; n < N; n++) { // Pull out values const T_partials_return y_dbl = value_of(y_vec[n]); const T_partials_return alpha_dbl = value_of(alpha_vec[n]); const T_partials_return beta_dbl = value_of(beta_vec[n]); const T_partials_return betafunc_dbl = exp(lbeta(alpha_dbl, beta_dbl)); // Compute const T_partials_return Pn = inc_beta(alpha_dbl, beta_dbl, y_dbl); cdf_log += log(Pn); if (!is_constant_struct<T_y>::value) operands_and_partials.d_x1[n] += pow(1-y_dbl, beta_dbl-1) * pow(y_dbl, alpha_dbl-1) / betafunc_dbl / Pn; T_partials_return g1 = 0; T_partials_return g2 = 0; if (contains_nonconstant_struct<T_scale_succ, T_scale_fail>::value) { stan::math::grad_reg_inc_beta(g1, g2, alpha_dbl, beta_dbl, y_dbl, digamma_alpha_vec[n], digamma_beta_vec[n], digamma_sum_vec[n], betafunc_dbl); } if (!is_constant_struct<T_scale_succ>::value) operands_and_partials.d_x2[n] += g1 / Pn; if (!is_constant_struct<T_scale_fail>::value) operands_and_partials.d_x3[n] += g2 / Pn; } return operands_and_partials.to_var(cdf_log, y, alpha, beta); }
DualNumber<T> exp(DualNumber<T> x) { using std::exp; return DualNumber<T>(exp(x.first), x.second * exp(x.first)); }
TEST(AgradFwdLogDiffExp,FvarVar_FvarVar_2ndDeriv) { using stan::agrad::fvar; using stan::agrad::var; using stan::math::log_diff_exp; using std::exp; fvar<var> x(9.0,1.3); fvar<var> z(6.0,1.0); fvar<var> a = log_diff_exp(x,z); AVEC y = createAVEC(x.val_,z.val_); VEC g; a.d_.grad(y,g); EXPECT_FLOAT_EQ((1.3 * exp(9.0) * (exp(9.0) - exp(6.0)) - exp(9.0) * (1.3 * exp(9.0) - exp(6.0))) / (exp(9.0) - exp(6.0)) / (exp(9.0) - exp(6.0)) ,g[0]); EXPECT_FLOAT_EQ((-exp(6.0) * (exp(9.0) - exp(6.0)) + exp(6.0) * (1.3 * exp(9.0) - exp(6.0))) / (exp(9.0) - exp(6.0)) / (exp(9.0) - exp(6.0)) ,g[1]); }
typename return_type<T_prob>::type binomial_cdf(const T_n& n, const T_N& N, const T_prob& theta) { static const char* function("stan::prob::binomial_cdf"); typedef typename stan::partials_return_type<T_n,T_N,T_prob>::type T_partials_return; using stan::math::check_finite; using stan::math::check_bounded; using stan::math::check_nonnegative; using stan::math::value_of; using stan::math::check_consistent_sizes; using stan::prob::include_summand; // Ensure non-zero arguments lenghts if (!(stan::length(n) && stan::length(N) && stan::length(theta))) return 1.0; T_partials_return P(1.0); // Validate arguments check_nonnegative(function, "Population size parameter", N); check_finite(function, "Probability parameter", theta); check_bounded(function, "Probability parameter", theta, 0.0, 1.0); check_consistent_sizes(function, "Successes variable", n, "Population size parameter", N, "Probability parameter", theta); // Wrap arguments in vector views VectorView<const T_n> n_vec(n); VectorView<const T_N> N_vec(N); VectorView<const T_prob> theta_vec(theta); size_t size = max_size(n, N, theta); // Compute vectorized CDF and gradient using stan::math::value_of; using stan::math::inc_beta; using stan::math::lbeta; using std::exp; using std::pow; agrad::OperandsAndPartials<T_prob> operands_and_partials(theta); // Explicit return for extreme values // The gradients are technically ill-defined, but treated as zero for (size_t i = 0; i < stan::length(n); i++) { if (value_of(n_vec[i]) < 0) return operands_and_partials.to_var(0.0,theta); } for (size_t i = 0; i < size; i++) { // Explicit results for extreme values // The gradients are technically ill-defined, but treated as zero if (value_of(n_vec[i]) >= value_of(N_vec[i])) { continue; } const T_partials_return n_dbl = value_of(n_vec[i]); const T_partials_return N_dbl = value_of(N_vec[i]); const T_partials_return theta_dbl = value_of(theta_vec[i]); const T_partials_return betafunc = exp(lbeta(N_dbl-n_dbl,n_dbl+1)); const T_partials_return Pi = inc_beta(N_dbl - n_dbl, n_dbl + 1, 1 - theta_dbl); P *= Pi; if (!is_constant_struct<T_prob>::value) operands_and_partials.d_x1[i] -= pow(theta_dbl,n_dbl) * pow(1-theta_dbl,N_dbl-n_dbl-1) / betafunc / Pi; } if (!is_constant_struct<T_prob>::value) { for(size_t i = 0; i < stan::length(theta); ++i) operands_and_partials.d_x1[i] *= P; } return operands_and_partials.to_var(P,theta); }
typename return_type<T_y, T_dof>::type inv_chi_square_cdf_log(const T_y& y, const T_dof& nu) { typedef typename stan::partials_return_type<T_y, T_dof>::type T_partials_return; // Size checks if ( !( stan::length(y) && stan::length(nu) ) ) return 0.0; // Error checks static const char* function("stan::math::inv_chi_square_cdf_log"); using stan::math::check_positive_finite; using stan::math::check_not_nan; using stan::math::check_consistent_sizes; using stan::math::check_nonnegative; using boost::math::tools::promote_args; using stan::math::value_of; using std::exp; T_partials_return P(0.0); check_positive_finite(function, "Degrees of freedom parameter", nu); check_not_nan(function, "Random variable", y); check_nonnegative(function, "Random variable", y); check_consistent_sizes(function, "Random variable", y, "Degrees of freedom parameter", nu); // Wrap arguments in vectors VectorView<const T_y> y_vec(y); VectorView<const T_dof> nu_vec(nu); size_t N = max_size(y, nu); OperandsAndPartials<T_y, T_dof> operands_and_partials(y, nu); // Explicit return for extreme values // The gradients are technically ill-defined, but treated as zero for (size_t i = 0; i < stan::length(y); i++) if (value_of(y_vec[i]) == 0) return operands_and_partials.to_var(stan::math::negative_infinity(), y, nu); // Compute cdf_log and its gradients using stan::math::gamma_q; using stan::math::digamma; using boost::math::tgamma; using std::exp; using std::pow; using std::log; // Cache a few expensive function calls if nu is a parameter VectorBuilder<!is_constant_struct<T_dof>::value, T_partials_return, T_dof> gamma_vec(stan::length(nu)); VectorBuilder<!is_constant_struct<T_dof>::value, T_partials_return, T_dof> digamma_vec(stan::length(nu)); if (!is_constant_struct<T_dof>::value) { for (size_t i = 0; i < stan::length(nu); i++) { const T_partials_return nu_dbl = value_of(nu_vec[i]); gamma_vec[i] = tgamma(0.5 * nu_dbl); digamma_vec[i] = digamma(0.5 * nu_dbl); } } // Compute vectorized cdf_log and gradient for (size_t n = 0; n < N; n++) { // Explicit results for extreme values // The gradients are technically ill-defined, but treated as zero if (value_of(y_vec[n]) == std::numeric_limits<double>::infinity()) { continue; } // Pull out values const T_partials_return y_dbl = value_of(y_vec[n]); const T_partials_return y_inv_dbl = 1.0 / y_dbl; const T_partials_return nu_dbl = value_of(nu_vec[n]); // Compute const T_partials_return Pn = gamma_q(0.5 * nu_dbl, 0.5 * y_inv_dbl); P += log(Pn); if (!is_constant_struct<T_y>::value) operands_and_partials.d_x1[n] += 0.5 * y_inv_dbl * y_inv_dbl * exp(-0.5*y_inv_dbl) * pow(0.5*y_inv_dbl, 0.5*nu_dbl-1) / tgamma(0.5*nu_dbl) / Pn; if (!is_constant_struct<T_dof>::value) operands_and_partials.d_x2[n] += 0.5 * stan::math::grad_reg_inc_gamma(0.5 * nu_dbl, 0.5 * y_inv_dbl, gamma_vec[n], digamma_vec[n]) / Pn; } return operands_and_partials.to_var(P, y, nu); }
typename return_type<T_y, T_dof, T_scale>::type scaled_inv_chi_square_ccdf_log(const T_y& y, const T_dof& nu, const T_scale& s) { typedef typename stan::partials_return_type<T_y, T_dof, T_scale>::type T_partials_return; if (!(stan::length(y) && stan::length(nu) && stan::length(s))) return 0.0; static const char* function("scaled_inv_chi_square_ccdf_log"); using std::exp; T_partials_return P(0.0); check_not_nan(function, "Random variable", y); check_nonnegative(function, "Random variable", y); check_positive_finite(function, "Degrees of freedom parameter", nu); check_positive_finite(function, "Scale parameter", s); check_consistent_sizes(function, "Random variable", y, "Degrees of freedom parameter", nu, "Scale parameter", s); VectorView<const T_y> y_vec(y); VectorView<const T_dof> nu_vec(nu); VectorView<const T_scale> s_vec(s); size_t N = max_size(y, nu, s); OperandsAndPartials<T_y, T_dof, T_scale> operands_and_partials(y, nu, s); // Explicit return for extreme values // The gradients are technically ill-defined, but treated as zero for (size_t i = 0; i < stan::length(y); i++) { if (value_of(y_vec[i]) == 0) return operands_and_partials.value(0.0); } using std::exp; using std::pow; using std::log; VectorBuilder<!is_constant_struct<T_dof>::value, T_partials_return, T_dof> gamma_vec(stan::length(nu)); VectorBuilder<!is_constant_struct<T_dof>::value, T_partials_return, T_dof> digamma_vec(stan::length(nu)); if (!is_constant_struct<T_dof>::value) { for (size_t i = 0; i < stan::length(nu); i++) { const T_partials_return half_nu_dbl = 0.5 * value_of(nu_vec[i]); gamma_vec[i] = tgamma(half_nu_dbl); digamma_vec[i] = digamma(half_nu_dbl); } } for (size_t n = 0; n < N; n++) { // Explicit results for extreme values // The gradients are technically ill-defined, but treated as zero if (value_of(y_vec[n]) == std::numeric_limits<double>::infinity()) { return operands_and_partials.value(negative_infinity()); } const T_partials_return y_dbl = value_of(y_vec[n]); const T_partials_return y_inv_dbl = 1.0 / y_dbl; const T_partials_return half_nu_dbl = 0.5 * value_of(nu_vec[n]); const T_partials_return s_dbl = value_of(s_vec[n]); const T_partials_return half_s2_overx_dbl = 0.5 * s_dbl * s_dbl * y_inv_dbl; const T_partials_return half_nu_s2_overx_dbl = 2.0 * half_nu_dbl * half_s2_overx_dbl; const T_partials_return Pn = gamma_p(half_nu_dbl, half_nu_s2_overx_dbl); const T_partials_return gamma_p_deriv = exp(-half_nu_s2_overx_dbl) * pow(half_nu_s2_overx_dbl, half_nu_dbl-1) / tgamma(half_nu_dbl); P += log(Pn); if (!is_constant_struct<T_y>::value) operands_and_partials.d_x1[n] -= half_nu_s2_overx_dbl * y_inv_dbl * gamma_p_deriv / Pn; if (!is_constant_struct<T_dof>::value) operands_and_partials.d_x2[n] -= (0.5 * grad_reg_inc_gamma(half_nu_dbl, half_nu_s2_overx_dbl, gamma_vec[n], digamma_vec[n]) - half_s2_overx_dbl * gamma_p_deriv) / Pn; if (!is_constant_struct<T_scale>::value) operands_and_partials.d_x3[n] += 2.0 * half_nu_dbl * s_dbl * y_inv_dbl * gamma_p_deriv / Pn; } return operands_and_partials.value(P); }
inline T0 operator()(const T0& arg1) const { return exp(arg1); }
TEST(AgradFwdExp,Fvar) { using stan::math::fvar; using std::exp; fvar<double> x(0.5,1.0); fvar<double> a = exp(x); EXPECT_FLOAT_EQ(exp(0.5), a.val_); EXPECT_FLOAT_EQ(exp(0.5), a.d_); fvar<double> b = 2 * exp(x) + 4; EXPECT_FLOAT_EQ(2 * exp(0.5) + 4, b.val_); EXPECT_FLOAT_EQ(2 * exp(0.5), b.d_); fvar<double> c = -exp(x) + 5; EXPECT_FLOAT_EQ(-exp(0.5) + 5, c.val_); EXPECT_FLOAT_EQ(-exp(0.5), c.d_); fvar<double> d = -3 * exp(-x) + 5 * x; EXPECT_FLOAT_EQ(-3 * exp(-0.5) + 5 * 0.5, d.val_); EXPECT_FLOAT_EQ(3 * exp(-0.5) + 5, d.d_); fvar<double> y(-0.5,1.0); fvar<double> e = exp(y); EXPECT_FLOAT_EQ(exp(-0.5), e.val_); EXPECT_FLOAT_EQ(exp(-0.5), e.d_); fvar<double> z(0.0,1.0); fvar<double> f = exp(z); EXPECT_FLOAT_EQ(exp(0.0), f.val_); EXPECT_FLOAT_EQ(exp(0.0), f.d_); }
double exact_soln(double x){ return 1.0 - (1.0-exp(-10.0))*x - exp(-10.0*x); }
double f(double x){ // Source term or Inhomogeneous term return 100.0 * exp(-10.0 * x); }
const float phi1 = degreeToRadian(44.f); // 1st automecoic parallel const float phi2 = degreeToRadian(49.f); // 2nd automecoic parallel const float phi0 = degreeToRadian(46.5f);// latitude of origin const float X0 = 700000; // x coordinate at origin const float Y0 = 6600000; // y coordinate at origin // Normals const float gN1 = a/sqrt(1-e*e*sin(phi1)*sin(phi1)); const float gN2 = a/sqrt(1-e*e*sin(phi2)*sin(phi2)); // Isometric latitudes const float gl1=log(tan(M_PI/4+phi1/2)*pow((1-e*sin(phi1))/(1+e*sin(phi1)),e/2)); const float gl2=log(tan(M_PI/4+phi2/2)*pow((1-e*sin(phi2))/(1+e*sin(phi2)),e/2)); const float gl0=log(tan(M_PI/4+phi0/2)*pow((1-e*sin(phi0))/(1+e*sin(phi0)),e/2)); // Projection exponent const float n = (log((gN2*cos(phi2))/(gN1*cos(phi1))))/(gl1-gl2); // Projection constant const float c = ((gN1*cos(phi1))/n)*exp(n*gl1); // Coordinate const float ys = Y0 + c*exp(-n*gl0); // Convert geographic coordinates (latitude, longitude in degrees) into // cartesian coordinates (in kilometers) using the Lambert 93 projection. pair<float,float> geoToLambert93(float latitude,float longitude) { float phi = degreeToRadian(latitude); float l = degreeToRadian(longitude); float gl = log(tan(M_PI/4+phi/2)*pow((1-e*sin(phi))/(1+e*sin(phi)),e/2)); float x93 = X0 + c*exp(-n*gl)*sin(n*(l-lc)); float y93 = ys - c*exp(-n*gl)*cos(n*(l-lc)); return make_pair(x93/1000,y93/1000); }
void FunctionsTest::testWeightedModifiedBesselFunctions() { BOOST_TEST_MESSAGE("Testing weighted modified Bessel functions..."); Real nu = -5.0; while (nu <= 5.0) { Real x = 0.1; while (x <= 15.0) { const Real calculated_i = modifiedBesselFunction_i_exponentiallyWeighted(nu, x); const Real expected_i = modifiedBesselFunction_i(nu, x) * exp(-x); const Real calculated_k = modifiedBesselFunction_k_exponentiallyWeighted(nu, x); const Real expected_k = M_PI_2 * (modifiedBesselFunction_i(-nu,x) - modifiedBesselFunction_i(nu,x)) * exp(-x) / std::sin(M_PI*nu); const Real tol_i = 1e3 * QL_EPSILON * std::fabs(expected_i) * std::max(exp(x), 1.0); const Real tol_k = std::max(QL_EPSILON, 1e3 * QL_EPSILON * std::fabs(expected_k) * std::max(exp(x), 1.0)); if (std::abs(expected_i - calculated_i) > tol_i) { BOOST_ERROR("failed to verify exponentially weighted" << "modified Bessel function of first kind" << "\n order : " << nu << "\n argument : " << x << "\n calculated : " << calculated_i << "\n expected : " << expected_i); } if (std::abs(expected_k - calculated_k) > tol_k) { BOOST_ERROR("failed to verify exponentially weighted" << "modified Bessel function of second kind" << "\n order : " << nu << "\n argument : " << x << "\n calculated : " << calculated_k << "\n expected : " << expected_k); } x += 0.5; } nu += 0.5; } nu = -5.0; while (nu <= 5.0) { Real x = -5.0; while (x <= 5.0) { Real y = -5.0; while (y <= 5.0) { const std::complex<Real> z(x, y); const std::complex<Real> calculated_i = modifiedBesselFunction_i_exponentiallyWeighted(nu, z); const std::complex<Real> expected_i = modifiedBesselFunction_i(nu, z) * exp(-z); const std::complex<Real> calculated_k = modifiedBesselFunction_k_exponentiallyWeighted(nu, z); const std::complex<Real> expected_k = M_PI_2 * (modifiedBesselFunction_i(-nu, z) * exp(-z) - modifiedBesselFunction_i(nu, z) * exp(-z)) / std::sin(M_PI * nu); const Real tol_i = 1e3 * QL_EPSILON*std::abs(calculated_i); const Real tol_k = 1e3 * QL_EPSILON*std::abs(calculated_k); if (std::abs(calculated_i - expected_i) > tol_i) { BOOST_ERROR("failed to verify exponentially weighted" << "modified Bessel function of first kind" << "\n order : " << nu << "\n argument : " << z << "\n calculated: " << calculated_i << "\n expected : " << expected_i); } if (std::abs(calculated_k - expected_k) > tol_k) { BOOST_ERROR("failed to verify exponentially weighted" << "modified Bessel function of second kind" << "\n order : " << nu << "\n argument : " << z << "\n calculated: " << calculated_k << "\n expected : " << expected_k); } y += 0.5; } x += 0.5; } nu += 0.5; } }
int test_values(const Scalar & Cf, const Scalar & eta, const Scalar & Ea, const Scalar & D, const Scalar & Tref, const Scalar & R, const Antioch::KineticsType<Scalar> & rate_base) { using std::abs; using std::exp; using std::pow; int return_flag = 0; const Scalar tol = std::numeric_limits<Scalar>::epsilon() * 100; for(Scalar T = 300.1L; T <= 2500.1L; T += 10.L) { const Scalar rate_exact = Cf*pow(T/Tref,eta)*exp(-Ea/(R*T) + D * T); const Scalar derive_exact = exp(-Ea/(R*T) + D * T) * pow(T/Tref,eta) * Cf * (Ea/(R*T*T) + eta/T + D ); Antioch::KineticsConditions<Scalar> cond(T); Scalar rate1 = rate_base(cond); Scalar deriveRate1 = rate_base.derivative(cond); Scalar rate; Scalar deriveRate; rate_base.compute_rate_and_derivative(cond,rate,deriveRate); if( abs( (rate1 - rate_exact)/rate_exact ) > tol ) { std::cerr << std::scientific << std::setprecision(16) << "Error: Mismatch in rate values." << std::endl << "T = " << T << " K" << std::endl << "rate(T) = " << rate1 << std::endl << "rate_exact = " << rate_exact << std::endl << "relative difference = " << abs( (rate1 - rate_exact)/rate_exact ) << std::endl << "tolerance = " << tol << std::endl << "on rate " << rate_base << std::endl << std::endl; return_flag = 1; } if( abs( (rate - rate_exact)/rate_exact ) > tol ) { std::cerr << std::scientific << std::setprecision(16) << "Error: Mismatch in rate values." << std::endl << "T = " << T << " K" << std::endl << "rate(T) = " << rate << std::endl << "rate_exact = " << rate_exact << std::endl << "relative difference = " << abs( (rate - rate_exact)/rate_exact ) << std::endl << "tolerance = " << tol << std::endl << "on rate " << rate_base << std::endl << std::endl; return_flag = 1; } if( abs( (deriveRate1 - derive_exact)/derive_exact ) > tol ) { std::cerr << std::scientific << std::setprecision(16) << "Error: Mismatch in rate derivative values." << std::endl << "T = " << T << " K" << std::endl << "drate_dT(T) = " << deriveRate1 << std::endl << "derive_exact = " << derive_exact << std::endl << "relative difference = " << abs( (deriveRate1 - derive_exact)/derive_exact ) << std::endl << "tolerance = " << tol << std::endl << "on rate " << rate_base << std::endl << std::endl; return_flag = 1; } if( abs( (deriveRate - derive_exact)/derive_exact ) > tol ) { std::cerr << std::scientific << std::setprecision(16) << "Error: Mismatch in rate derivative values." << std::endl << "T = " << T << " K" << std::endl << "drate_dT(T) = " << deriveRate << std::endl << "derive_exact = " << derive_exact << std::endl << "relative difference = " << abs( (deriveRate - derive_exact)/derive_exact ) << std::endl << "tolerance = " << tol << std::endl << "on rate " << rate_base << std::endl << std::endl; return_flag = 1; } if(return_flag)break; } return return_flag; }
typename return_type<T_y,T_dof>::type chi_square_cdf(const T_y& y, const T_dof& nu) { static const char* function("stan::prob::chi_square_cdf"); typedef typename stan::partials_return_type<T_y,T_dof>::type T_partials_return; using stan::math::check_positive_finite; using stan::math::check_nonnegative; using stan::math::check_not_nan; using stan::math::check_consistent_sizes; using stan::math::value_of; T_partials_return cdf(1.0); // Size checks if (!(stan::length(y) && stan::length(nu))) return cdf; check_not_nan(function, "Random variable", y); check_nonnegative(function, "Random variable", y); check_positive_finite(function, "Degrees of freedom parameter", nu); check_consistent_sizes(function, "Random variable", y, "Degrees of freedom parameter", nu); // Wrap arguments in vectors VectorView<const T_y> y_vec(y); VectorView<const T_dof> nu_vec(nu); size_t N = max_size(y, nu); agrad::OperandsAndPartials<T_y, T_dof> operands_and_partials(y, nu); // Explicit return for extreme values // The gradients are technically ill-defined, but treated as zero for (size_t i = 0; i < stan::length(y); i++) { if (value_of(y_vec[i]) == 0) return operands_and_partials.to_var(0.0,y,nu); } // Compute CDF and its gradients using stan::math::gamma_p; using stan::math::digamma; using boost::math::tgamma; using std::exp; using std::pow; // Cache a few expensive function calls if nu is a parameter VectorBuilder<!is_constant_struct<T_dof>::value, T_partials_return, T_dof> gamma_vec(stan::length(nu)); VectorBuilder<!is_constant_struct<T_dof>::value, T_partials_return,T_dof> digamma_vec(stan::length(nu)); if (!is_constant_struct<T_dof>::value) { for (size_t i = 0; i < stan::length(nu); i++) { const T_partials_return alpha_dbl = value_of(nu_vec[i]) * 0.5; gamma_vec[i] = tgamma(alpha_dbl); digamma_vec[i] = digamma(alpha_dbl); } } // Compute vectorized CDF and gradient for (size_t n = 0; n < N; n++) { // Explicit results for extreme values // The gradients are technically ill-defined, but treated as zero if (value_of(y_vec[n]) == std::numeric_limits<double>::infinity()) continue; // Pull out values const T_partials_return y_dbl = value_of(y_vec[n]); const T_partials_return alpha_dbl = value_of(nu_vec[n]) * 0.5; const T_partials_return beta_dbl = 0.5; // Compute const T_partials_return Pn = gamma_p(alpha_dbl, beta_dbl * y_dbl); cdf *= Pn; if (!is_constant_struct<T_y>::value) operands_and_partials.d_x1[n] += beta_dbl * exp(-beta_dbl * y_dbl) * pow(beta_dbl * y_dbl,alpha_dbl-1) / tgamma(alpha_dbl) / Pn; if (!is_constant_struct<T_dof>::value) operands_and_partials.d_x2[n] -= 0.5 * stan::math::grad_reg_inc_gamma(alpha_dbl, beta_dbl * y_dbl, gamma_vec[n], digamma_vec[n]) / Pn; } if (!is_constant_struct<T_y>::value) for (size_t n = 0; n < stan::length(y); ++n) operands_and_partials.d_x1[n] *= cdf; if (!is_constant_struct<T_dof>::value) for (size_t n = 0; n < stan::length(nu); ++n) operands_and_partials.d_x2[n] *= cdf; return operands_and_partials.to_var(cdf,y,nu); }
typename return_type<T_size1,T_size2>::type beta_binomial_ccdf_log(const T_n& n, const T_N& N, const T_size1& alpha, const T_size2& beta) { static const char* function("stan::prob::beta_binomial_ccdf_log"); typedef typename stan::partials_return_type<T_n,T_N,T_size1, T_size2>::type T_partials_return; using stan::math::check_positive_finite; using stan::math::check_nonnegative; using stan::math::value_of; using stan::math::check_consistent_sizes; using stan::prob::include_summand; // Ensure non-zero argument lengths if (!(stan::length(n) && stan::length(N) && stan::length(alpha) && stan::length(beta))) return 0.0; T_partials_return P(0.0); // Validate arguments check_nonnegative(function, "Population size parameter", N); check_positive_finite(function, "First prior sample size parameter", alpha); check_positive_finite(function, "Second prior sample size parameter", beta); check_consistent_sizes(function, "Successes variable", n, "Population size parameter", N, "First prior sample size parameter", alpha, "Second prior sample size parameter", beta); // Wrap arguments in vector views VectorView<const T_n> n_vec(n); VectorView<const T_N> N_vec(N); VectorView<const T_size1> alpha_vec(alpha); VectorView<const T_size2> beta_vec(beta); size_t size = max_size(n, N, alpha, beta); // Compute vectorized cdf_log and gradient using stan::math::lgamma; using stan::math::lbeta; using stan::math::digamma; using std::exp; agrad::OperandsAndPartials<T_size1, T_size2> operands_and_partials(alpha, beta); // Explicit return for extreme values // The gradients are technically ill-defined, but treated as neg infinity for (size_t i = 0; i < stan::length(n); i++) { if (value_of(n_vec[i]) <= 0) return operands_and_partials.to_var(0.0,alpha,beta); } for (size_t i = 0; i < size; i++) { // Explicit results for extreme values // The gradients are technically ill-defined, but treated as zero if (value_of(n_vec[i]) >= value_of(N_vec[i])) { return operands_and_partials.to_var(stan::math::negative_infinity(), alpha,beta); } const T_partials_return n_dbl = value_of(n_vec[i]); const T_partials_return N_dbl = value_of(N_vec[i]); const T_partials_return alpha_dbl = value_of(alpha_vec[i]); const T_partials_return beta_dbl = value_of(beta_vec[i]); const T_partials_return mu = alpha_dbl + n_dbl + 1; const T_partials_return nu = beta_dbl + N_dbl - n_dbl - 1; const T_partials_return F = stan::math::F32((T_partials_return)1, mu, -N_dbl + n_dbl + 1, n_dbl + 2, 1 - nu, (T_partials_return)1); T_partials_return C = lgamma(nu) - lgamma(N_dbl - n_dbl); C += lgamma(mu) - lgamma(n_dbl + 2); C += lgamma(N_dbl + 2) - lgamma(N_dbl + alpha_dbl + beta_dbl); C = exp(C); C *= F / exp(lbeta(alpha_dbl, beta_dbl)); C /= N_dbl + 1; const T_partials_return Pi = C; P += log(Pi); T_partials_return dF[6]; T_partials_return digammaOne = 0; T_partials_return digammaTwo = 0; if (contains_nonconstant_struct<T_size1,T_size2>::value) { digammaOne = digamma(mu + nu); digammaTwo = digamma(alpha_dbl + beta_dbl); stan::math::grad_F32(dF, (T_partials_return)1, mu, -N_dbl + n_dbl + 1, n_dbl + 2, 1 - nu, (T_partials_return)1); } if (!is_constant_struct<T_size1>::value) { const T_partials_return g = - C * (digamma(mu) - digammaOne + dF[1] / F - digamma(alpha_dbl) + digammaTwo); operands_and_partials.d_x1[i] -= g / Pi; } if (!is_constant_struct<T_size2>::value) { const T_partials_return g = - C * (digamma(nu) - digammaOne - dF[4] / F - digamma(beta_dbl) + digammaTwo); operands_and_partials.d_x2[i] -= g / Pi; } } return operands_and_partials.to_var(P,alpha,beta); }
int vectester(const PairScalars& example) { using std::abs; using std::exp; typedef typename Antioch::value_type<PairScalars>::type Scalar; const Scalar Cf = 1.4; const Scalar D = -2.5; Antioch::BerthelotRate<Scalar> berthelot_rate(Cf,D); // Construct from example to avoid resizing issues PairScalars T = example; T[0] = 1500.1; T[1] = 1600.1; const Scalar rate_exact0 = Cf*exp(D*1500.1); const Scalar rate_exact1 = Cf*exp(D*1600.1); const Scalar derive_exact0 = D * Cf * exp(D*Scalar(1500.1)); const Scalar derive_exact1 = D * Cf * exp(D*Scalar(1600.1)); int return_flag = 0; const PairScalars rate = berthelot_rate(T); const PairScalars deriveRate = berthelot_rate.derivative(T); const Scalar tol = std::numeric_limits<Scalar>::epsilon()*10; if( abs( (rate[0] - rate_exact0)/rate_exact0 ) > tol ) { std::cout << "Error: Mismatch in rate values." << std::endl << "rate(T0) = " << rate[0] << std::endl << "rate_exact = " << rate_exact0 << std::endl << "difference = " << rate[0] - rate_exact0 << std::endl; return_flag = 1; } if( abs( (rate[1] - rate_exact1)/rate_exact1 ) > tol ) { std::cout << "Error: Mismatch in rate values." << std::endl << "rate(T1) = " << rate[1] << std::endl << "rate_exact = " << rate_exact1 << std::endl << "difference = " << rate[1] - rate_exact1 << std::endl; return_flag = 1; } if( abs( (deriveRate[0] - derive_exact0)/derive_exact0 ) > tol ) { std::cout << std::scientific << std::setprecision(16) << "Error: Mismatch in rate derivative values." << std::endl << "drate_dT(T0) = " << deriveRate[0] << std::endl << "derive_exact = " << derive_exact0 << std::endl; return_flag = 1; } if( abs( (deriveRate[1] - derive_exact1)/derive_exact1 ) > tol ) { std::cout << std::scientific << std::setprecision(16) << "Error: Mismatch in rate derivative values." << std::endl << "drate_dT(T1) = " << deriveRate[1] << std::endl << "derive_exact = " << derive_exact1 << std::endl; return_flag = 1; } std::cout << "Berthelot rate: " << berthelot_rate << std::endl; return return_flag; }
typename return_type<T_y, T_loc, T_scale>::type normal_ccdf_log(const T_y& y, const T_loc& mu, const T_scale& sigma) { static const char* function("stan::math::normal_ccdf_log"); typedef typename stan::partials_return_type<T_y, T_loc, T_scale>::type T_partials_return; using stan::math::check_positive; using stan::math::check_finite; using stan::math::check_not_nan; using stan::math::check_consistent_sizes; using stan::math::value_of; using stan::math::INV_SQRT_2; using std::log; using std::exp; T_partials_return ccdf_log(0.0); // check if any vectors are zero length if (!(stan::length(y) && stan::length(mu) && stan::length(sigma))) return ccdf_log; check_not_nan(function, "Random variable", y); check_finite(function, "Location parameter", mu); check_not_nan(function, "Scale parameter", sigma); check_positive(function, "Scale parameter", sigma); check_consistent_sizes(function, "Random variable", y, "Location parameter", mu, "Scale parameter", sigma); OperandsAndPartials<T_y, T_loc, T_scale> operands_and_partials(y, mu, sigma); VectorView<const T_y> y_vec(y); VectorView<const T_loc> mu_vec(mu); VectorView<const T_scale> sigma_vec(sigma); size_t N = max_size(y, mu, sigma); double log_half = std::log(0.5); const double SQRT_TWO_OVER_PI = std::sqrt(2.0 / stan::math::pi()); for (size_t n = 0; n < N; n++) { const T_partials_return y_dbl = value_of(y_vec[n]); const T_partials_return mu_dbl = value_of(mu_vec[n]); const T_partials_return sigma_dbl = value_of(sigma_vec[n]); const T_partials_return scaled_diff = (y_dbl - mu_dbl) / (sigma_dbl * SQRT_2); T_partials_return one_m_erf; if (scaled_diff < -37.5 * INV_SQRT_2) one_m_erf = 2.0; else if (scaled_diff < -5.0 * INV_SQRT_2) one_m_erf = 2.0 - erfc(-scaled_diff); else if (scaled_diff > 8.25 * INV_SQRT_2) one_m_erf = 0.0; else one_m_erf = 1.0 - erf(scaled_diff); // log ccdf ccdf_log += log_half + log(one_m_erf); // gradients if (contains_nonconstant_struct<T_y, T_loc, T_scale>::value) { const T_partials_return rep_deriv_div_sigma = scaled_diff > 8.25 * INV_SQRT_2 ? std::numeric_limits<double>::infinity() : SQRT_TWO_OVER_PI * exp(-scaled_diff * scaled_diff) / one_m_erf / sigma_dbl; if (!is_constant_struct<T_y>::value) operands_and_partials.d_x1[n] -= rep_deriv_div_sigma; if (!is_constant_struct<T_loc>::value) operands_and_partials.d_x2[n] += rep_deriv_div_sigma; if (!is_constant_struct<T_scale>::value) operands_and_partials.d_x3[n] += rep_deriv_div_sigma * scaled_diff * stan::math::SQRT_2; } } return operands_and_partials.value(ccdf_log); }
typename return_type<T_y, T_scale, T_shape>::type pareto_ccdf_log(const T_y& y, const T_scale& y_min, const T_shape& alpha) { typedef typename stan::partials_return_type<T_y, T_scale, T_shape>::type T_partials_return; // Size checks if ( !( stan::length(y) && stan::length(y_min) && stan::length(alpha) ) ) return 0.0; // Check errors static const char* function("stan::math::pareto_ccdf_log"); using stan::math::check_positive_finite; using stan::math::check_not_nan; using stan::math::check_greater_or_equal; using stan::math::check_consistent_sizes; using stan::math::check_nonnegative; using stan::math::value_of; using std::log; using std::exp; T_partials_return P(0.0); check_not_nan(function, "Random variable", y); check_nonnegative(function, "Random variable", y); check_positive_finite(function, "Scale parameter", y_min); check_positive_finite(function, "Shape parameter", alpha); check_consistent_sizes(function, "Random variable", y, "Scale parameter", y_min, "Shape parameter", alpha); // Wrap arguments in vectors VectorView<const T_y> y_vec(y); VectorView<const T_scale> y_min_vec(y_min); VectorView<const T_shape> alpha_vec(alpha); size_t N = max_size(y, y_min, alpha); OperandsAndPartials<T_y, T_scale, T_shape> operands_and_partials(y, y_min, alpha); // Explicit return for extreme values // The gradients are technically ill-defined, but treated as zero for (size_t i = 0; i < stan::length(y); i++) { if (value_of(y_vec[i]) < value_of(y_min_vec[i])) return operands_and_partials.to_var(0.0, y, y_min, alpha); } // Compute vectorized cdf_log and its gradients for (size_t n = 0; n < N; n++) { // Explicit results for extreme values // The gradients are technically ill-defined, but treated as zero if (value_of(y_vec[n]) == std::numeric_limits<double>::infinity()) { return operands_and_partials.to_var(stan::math::negative_infinity(), y, y_min, alpha); } // Pull out values const T_partials_return log_dbl = log(value_of(y_min_vec[n]) / value_of(y_vec[n])); const T_partials_return y_min_inv_dbl = 1.0 / value_of(y_min_vec[n]); const T_partials_return alpha_dbl = value_of(alpha_vec[n]); P += alpha_dbl * log_dbl; if (!is_constant_struct<T_y>::value) operands_and_partials.d_x1[n] -= alpha_dbl * y_min_inv_dbl * exp(log_dbl); if (!is_constant_struct<T_scale>::value) operands_and_partials.d_x2[n] += alpha_dbl * y_min_inv_dbl; if (!is_constant_struct<T_shape>::value) operands_and_partials.d_x3[n] += log_dbl; } return operands_and_partials.to_var(P, y, y_min, alpha); }
typename return_type<T_y, T_loc, T_scale>::type double_exponential_cdf(const T_y& y, const T_loc& mu, const T_scale& sigma) { static const char* function("stan::math::double_exponential_cdf"); typedef typename stan::partials_return_type<T_y, T_loc, T_scale>::type T_partials_return; // Size checks if ( !( stan::length(y) && stan::length(mu) && stan::length(sigma) ) ) return 1.0; using stan::math::value_of; using stan::math::check_finite; using stan::math::check_positive_finite; using stan::math::check_not_nan; using boost::math::tools::promote_args; using std::exp; T_partials_return cdf(1.0); check_not_nan(function, "Random variable", y); check_finite(function, "Location parameter", mu); check_positive_finite(function, "Scale parameter", sigma); OperandsAndPartials<T_y, T_loc, T_scale> operands_and_partials(y, mu, sigma); VectorView<const T_y> y_vec(y); VectorView<const T_loc> mu_vec(mu); VectorView<const T_scale> sigma_vec(sigma); size_t N = max_size(y, mu, sigma); // cdf for (size_t n = 0; n < N; n++) { const T_partials_return y_dbl = value_of(y_vec[n]); const T_partials_return mu_dbl = value_of(mu_vec[n]); const T_partials_return sigma_dbl = value_of(sigma_vec[n]); const T_partials_return scaled_diff = (y_dbl - mu_dbl) / (sigma_dbl); const T_partials_return exp_scaled_diff = exp(scaled_diff); if (y_dbl < mu_dbl) cdf *= exp_scaled_diff * 0.5; else cdf *= 1.0 - 0.5 / exp_scaled_diff; } // gradients for (size_t n = 0; n < N; n++) { const T_partials_return y_dbl = value_of(y_vec[n]); const T_partials_return mu_dbl = value_of(mu_vec[n]); const T_partials_return sigma_dbl = value_of(sigma_vec[n]); const T_partials_return scaled_diff = (y_dbl - mu_dbl) / sigma_dbl; const T_partials_return exp_scaled_diff = exp(scaled_diff); const T_partials_return inv_sigma = 1.0 / sigma_dbl; if (y_dbl < mu_dbl) { if (!is_constant_struct<T_y>::value) operands_and_partials.d_x1[n] += inv_sigma * cdf; if (!is_constant_struct<T_loc>::value) operands_and_partials.d_x2[n] -= inv_sigma * cdf; if (!is_constant_struct<T_scale>::value) operands_and_partials.d_x3[n] -= scaled_diff * inv_sigma * cdf; } else { const T_partials_return rep_deriv = cdf * inv_sigma / (2.0 * exp_scaled_diff - 1.0); if (!is_constant_struct<T_y>::value) operands_and_partials.d_x1[n] += rep_deriv; if (!is_constant_struct<T_loc>::value) operands_and_partials.d_x2[n] -= rep_deriv; if (!is_constant_struct<T_scale>::value) operands_and_partials.d_x3[n] -= rep_deriv * scaled_diff; } } return operands_and_partials.value(cdf); }
typename return_type<T_y, T_shape, T_scale>::type weibull_cdf(const T_y& y, const T_shape& alpha, const T_scale& sigma) { typedef typename stan::partials_return_type<T_y, T_shape, T_scale>::type T_partials_return; static const char* function("stan::math::weibull_cdf"); using stan::math::check_positive_finite; using stan::math::check_nonnegative; using boost::math::tools::promote_args; using stan::math::value_of; using std::log; using std::exp; // check if any vectors are zero length if (!(stan::length(y) && stan::length(alpha) && stan::length(sigma))) return 1.0; T_partials_return cdf(1.0); check_nonnegative(function, "Random variable", y); check_positive_finite(function, "Shape parameter", alpha); check_positive_finite(function, "Scale parameter", sigma); OperandsAndPartials<T_y, T_shape, T_scale> operands_and_partials(y, alpha, sigma); VectorView<const T_y> y_vec(y); VectorView<const T_scale> sigma_vec(sigma); VectorView<const T_shape> alpha_vec(alpha); size_t N = max_size(y, sigma, alpha); for (size_t n = 0; n < N; n++) { const T_partials_return y_dbl = value_of(y_vec[n]); const T_partials_return sigma_dbl = value_of(sigma_vec[n]); const T_partials_return alpha_dbl = value_of(alpha_vec[n]); const T_partials_return pow_ = pow(y_dbl / sigma_dbl, alpha_dbl); const T_partials_return exp_ = exp(-pow_); const T_partials_return cdf_ = 1.0 - exp_; // cdf cdf *= cdf_; // gradients const T_partials_return rep_deriv = exp_ * pow_ / cdf_; if (!is_constant_struct<T_y>::value) operands_and_partials.d_x1[n] += rep_deriv * alpha_dbl / y_dbl; if (!is_constant_struct<T_shape>::value) operands_and_partials.d_x2[n] += rep_deriv * log(y_dbl / sigma_dbl); if (!is_constant_struct<T_scale>::value) operands_and_partials.d_x3[n] -= rep_deriv * alpha_dbl / sigma_dbl; } if (!is_constant_struct<T_y>::value) { for (size_t n = 0; n < stan::length(y); ++n) operands_and_partials.d_x1[n] *= cdf; } if (!is_constant_struct<T_shape>::value) { for (size_t n = 0; n < stan::length(alpha); ++n) operands_and_partials.d_x2[n] *= cdf; } if (!is_constant_struct<T_scale>::value) { for (size_t n = 0; n < stan::length(sigma); ++n) operands_and_partials.d_x3[n] *= cdf; } return operands_and_partials.to_var(cdf, y, alpha, sigma); }
typename return_type<T_y, T_shape, T_inv_scale>::type gamma_ccdf_log(const T_y& y, const T_shape& alpha, const T_inv_scale& beta) { if (!(stan::length(y) && stan::length(alpha) && stan::length(beta))) return 0.0; typedef typename stan::partials_return_type<T_y, T_shape, T_inv_scale>::type T_partials_return; static const char* function("gamma_ccdf_log"); using boost::math::tools::promote_args; using std::exp; T_partials_return P(0.0); check_positive_finite(function, "Shape parameter", alpha); check_positive_finite(function, "Scale parameter", beta); check_not_nan(function, "Random variable", y); check_nonnegative(function, "Random variable", y); check_consistent_sizes(function, "Random variable", y, "Shape parameter", alpha, "Scale Parameter", beta); VectorView<const T_y> y_vec(y); VectorView<const T_shape> alpha_vec(alpha); VectorView<const T_inv_scale> beta_vec(beta); size_t N = max_size(y, alpha, beta); OperandsAndPartials<T_y, T_shape, T_inv_scale> operands_and_partials(y, alpha, beta); // Explicit return for extreme values // The gradients are technically ill-defined, but treated as zero for (size_t i = 0; i < stan::length(y); i++) { if (value_of(y_vec[i]) == 0) return operands_and_partials.value(0.0); } using boost::math::tgamma; using std::exp; using std::pow; using std::log; VectorBuilder<!is_constant_struct<T_shape>::value, T_partials_return, T_shape> gamma_vec(stan::length(alpha)); VectorBuilder<!is_constant_struct<T_shape>::value, T_partials_return, T_shape> digamma_vec(stan::length(alpha)); if (!is_constant_struct<T_shape>::value) { for (size_t i = 0; i < stan::length(alpha); i++) { const T_partials_return alpha_dbl = value_of(alpha_vec[i]); gamma_vec[i] = tgamma(alpha_dbl); digamma_vec[i] = digamma(alpha_dbl); } } for (size_t n = 0; n < N; n++) { // Explicit results for extreme values // The gradients are technically ill-defined, but treated as zero if (value_of(y_vec[n]) == std::numeric_limits<double>::infinity()) return operands_and_partials.value(negative_infinity()); const T_partials_return y_dbl = value_of(y_vec[n]); const T_partials_return alpha_dbl = value_of(alpha_vec[n]); const T_partials_return beta_dbl = value_of(beta_vec[n]); const T_partials_return Pn = gamma_q(alpha_dbl, beta_dbl * y_dbl); P += log(Pn); if (!is_constant_struct<T_y>::value) operands_and_partials.d_x1[n] -= beta_dbl * exp(-beta_dbl * y_dbl) * pow(beta_dbl * y_dbl, alpha_dbl-1) / tgamma(alpha_dbl) / Pn; if (!is_constant_struct<T_shape>::value) operands_and_partials.d_x2[n] += grad_reg_inc_gamma(alpha_dbl, beta_dbl * y_dbl, gamma_vec[n], digamma_vec[n]) / Pn; if (!is_constant_struct<T_inv_scale>::value) operands_and_partials.d_x3[n] -= y_dbl * exp(-beta_dbl * y_dbl) * pow(beta_dbl * y_dbl, alpha_dbl-1) / tgamma(alpha_dbl) / Pn; } return operands_and_partials.value(P); }
typename return_type<T_log_rate>::type poisson_log_log(const T_n& n, const T_log_rate& alpha) { typedef typename stan::partials_return_type<T_n,T_log_rate>::type T_partials_return; static const char* function("stan::prob::poisson_log_log"); using boost::math::lgamma; using stan::math::check_not_nan; using stan::math::check_nonnegative; using stan::math::value_of; using stan::math::check_consistent_sizes; using stan::prob::include_summand; using std::exp; // check if any vectors are zero length if (!(stan::length(n) && stan::length(alpha))) return 0.0; // set up return value accumulator T_partials_return logp(0.0); // validate args check_nonnegative(function, "Random variable", n); check_not_nan(function, "Log rate parameter", alpha); check_consistent_sizes(function, "Random variable", n, "Log rate parameter", alpha); // check if no variables are involved and prop-to if (!include_summand<propto,T_log_rate>::value) return 0.0; // set up expression templates wrapping scalars/vecs into vector views VectorView<const T_n> n_vec(n); VectorView<const T_log_rate> alpha_vec(alpha); size_t size = max_size(n, alpha); // FIXME: first loop size of alpha_vec, second loop if-ed for size==1 for (size_t i = 0; i < size; i++) if (std::numeric_limits<double>::infinity() == alpha_vec[i]) return LOG_ZERO; for (size_t i = 0; i < size; i++) if (-std::numeric_limits<double>::infinity() == alpha_vec[i] && n_vec[i] != 0) return LOG_ZERO; // return accumulator with gradients agrad::OperandsAndPartials<T_log_rate> operands_and_partials(alpha); // FIXME: cache value_of for alpha_vec? faster if only one? VectorBuilder<include_summand<propto,T_log_rate>::value, T_partials_return, T_log_rate> exp_alpha(length(alpha)); for (size_t i = 0; i < length(alpha); i++) if (include_summand<propto,T_log_rate>::value) exp_alpha[i] = exp(value_of(alpha_vec[i])); using stan::math::multiply_log; for (size_t i = 0; i < size; i++) { if (!(alpha_vec[i] == -std::numeric_limits<double>::infinity() && n_vec[i] == 0)) { if (include_summand<propto>::value) logp -= lgamma(n_vec[i] + 1.0); if (include_summand<propto,T_log_rate>::value) logp += n_vec[i] * value_of(alpha_vec[i]) - exp_alpha[i]; } // gradients if (!is_constant_struct<T_log_rate>::value) operands_and_partials.d_x1[i] += n_vec[i] - exp_alpha[i]; } return operands_and_partials.to_var(logp,alpha); }
typename return_type<T_rate>::type poisson_cdf_log(const T_n& n, const T_rate& lambda) { static const char* function("stan::prob::poisson_cdf_log"); typedef typename stan::partials_return_type<T_n,T_rate>::type T_partials_return; using stan::math::check_not_nan; using stan::math::check_nonnegative; using stan::math::value_of; using stan::math::check_consistent_sizes; // Ensure non-zero argument slengths if (!(stan::length(n) && stan::length(lambda))) return 0.0; T_partials_return P(0.0); // Validate arguments check_not_nan(function, "Rate parameter", lambda); check_nonnegative(function, "Rate parameter", lambda); check_consistent_sizes(function, "Random variable", n, "Rate parameter", lambda); // Wrap arguments into vector views VectorView<const T_n> n_vec(n); VectorView<const T_rate> lambda_vec(lambda); size_t size = max_size(n, lambda); // Compute vectorized cdf_log and gradient using stan::math::value_of; using stan::math::gamma_q; using boost::math::tgamma; using std::exp; using std::pow; agrad::OperandsAndPartials<T_rate> operands_and_partials(lambda); // Explicit return for extreme values // The gradients are technically ill-defined, but treated as neg infinity for (size_t i = 0; i < stan::length(n); i++) { if (value_of(n_vec[i]) < 0) return operands_and_partials.to_var(stan::math::negative_infinity(), lambda); } for (size_t i = 0; i < size; i++) { // Explicit results for extreme values // The gradients are technically ill-defined, but treated as zero if (value_of(n_vec[i]) == std::numeric_limits<int>::max()) continue; const T_partials_return n_dbl = value_of(n_vec[i]); const T_partials_return lambda_dbl = value_of(lambda_vec[i]); const T_partials_return Pi = gamma_q(n_dbl+1, lambda_dbl); P += log(Pi); if (!is_constant_struct<T_rate>::value) operands_and_partials.d_x1[i] -= exp(-lambda_dbl) * pow(lambda_dbl,n_dbl) / tgamma(n_dbl+1) / Pi; } return operands_and_partials.to_var(P,lambda); }