Tor  0.4.4.0-alpha-dev
prob_distr.h
Go to the documentation of this file.
1 
2 /**
3  * \file prob_distr.h
4  *
5  * \brief Header for prob_distr.c
6  **/
7 
8 #ifndef TOR_PROB_DISTR_H
9 #define TOR_PROB_DISTR_H
10 
11 #include "lib/cc/compat_compiler.h"
12 #include "lib/cc/torint.h"
14 
15 /**
16  * Container for distribution parameters for sampling, CDF, &c.
17  */
18 struct dist_t {
19  const struct dist_ops_t *ops;
20 };
21 
22 /**
23  * Untyped initializer element for struct dist_t using the specified
24  * struct dist_ops_t pointer. Don't actually use this directly -- use
25  * the type-specific macro built out of DIST_BASE_TYPED below -- but if
26  * you did use this directly, it would be something like:
27  *
28  * struct weibull mydist = {
29  * DIST_BASE(&weibull_ops),
30  * .lambda = ...,
31  * .k = ...,
32  * };
33  *
34  * Note there is NO COMPILER FEEDBACK if you accidentally do something
35  * like
36  *
37  * struct geometric mydist = {
38  * DIST_BASE(&weibull_ops),
39  * ...
40  * };
41  */
42 #define DIST_BASE(OPS) { .ops = (OPS) }
43 
44 /** A compile-time type-checking macro for use with DIST_BASE_TYPED.
45  *
46  * This macro works by checking that &OBJ is a pointer type that is the same
47  * type (except for qualifiers) as (const TYPE *)&OBJ. It's a C constraint
48  * violation (which requires a diagnostic) if two pointers are different types
49  * and are subtracted. The sizeof() forces compile-time evaluation, and the
50  * multiplication by zero is to discard the result of the sizeof() from the
51  * expression.
52  *
53  * We define this conditionally to suppress false positives from
54  * Coverity, which gets confused by the sizeof business.
55  */
56 #ifdef __COVERITY__
57 #define TYPE_CHECK_OBJ(OPS, OBJ, TYPE) 0
58 #else
59 #define TYPE_CHECK_OBJ(OPS, OBJ, TYPE) \
60  (0*sizeof(&(OBJ) - (const TYPE *)&(OBJ)))
61 #endif /* defined(__COVERITY__) */
62 
63 /**
64 * Typed initializer element for struct dist_t using the specified struct
65 * dist_ops_t pointer. Don't actually use this directly -- use a
66 * type-specific macro built out of it -- but if you did use this
67 * directly, it would be something like:
68 *
69 * struct weibull mydist = {
70 * DIST_BASE_TYPED(&weibull_ops, mydist, struct weibull_t),
71 * .lambda = ...,
72 * .k = ...,
73 * };
74 *
75 * If you want to define a distribution type, define a canonical set of
76 * operations and define a type-specific initializer element like so:
77 *
78 * struct foo_t {
79 * struct dist_t base;
80 * int omega;
81 * double tau;
82 * double phi;
83 * };
84 *
85 * struct dist_ops_t foo_ops = ...;
86 *
87 * #define FOO(OBJ) DIST_BASE_TYPED(&foo_ops, OBJ, struct foo_t)
88 *
89 * Then users can do:
90 *
91 * struct foo_t mydist = {
92 * FOO(mydist),
93 * .omega = ...,
94 * .tau = ...,
95 * .phi = ...,
96 * };
97 *
98 * If you accidentally write
99 *
100 * struct bar_t mydist = {
101 * FOO(mydist),
102 * ...
103 * };
104 *
105 * then the compiler will report a type mismatch in the sizeof
106 * expression, which otherwise evaporates at runtime.
107 */
108 #define DIST_BASE_TYPED(OPS, OBJ, TYPE) \
109  DIST_BASE((OPS) + TYPE_CHECK_OBJ(OPS,OBJ,TYPE))
110 
111 /**
112  * Generic operations on distributions. These simply defer to the
113  * corresponding dist_ops_t function. In the parlance of C++, these call
114  * virtual member functions.
115  */
116 const char *dist_name(const struct dist_t *);
117 double dist_sample(const struct dist_t *);
118 double dist_cdf(const struct dist_t *, double x);
119 double dist_sf(const struct dist_t *, double x);
120 double dist_icdf(const struct dist_t *, double p);
121 double dist_isf(const struct dist_t *, double p);
122 
123 /**
124  * Set of operations on a potentially parametric family of
125  * distributions. In the parlance of C++, this would be called a
126  * `vtable' and the members are virtual member functions.
127  */
128 struct dist_ops_t {
129  const char *name;
130  double (*sample)(const struct dist_t *);
131  double (*cdf)(const struct dist_t *, double x);
132  double (*sf)(const struct dist_t *, double x);
133  double (*icdf)(const struct dist_t *, double p);
134  double (*isf)(const struct dist_t *, double p);
135 };
136 
137 /* Geometric distribution on positive number of trials before first success */
138 
139 struct geometric_t {
140  struct dist_t base;
141  double p; /* success probability */
142 };
143 
144 extern const struct dist_ops_t geometric_ops;
145 
146 #define GEOMETRIC(OBJ) \
147  DIST_BASE_TYPED(&geometric_ops, OBJ, struct geometric_t)
148 
149 /* Pareto distribution */
150 
151 struct genpareto_t {
152  struct dist_t base;
153  double mu;
154  double sigma;
155  double xi;
156 };
157 
158 extern const struct dist_ops_t genpareto_ops;
159 
160 #define GENPARETO(OBJ) \
161  DIST_BASE_TYPED(&genpareto_ops, OBJ, struct genpareto_t)
162 
163 /* Weibull distribution */
164 
165 struct weibull_t {
166  struct dist_t base;
167  double lambda;
168  double k;
169 };
170 
171 extern const struct dist_ops_t weibull_ops;
172 
173 #define WEIBULL(OBJ) \
174  DIST_BASE_TYPED(&weibull_ops, OBJ, struct weibull_t)
175 
176 /* Log-logistic distribution */
177 
179  struct dist_t base;
180  double alpha;
181  double beta;
182 };
183 
184 extern const struct dist_ops_t log_logistic_ops;
185 
186 #define LOG_LOGISTIC(OBJ) \
187  DIST_BASE_TYPED(&log_logistic_ops, OBJ, struct log_logistic_t)
188 
189 /* Logistic distribution */
190 
191 struct logistic_t {
192  struct dist_t base;
193  double mu;
194  double sigma;
195 };
196 
197 extern const struct dist_ops_t logistic_ops;
198 
199 #define LOGISTIC(OBJ) \
200  DIST_BASE_TYPED(&logistic_ops, OBJ, struct logistic_t)
201 
202 /* Uniform distribution */
203 
204 struct uniform_t {
205  struct dist_t base;
206  double a;
207  double b;
208 };
209 
210 extern const struct dist_ops_t uniform_ops;
211 
212 #define UNIFORM(OBJ) \
213  DIST_BASE_TYPED(&uniform_ops, OBJ, struct uniform_t)
214 
215 /** Only by unittests */
216 
217 #ifdef PROB_DISTR_PRIVATE
218 
219 STATIC double logithalf(double p0);
220 STATIC double logit(double p);
221 
222 STATIC double random_uniform_01(void);
223 
224 STATIC double logistic(double x);
225 STATIC double cdf_logistic(double x, double mu, double sigma);
226 STATIC double sf_logistic(double x, double mu, double sigma);
227 STATIC double icdf_logistic(double p, double mu, double sigma);
228 STATIC double isf_logistic(double p, double mu, double sigma);
229 STATIC double sample_logistic(uint32_t s, double t, double p0);
230 
231 STATIC double cdf_log_logistic(double x, double alpha, double beta);
232 STATIC double sf_log_logistic(double x, double alpha, double beta);
233 STATIC double icdf_log_logistic(double p, double alpha, double beta);
234 STATIC double isf_log_logistic(double p, double alpha, double beta);
235 STATIC double sample_log_logistic(uint32_t s, double p0);
236 
237 STATIC double cdf_weibull(double x, double lambda, double k);
238 STATIC double sf_weibull(double x, double lambda, double k);
239 STATIC double icdf_weibull(double p, double lambda, double k);
240 STATIC double isf_weibull(double p, double lambda, double k);
241 STATIC double sample_weibull(uint32_t s, double p0, double lambda, double k);
242 
243 STATIC double sample_uniform_interval(double p0, double a, double b);
244 
245 STATIC double cdf_genpareto(double x, double mu, double sigma, double xi);
246 STATIC double sf_genpareto(double x, double mu, double sigma, double xi);
247 STATIC double icdf_genpareto(double p, double mu, double sigma, double xi);
248 STATIC double isf_genpareto(double p, double mu, double sigma, double xi);
249 STATIC double sample_genpareto(uint32_t s, double p0, double xi);
250 
251 #endif /* defined(PROB_DISTR_PRIVATE) */
252 
253 #endif /* !defined(TOR_PROB_DISTR_H) */
STATIC double logithalf(double p0)
Definition: prob_distr.c:360
STATIC double sf_logistic(double x, double mu, double sigma)
Definition: prob_distr.c:523
STATIC double cdf_genpareto(double x, double mu, double sigma, double xi)
Definition: prob_distr.c:792
double dist_cdf(const struct dist_t *, double x)
Definition: prob_distr.c:1343
STATIC double isf_genpareto(double p, double mu, double sigma, double xi)
Definition: prob_distr.c:899
STATIC double isf_logistic(double p, double mu, double sigma)
Definition: prob_distr.c:545
STATIC double icdf_genpareto(double p, double mu, double sigma, double xi)
Definition: prob_distr.c:853
STATIC double logit(double p)
Definition: prob_distr.c:280
STATIC double logistic(double x)
Definition: prob_distr.c:193
STATIC double sf_weibull(double x, double lambda, double k)
Definition: prob_distr.c:726
double dist_icdf(const struct dist_t *, double p)
Definition: prob_distr.c:1357
STATIC double sample_log_logistic(uint32_t s, double p0)
Definition: prob_distr.c:1160
Integer definitions used throughout Tor.
STATIC double icdf_log_logistic(double p, double alpha, double beta)
Definition: prob_distr.c:675
STATIC double sf_log_logistic(double x, double alpha, double beta)
Definition: prob_distr.c:659
double dist_isf(const struct dist_t *, double p)
Definition: prob_distr.c:1364
#define STATIC
Definition: testsupport.h:32
STATIC double cdf_weibull(double x, double lambda, double k)
Definition: prob_distr.c:711
STATIC double cdf_logistic(double x, double mu, double sigma)
Definition: prob_distr.c:511
STATIC double sf_genpareto(double x, double mu, double sigma, double xi)
Definition: prob_distr.c:836
STATIC double cdf_log_logistic(double x, double alpha, double beta)
Definition: prob_distr.c:598
Utility macros to handle different features and behavior in different compilers.
STATIC double sample_uniform_interval(double p0, double a, double b)
Definition: prob_distr.c:941
STATIC double icdf_logistic(double p, double mu, double sigma)
Definition: prob_distr.c:534
double dist_sf(const struct dist_t *, double x)
Definition: prob_distr.c:1350
STATIC double isf_weibull(double p, double lambda, double k)
Definition: prob_distr.c:752
STATIC double sample_genpareto(uint32_t s, double p0, double xi)
Definition: prob_distr.c:1231
const char * dist_name(const struct dist_t *)
Definition: prob_distr.c:1329
Macros to implement mocking and selective exposure for the test code.
STATIC double random_uniform_01(void)
Definition: prob_distr.c:453
STATIC double sample_logistic(uint32_t s, double t, double p0)
Definition: prob_distr.c:1094
STATIC double isf_log_logistic(double p, double alpha, double beta)
Definition: prob_distr.c:686
STATIC double sample_weibull(uint32_t s, double p0, double lambda, double k)
Definition: prob_distr.c:1219
STATIC double icdf_weibull(double p, double lambda, double k)
Definition: prob_distr.c:739