[tor-commits] [tor/master] prob_distr: Implement type-safe downcasting functions.

teor at torproject.org teor at torproject.org
Fri Mar 22 03:11:29 UTC 2019


commit 8d9f81bc9cdca3022ec3243145bf232fe4f28579
Author: George Kadianakis <desnacked at riseup.net>
Date:   Tue Mar 5 17:49:44 2019 +0200

    prob_distr: Implement type-safe downcasting functions.
---
 src/lib/math/prob_distr.c | 133 ++++++++++++++++------------------------------
 1 file changed, 46 insertions(+), 87 deletions(-)

diff --git a/src/lib/math/prob_distr.c b/src/lib/math/prob_distr.c
index c952dadc0..2dff9e76e 100644
--- a/src/lib/math/prob_distr.c
+++ b/src/lib/math/prob_distr.c
@@ -46,26 +46,27 @@
 
 #include "lib/crypt_ops/crypto_rand.h"
 #include "lib/cc/ctassert.h"
+#include "lib/log/util_bug.h"
 
 #include <float.h>
 #include <math.h>
 #include <stddef.h>
 
-/** Validators for downcasting macros below */
-#define validate_container_of(PTR, TYPE, FIELD)                         \
-  (0 * sizeof((PTR) - &((TYPE *)(((char *)(PTR)) -                      \
-      offsetof(TYPE, FIELD)))->FIELD))
-#define validate_const_container_of(PTR, TYPE, FIELD)                   \
-  (0 * sizeof((PTR) - &((const TYPE *)(((const char *)(PTR)) -          \
-      offsetof(TYPE, FIELD)))->FIELD))
-/** Downcasting macro */
-#define container_of(PTR, TYPE, FIELD)                                  \
-  ((TYPE *)(((char *)(PTR)) - offsetof(TYPE, FIELD))                    \
-    + validate_container_of(PTR, TYPE, FIELD))
-/** Constified downcasting macro */
-#define const_container_of(PTR, TYPE, FIELD)                            \
-  ((const TYPE *)(((const char *)(PTR)) - offsetof(TYPE, FIELD))        \
-    + validate_const_container_of(PTR, TYPE, FIELD))
+/** Declare a function that downcasts from a generic dist struct to the actual
+ *  subtype probablity distribution it represents. */
+#define DECLARE_PROB_DISTR_DOWNCAST_FN(name) \
+  static inline                           \
+  const struct name *                             \
+  dist_to_const_##name(const struct dist *obj) {    \
+    tor_assert(obj->ops == &name##_ops);            \
+    return SUBTYPE_P(obj, struct name, base);   \
+  }
+DECLARE_PROB_DISTR_DOWNCAST_FN(uniform)
+DECLARE_PROB_DISTR_DOWNCAST_FN(geometric)
+DECLARE_PROB_DISTR_DOWNCAST_FN(logistic)
+DECLARE_PROB_DISTR_DOWNCAST_FN(log_logistic)
+DECLARE_PROB_DISTR_DOWNCAST_FN(genpareto)
+DECLARE_PROB_DISTR_DOWNCAST_FN(weibull)
 
 /**
  * Count number of one bits in 32-bit word.
@@ -1360,8 +1361,7 @@ dist_isf(const struct dist *dist, double p)
 static double
 uniform_sample(const struct dist *dist)
 {
-  const struct uniform *U = const_container_of(dist, struct uniform,
-    base);
+  const struct uniform *U = dist_to_const_uniform(dist);
   double p0 = random_uniform_01();
 
   return sample_uniform_interval(p0, U->a, U->b);
@@ -1370,9 +1370,7 @@ uniform_sample(const struct dist *dist)
 static double
 uniform_cdf(const struct dist *dist, double x)
 {
-  const struct uniform *U = const_container_of(dist, struct uniform,
-    base);
-
+  const struct uniform *U = dist_to_const_uniform(dist);
   if (x < U->a)
     return 0;
   else if (x < U->b)
@@ -1384,8 +1382,7 @@ uniform_cdf(const struct dist *dist, double x)
 static double
 uniform_sf(const struct dist *dist, double x)
 {
-  const struct uniform *U = const_container_of(dist, struct uniform,
-    base);
+  const struct uniform *U = dist_to_const_uniform(dist);
 
   if (x > U->b)
     return 0;
@@ -1398,8 +1395,7 @@ uniform_sf(const struct dist *dist, double x)
 static double
 uniform_icdf(const struct dist *dist, double p)
 {
-  const struct uniform *U = const_container_of(dist, struct uniform,
-    base);
+  const struct uniform *U = dist_to_const_uniform(dist);
   double w = U->b - U->a;
 
   return (p < 0.5 ? (U->a + w*p) : (U->b - w*(1 - p)));
@@ -1408,8 +1404,7 @@ uniform_icdf(const struct dist *dist, double p)
 static double
 uniform_isf(const struct dist *dist, double p)
 {
-  const struct uniform *U = const_container_of(dist, struct uniform,
-    base);
+  const struct uniform *U = dist_to_const_uniform(dist);
   double w = U->b - U->a;
 
   return (p < 0.5 ? (U->b - w*p) : (U->a + w*(1 - p)));
@@ -1429,8 +1424,7 @@ const struct dist_ops uniform_ops = {
 static double
 logistic_sample(const struct dist *dist)
 {
-  const struct logistic *L = const_container_of(dist, struct logistic,
-    base);
+  const struct logistic *L = dist_to_const_logistic(dist);
   uint32_t s = crypto_rand_u32();
   double t = random_uniform_01();
   double p0 = random_uniform_01();
@@ -1441,36 +1435,28 @@ logistic_sample(const struct dist *dist)
 static double
 logistic_cdf(const struct dist *dist, double x)
 {
-  const struct logistic *L = const_container_of(dist, struct logistic,
-    base);
-
+  const struct logistic *L = dist_to_const_logistic(dist);
   return cdf_logistic(x, L->mu, L->sigma);
 }
 
 static double
 logistic_sf(const struct dist *dist, double x)
 {
-  const struct logistic *L = const_container_of(dist, struct logistic,
-    base);
-
+  const struct logistic *L = dist_to_const_logistic(dist);
   return sf_logistic(x, L->mu, L->sigma);
 }
 
 static double
 logistic_icdf(const struct dist *dist, double p)
 {
-  const struct logistic *L = const_container_of(dist, struct logistic,
-    base);
-
+  const struct logistic *L = dist_to_const_logistic(dist);
   return icdf_logistic(p, L->mu, L->sigma);
 }
 
 static double
 logistic_isf(const struct dist *dist, double p)
 {
-  const struct logistic *L = const_container_of(dist, struct logistic,
-    base);
-
+  const struct logistic *L = dist_to_const_logistic(dist);
   return isf_logistic(p, L->mu, L->sigma);
 }
 
@@ -1488,8 +1474,7 @@ const struct dist_ops logistic_ops = {
 static double
 log_logistic_sample(const struct dist *dist)
 {
-  const struct log_logistic *LL = const_container_of(dist, struct
-    log_logistic, base);
+  const struct log_logistic *LL = dist_to_const_log_logistic(dist);
   uint32_t s = crypto_rand_u32();
   double p0 = random_uniform_01();
 
@@ -1499,36 +1484,28 @@ log_logistic_sample(const struct dist *dist)
 static double
 log_logistic_cdf(const struct dist *dist, double x)
 {
-  const struct log_logistic *LL = const_container_of(dist,
-    struct log_logistic, base);
-
+  const struct log_logistic *LL = dist_to_const_log_logistic(dist);
   return cdf_log_logistic(x, LL->alpha, LL->beta);
 }
 
 static double
 log_logistic_sf(const struct dist *dist, double x)
 {
-  const struct log_logistic *LL = const_container_of(dist,
-    struct log_logistic, base);
-
+  const struct log_logistic *LL = dist_to_const_log_logistic(dist);
   return sf_log_logistic(x, LL->alpha, LL->beta);
 }
 
 static double
 log_logistic_icdf(const struct dist *dist, double p)
 {
-  const struct log_logistic *LL = const_container_of(dist,
-    struct log_logistic, base);
-
+  const struct log_logistic *LL = dist_to_const_log_logistic(dist);
   return icdf_log_logistic(p, LL->alpha, LL->beta);
 }
 
 static double
 log_logistic_isf(const struct dist *dist, double p)
 {
-  const struct log_logistic *LL = const_container_of(dist,
-    struct log_logistic, base);
-
+  const struct log_logistic *LL = dist_to_const_log_logistic(dist);
   return isf_log_logistic(p, LL->alpha, LL->beta);
 }
 
@@ -1546,8 +1523,7 @@ const struct dist_ops log_logistic_ops = {
 static double
 weibull_sample(const struct dist *dist)
 {
-  const struct weibull *W = const_container_of(dist, struct weibull,
-    base);
+  const struct weibull *W = dist_to_const_weibull(dist);
   uint32_t s = crypto_rand_u32();
   double p0 = random_uniform_01();
 
@@ -1557,36 +1533,28 @@ weibull_sample(const struct dist *dist)
 static double
 weibull_cdf(const struct dist *dist, double x)
 {
-  const struct weibull *W = const_container_of(dist, struct weibull,
-    base);
-
+  const struct weibull *W = dist_to_const_weibull(dist);
   return cdf_weibull(x, W->lambda, W->k);
 }
 
 static double
 weibull_sf(const struct dist *dist, double x)
 {
-  const struct weibull *W = const_container_of(dist, struct weibull,
-    base);
-
+  const struct weibull *W = dist_to_const_weibull(dist);
   return sf_weibull(x, W->lambda, W->k);
 }
 
 static double
 weibull_icdf(const struct dist *dist, double p)
 {
-  const struct weibull *W = const_container_of(dist, struct weibull,
-    base);
-
+  const struct weibull *W = dist_to_const_weibull(dist);
   return icdf_weibull(p, W->lambda, W->k);
 }
 
 static double
 weibull_isf(const struct dist *dist, double p)
 {
-  const struct weibull *W = const_container_of(dist, struct weibull,
-    base);
-
+  const struct weibull *W = dist_to_const_weibull(dist);
   return isf_weibull(p, W->lambda, W->k);
 }
 
@@ -1604,8 +1572,7 @@ const struct dist_ops weibull_ops = {
 static double
 genpareto_sample(const struct dist *dist)
 {
-  const struct genpareto *GP = const_container_of(dist, struct genpareto,
-    base);
+  const struct genpareto *GP = dist_to_const_genpareto(dist);
   uint32_t s = crypto_rand_u32();
   double p0 = random_uniform_01();
 
@@ -1615,36 +1582,28 @@ genpareto_sample(const struct dist *dist)
 static double
 genpareto_cdf(const struct dist *dist, double x)
 {
-  const struct genpareto *GP = const_container_of(dist, struct genpareto,
-    base);
-
+  const struct genpareto *GP = dist_to_const_genpareto(dist);
   return cdf_genpareto(x, GP->mu, GP->sigma, GP->xi);
 }
 
 static double
 genpareto_sf(const struct dist *dist, double x)
 {
-  const struct genpareto *GP = const_container_of(dist, struct genpareto,
-    base);
-
+  const struct genpareto *GP = dist_to_const_genpareto(dist);
   return sf_genpareto(x, GP->mu, GP->sigma, GP->xi);
 }
 
 static double
 genpareto_icdf(const struct dist *dist, double p)
 {
-  const struct genpareto *GP = const_container_of(dist, struct genpareto,
-    base);
-
+  const struct genpareto *GP = dist_to_const_genpareto(dist);
   return icdf_genpareto(p, GP->mu, GP->sigma, GP->xi);
 }
 
 static double
 genpareto_isf(const struct dist *dist, double p)
 {
-  const struct genpareto *GP = const_container_of(dist, struct genpareto,
-    base);
-
+  const struct genpareto *GP = dist_to_const_genpareto(dist);
   return isf_genpareto(p, GP->mu, GP->sigma, GP->xi);
 }
 
@@ -1662,7 +1621,7 @@ const struct dist_ops genpareto_ops = {
 static double
 geometric_sample(const struct dist *dist)
 {
-  const struct geometric *G = const_container_of(dist, struct geometric, base);
+  const struct geometric *G = dist_to_const_geometric(dist);
   uint32_t s = crypto_rand_u32();
   double p0 = random_uniform_01();
 
@@ -1672,7 +1631,7 @@ geometric_sample(const struct dist *dist)
 static double
 geometric_cdf(const struct dist *dist, double x)
 {
-  const struct geometric *G = const_container_of(dist, struct geometric, base);
+  const struct geometric *G = dist_to_const_geometric(dist);
 
   if (x < 1)
     return 0;
@@ -1683,7 +1642,7 @@ geometric_cdf(const struct dist *dist, double x)
 static double
 geometric_sf(const struct dist *dist, double x)
 {
-  const struct geometric *G = const_container_of(dist, struct geometric, base);
+  const struct geometric *G = dist_to_const_geometric(dist);
 
   if (x < 1)
     return 0;
@@ -1694,7 +1653,7 @@ geometric_sf(const struct dist *dist, double x)
 static double
 geometric_icdf(const struct dist *dist, double p)
 {
-  const struct geometric *G = const_container_of(dist, struct geometric, base);
+  const struct geometric *G = dist_to_const_geometric(dist);
 
   return log1p(-p)/log1p(-G->p);
 }
@@ -1702,7 +1661,7 @@ geometric_icdf(const struct dist *dist, double p)
 static double
 geometric_isf(const struct dist *dist, double p)
 {
-  const struct geometric *G = const_container_of(dist, struct geometric, base);
+  const struct geometric *G = dist_to_const_geometric(dist);
 
   return log(p)/log1p(-G->p);
 }





More information about the tor-commits mailing list