Stan  1.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
special_functions.hpp
Go to the documentation of this file.
1 #ifndef __STAN__MATH__SPECIAL_FUNCTIONS_HPP__
2 #define __STAN__MATH__SPECIAL_FUNCTIONS_HPP__
3 
4 #include <stdexcept>
5 
6 
7 #include <boost/math/special_functions/gamma.hpp>
8 #include <boost/math/special_functions/beta.hpp>
9 #include <boost/math/tools/promotion.hpp>
10 #include <boost/throw_exception.hpp>
11 
12 #include <stan/math/constants.hpp>
14 
15 namespace stan {
16 
17  namespace math {
18 
19  // C99
20 
32  template <typename T>
33  inline typename boost::math::tools::promote_args<T>::type
34  exp2(T y) {
35  using std::pow;
36  return pow(2.0,y);
37  }
38 
50  template <typename T1, typename T2>
51  inline typename boost::math::tools::promote_args<T1, T2>::type
52  fdim(T1 a, T2 b) {
53  return (a > b) ? (a - b) : 0.0;
54  }
55 
68  template <typename T1, typename T2, typename T3>
69  inline typename boost::math::tools::promote_args<T1,T2,T3>::type
70  fma(T1 a, T2 b, T3 c) {
71  return (a * b) + c;
72  }
73 
85  template <typename T>
86  inline typename boost::math::tools::promote_args<T>::type
87  log2(T a) {
88  using std::log;
89  const static double LOG2 = std::log(2.0);
90  return log(a) / LOG2;
91  }
92 
93  // OTHER BASIC FUNCTIONS
94 
102  template <typename T>
103  unsigned int int_step(T y) {
104  return y > 0;
105  }
106 
119  template <typename T>
120  inline int step(T y) {
121  return y < 0.0 ? 0 : 1;
122  }
123 
124 
125  // PROBABILITY-RELATED FUNCTIONS
126 
148  template <typename T1, typename T2>
149  inline typename boost::math::tools::promote_args<T1,T2>::type
150  lbeta(T1 a, T2 b) {
151  return lgamma(a)
152  + lgamma(b)
153  - lgamma(a + b);
154  }
155 
174  template <typename T_N, typename T_n>
175  inline typename boost::math::tools::promote_args<T_N, T_n>::type
176  binomial_coefficient_log(T_N N, T_n n) {
177  using std::log;
178 
179  const double cutoff = 1000;
180  if ((N < cutoff) || (N - n < cutoff)) {
181  return lgamma(N + 1.0) - lgamma(n + 1.0) - lgamma(N - n + 1.0);
182  } else {
183  return n * log(N - n) + (N + 0.5) * log(N/(N-n))
184  + 1/(12*N) - n - 1/(12*(N-n)) - lgamma(n + 1.0);
185  }
186  }
187 
203  template <typename T>
204  inline typename boost::math::tools::promote_args<T>::type
205  inv_logit(T a) {
206  using std::exp;
207  return 1.0 / (1.0 + exp(-a));
208  }
209 
224  template <typename T>
225  inline typename boost::math::tools::promote_args<T>::type
226  logit(T a) {
227  using std::log;
228  return log(a / (1.0 - a));
229  }
230 
231 
232 
248  template <typename T>
249  inline typename boost::math::tools::promote_args<T>::type
250  Phi(T x) {
251  static const double INV_SQRT_TWO = 1.0 / std::sqrt(2.0);
252  return 0.5 * (1.0 + boost::math::erf(INV_SQRT_TWO * x));
253  }
254 
268  template <typename T>
269  inline typename boost::math::tools::promote_args<T>::type
270  inv_cloglog(T x) {
271  using std::exp;
272  return exp(-exp(x));
273  }
274 
290  template <typename T>
291  inline typename boost::math::tools::promote_args<T>::type
292  binary_log_loss(int y, T y_hat) {
293  using std::log;
294  return -log(y ? y_hat : (1.0 - y_hat));
295  }
296 
297  // hide helper for now; could use Eigen here
298  namespace {
299  template <typename Vector, typename Scalar>
300  Scalar maximum(const Vector& x) {
301  if(x.size() == 0)
302  BOOST_THROW_EXCEPTION(std::invalid_argument ("x must have at least one element"));
303  Scalar max_x(x[0]);
304  for (typename Vector::size_type i = 1; i < x.size(); ++i)
305  if (x[i] < max_x)
306  max_x = x[i];
307  return max_x;
308  }
309  }
310 
311 
361  template <typename Vector, typename Scalar>
362  void softmax(const Vector& x, Vector& simplex) {
363  using std::exp;
364  if(x.size() != simplex.size())
365  BOOST_THROW_EXCEPTION(std::invalid_argument ("x.size() != simplex.size()"));
366  Scalar sum(0.0);
367  Scalar max_x = maximum<Vector,Scalar>(x);
368  for (typename Vector::size_type i = 0; i < x.size(); ++i)
369  sum += (simplex[i] = exp(x[i]-max_x));
370  for (typename Vector::size_type i = 0; i < x.size(); ++i)
371  simplex[i] /= sum;
372  }
373 
396  template <typename Vector>
397  void inverse_softmax(const Vector& simplex, Vector& y) {
398  using std::log;
399  if(simplex.size() != y.size())
400  BOOST_THROW_EXCEPTION(std::invalid_argument ("simplex.size() != y.size()"));
401  for (size_t i = 0; i < simplex.size(); ++i)
402  y[i] = log(simplex[i]);
403  }
404 
414  template <typename T>
415  inline typename boost::math::tools::promote_args<T>::type
416  log1p(T x) {
417  using std::log;
418  if (x < -1.0)
419  BOOST_THROW_EXCEPTION(std::domain_error ("x can not be less than -1"));
420 
421  if (x > 1e-9 || x < -1e-9)
422  return log(1.0 + x); // direct, if distant from 1
423  else if (x > 1e-16 || x < -1e-16)
424  return x - 0.5 * x * x; // 2nd order Taylor, if close to 1
425  else
426  return x; // 1st order Taylor, if very close to 1
427  }
428 
438  template <typename T>
439  inline typename boost::math::tools::promote_args<T>::type
440  log1m(T x) {
441  return log1p(-x);
442  }
443 
444  namespace {
445  const double LOG_PI_OVER_FOUR = std::log(boost::math::constants::pi<double>()) / 4.0;
446  }
447 
464  template <typename T>
465  inline typename boost::math::tools::promote_args<T>::type
466  lmgamma(unsigned int k, T x) {
467  typename boost::math::tools::promote_args<T>::type result
468  = k * (k - 1) * LOG_PI_OVER_FOUR;
469  for (unsigned int j = 1; j <= k; ++j)
470  result += lgamma(x + (1.0 - j) / 2.0);
471  return result;
472  }
473 
474 
489  inline double if_else(bool c, double y_true, double y_false) {
490  return c ? y_true : y_false;
491  }
492 
507  template <typename T>
508  inline T square(T x) {
509  return x * x;
510  }
511 
512  template <typename T_a, typename T_b>
513  inline typename boost::math::tools::promote_args<T_a,T_b>::type
514  multiply_log(T_a a, T_b b) {
515  using std::log;
516  if (b == 0.0 && a == 0.0)
517  return 0.0;
518  return a * log(b);
519  }
520 
535  inline double log1p_exp(const double& a) {
536  using std::exp;
537  // like log_sum_exp below with b=0.0
538  if (a > 0.0)
539  return a + log1p(exp(-a));
540  return log1p(exp(a));
541  }
542 
553  inline double log_sum_exp(const double& a, const double& b) {
554  using std::exp;
555  if (a > b)
556  return a + log1p(exp(b - a));
557  return b + log1p(exp(a - b));
558  }
559 
572  inline double ibeta(const double& a,
573  const double& b,
574  const double& x) {
575  return boost::math::ibeta(a, b, x);
576  }
577 
578 
579 
591  static double log_sum_exp(const std::vector<double>& x) {
592  using std::numeric_limits;
593  using std::log;
594  using std::exp;
595  double max = -numeric_limits<double>::infinity();
596  for (size_t ii = 0; ii < x.size(); ii++)
597  if (x[ii] > max)
598  max = x[ii];
599 
600  double sum = 0.0;
601  for (size_t ii = 0; ii < x.size(); ii++)
602  if (x[ii] != -numeric_limits<double>::infinity())
603  sum += exp(x[ii] - max);
604 
605  return max + log(sum);
606  }
607 
625  template <typename T1, typename T2, typename T3>
626  inline double simple_var(double v,
627  const T1& /*y1*/, const T1& /*dy1*/,
628  const T2& /*y2*/, const T2& /*dy2*/,
629  const T3& /*y3*/, const T3& /*dy3*/) {
630  return v;
631  }
632 
645  template <typename T>
646  inline double value_of(T x) {
647  return static_cast<double>(x);
648  }
649 
661  template <>
662  inline double value_of<double>(double x) {
663  return x;
664  }
665 
666  // CONSTANTS
667 
673  inline double pi() {
674  return boost::math::constants::pi<double>();
675  }
676 
682  inline double e() {
683  return E;
684  }
685 
691  inline double sqrt2() {
692  return SQRT_2;
693  }
694 
700  inline double log2() {
701  return LOG_2;
702  }
703 
709  inline double log10() {
710  return LOG_10;
711  }
712 
718  inline double positive_infinity() {
719  return INFTY;
720  }
721 
727  inline double negative_infinity() {
728  return NEGATIVE_INFTY;
729  }
730 
736  inline double not_a_number() {
737  return NOT_A_NUMBER;
738  }
739 
745  inline double epsilon() {
746  return EPSILON;
747  }
748 
755  inline double negative_epsilon() {
756  return NEGATIVE_EPSILON;
757  }
758 
759  }
760 
761 
762 }
763 
764 #endif

     [ Stan Home Page ] © 2011–2012, Stan Development Team.