Turi Create  4.0
logit_math.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 #ifndef TURI_LOGIT_MATH_H_
7 #define TURI_LOGIT_MATH_H_
8 
9 
10 #include <core/util/code_optimization.hpp>
11 #include <core/logging/assertions.hpp>
12 #include <cmath>
13 
14 
15 namespace turi {
16 
17 /** Numerically stable version of 1 / (1 + exp(-x));
18  *
19  * If x < 0, then this is equal to
20  *
21  * exp(- abs(x)) / (1 + exp(-abs(x))) = 1 / (1 + exp(x))
22  *
23  * If x >=0, then this is equal to 1 / (1 + exp(-x)).
24  *
25  * This separation into the positive and negative case is so that the
26  * code never uses the result of exp(x) where x is large and
27  * positive, which could easily result in overflow.
28  */
29 static inline
31  double sigmoid(double x) {
32  double m_abs_x = std::copysign(x, -1.0);
33  double exp_neg = std::exp(m_abs_x);
34  bool is_negative = std::signbit(x);
35  double numerator = is_negative ? exp_neg : 1.0;
36 
37  return numerator / (1.0 + exp_neg);
38 }
39 
40 /** Numerically stable version of log(1 + exp(x) )
41  */
42 static inline GL_HOT_INLINE_FLATTEN double log1pe(double x)
43 {
44  return __builtin_expect((x > 48), 0) ? x : std::log1p(exp(x));
45 }
46 
47 /** Numerically stable version of log(1 + exp(-x) )
48  */
49 static inline GL_HOT_INLINE_FLATTEN double log1pen(double x)
50 {
51  return __builtin_expect((x < -48), 0) ? -x : std::log1p(exp(-x));
52 }
53 
54 /** Numerically stable version of log(1 - exp(x) )
55  */
56 static inline GL_HOT_INLINE_FLATTEN double log1me(double x)
57 {
58  DASSERT_LT(x, 0);
59  return __builtin_expect((x < -48), 0) ? 0 : std::log1p(-exp(x));
60 }
61 
62 /** Numerically stable version of log(1 - exp(-x) )
63  */
64 static inline GL_HOT_INLINE_FLATTEN double log1men(double x)
65 {
66  DASSERT_GT(x, 0);
67  return __builtin_expect((x > 48), 0) ? 0 : std::log1p(-exp(-x));
68 }
69 
70 /** Numerically stable version of log(exp(x) - 1)
71  */
72 static inline GL_HOT_INLINE_FLATTEN double logem1(double x)
73 {
74  return __builtin_expect((x > 48), 0) ? x : std::log(std::expm1(x));
75 }
76 
77 /** Numerically stable version of
78  * d/dx (log(1 + exp(x) )) = 1 / (1 + exp(-x)) = sigmoid(x).
79  */
80 static inline GL_HOT_INLINE_FLATTEN double log1pe_deriviative(double x)
81 {
82  return sigmoid(x);
83 }
84 
85 /** Numerically stable version of
86  * d/dx (log(1 + exp(-x) )) = -1 / (1 + exp(x)).
87  */
88 static inline GL_HOT_INLINE_FLATTEN double log1pen_deriviative(double x)
89 {
90  double m_abs_x = std::copysign(x, -1.0);
91  double exp_neg = std::exp(m_abs_x);
92  bool is_negative = std::signbit(x);
93  double numerator = is_negative ? 1.0 : exp_neg;
94 
95  return -numerator / (1.0 + exp_neg);
96 }
97 
98 template <typename T> static inline T sq(const T& t) { return t*t; }
99 
100 
101 }
102 
103 
104 #endif /* _LOGIT_MATH_H_ */
static GL_HOT_INLINE_FLATTEN double log1pe(double x)
Definition: logit_math.hpp:42
static GL_HOT_INLINE_FLATTEN double log1pe_deriviative(double x)
Definition: logit_math.hpp:80
static GL_HOT_INLINE_FLATTEN double logem1(double x)
Definition: logit_math.hpp:72
static GL_HOT_INLINE_FLATTEN double log1pen_deriviative(double x)
Definition: logit_math.hpp:88
static GL_HOT_INLINE_FLATTEN double sigmoid(double x)
Definition: logit_math.hpp:31
static GL_HOT_INLINE_FLATTEN double log1me(double x)
Definition: logit_math.hpp:56
static GL_HOT_INLINE_FLATTEN double log1pen(double x)
Definition: logit_math.hpp:49
#define GL_HOT_INLINE_FLATTEN
static GL_HOT_INLINE_FLATTEN double log1men(double x)
Definition: logit_math.hpp:64