|
@@ -2103,20 +2103,6 @@ scale_array_elements_to_u64(uint64_t *entries_out, const double *entries_in,
|
|
|
#undef SCALE_TO_U64_MAX
|
|
|
}
|
|
|
|
|
|
-/** Time-invariant 64-bit greater-than; works on two integers in the range
|
|
|
- * (0,INT64_MAX). */
|
|
|
-#if SIZEOF_VOID_P == 8
|
|
|
-#define gt_i64_timei(a,b) ((a) > (b))
|
|
|
-#else
|
|
|
-static inline int
|
|
|
-gt_i64_timei(uint64_t a, uint64_t b)
|
|
|
-{
|
|
|
- int64_t diff = (int64_t) (b - a);
|
|
|
- int res = diff >> 63;
|
|
|
- return res & 1;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
/** Pick a random element of <b>n_entries</b>-element array <b>entries</b>,
|
|
|
* choosing each element with a probability proportional to its (uint64_t)
|
|
|
* value, and return the index of that element. If all elements are 0, choose
|
|
@@ -2125,8 +2111,7 @@ gt_i64_timei(uint64_t a, uint64_t b)
|
|
|
STATIC int
|
|
|
choose_array_element_by_weight(const uint64_t *entries, int n_entries)
|
|
|
{
|
|
|
- int i, i_chosen=-1, n_chosen=0;
|
|
|
- uint64_t total_so_far = 0;
|
|
|
+ int i;
|
|
|
uint64_t rand_val;
|
|
|
uint64_t total = 0;
|
|
|
|
|
@@ -2143,22 +2128,8 @@ choose_array_element_by_weight(const uint64_t *entries, int n_entries)
|
|
|
|
|
|
rand_val = crypto_rand_uint64(total);
|
|
|
|
|
|
- for (i = 0; i < n_entries; ++i) {
|
|
|
- total_so_far += entries[i];
|
|
|
- if (gt_i64_timei(total_so_far, rand_val)) {
|
|
|
- i_chosen = i;
|
|
|
- n_chosen++;
|
|
|
- /* Set rand_val to INT64_MAX rather than stopping the loop. This way,
|
|
|
- * the time we spend in the loop does not leak which element we chose. */
|
|
|
- rand_val = INT64_MAX;
|
|
|
- }
|
|
|
- }
|
|
|
- tor_assert(total_so_far == total);
|
|
|
- tor_assert(n_chosen == 1);
|
|
|
- tor_assert(i_chosen >= 0);
|
|
|
- tor_assert(i_chosen < n_entries);
|
|
|
-
|
|
|
- return i_chosen;
|
|
|
+ return select_array_member_cumulative_timei(
|
|
|
+ entries, n_entries, total, rand_val);
|
|
|
}
|
|
|
|
|
|
/** When weighting bridges, enforce these values as lower and upper
|