GNUnet 0.21.1
ibf_sim.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
29#include "platform.h"
30#include <stdlib.h>
31#include <stdio.h>
32#include <string.h>
33
34#define MAX_IBF_DECODE 16
35
36/* report average over how many rounds? */
37#define ROUNDS 100000
38
39/* enable one of the three below */
40// simple fix
41#define FIX1 0
42// possibly slightly better fix for large IBF_DECODE values
43#define FIX2 1
44
45// SIGCOMM algorithm
46#define STRATA 0
47
48// print each value?
49#define VERBOSE 0
50// avoid assembly? (ASM is about 50% faster)
51#define SLOW 0
52
53int
54main (int argc, char **argv)
55{
56 unsigned int round;
57 unsigned int buckets[31]; // max is 2^31 as 'random' returns only between 0 and 2^31
58 unsigned int i;
59 int j;
60 unsigned int r;
61 unsigned int ret;
62 unsigned long long total;
63 unsigned int want;
64 double predict;
65
66 srandom (time (NULL));
67 total = 0;
68 want = atoi (argv[1]);
69 for (round = 0; round < ROUNDS; round++)
70 {
71 memset (buckets, 0, sizeof(buckets));
72 for (i = 0; i < want; i++)
73 {
74 /* FIXME: might want to use 'better' PRNG to avoid
75 PRNG-induced biases */
76 r = random ();
77 if (0 == r)
78 continue;
79#if SLOW
80 for (j = 0; (j < 31) && (0 == (r & (1 << j))); j++)
81 ;
82#else
83 /* use assembly / gcc */
84 j = __builtin_ffs (r) - 1;
85#endif
86 buckets[j]++;
87 }
88 ret = 0;
89 predict = 0.0;
90 for (j = 31; j >= 0; j--)
91 {
92#if FIX1
93 /* improved algorithm, for 1000 elements with IBF-DECODE 8, I
94 get 990/1000 elements on average over 1 million runs; key
95 idea being to stop short of the 'last' possible IBF as
96 otherwise a "lowball" per-chance would unduely influence the
97 result */if ((j > 0) &&
98 (buckets[j - 1] > MAX_IBF_DECODE))
99 {
100 ret *= (1 << (j + 1));
101 break;
102 }
103#endif
104#if FIX2
105 /* another improvement: don't just always cut off the last one,
106 but rather try to predict based on all previous values where
107 that "last" one is; additional prediction can only really
108 work if MAX_IBF_DECODE is sufficiently high */
109 if ((j > 0) &&
110 ((buckets[j - 1] > MAX_IBF_DECODE) ||
111 (predict > MAX_IBF_DECODE)))
112 {
113 ret *= (1 << (j + 1));
114 break;
115 }
116#endif
117#if STRATA
118 /* original algorithm, for 1000 elements with IBF-DECODE 8,
119 I get 920/1000 elements on average over 1 million runs */
120 if (buckets[j] > MAX_IBF_DECODE)
121 {
122 ret *= (1 << (j + 1));
123 break;
124 }
125#endif
126 ret += buckets[j];
127 predict = (buckets[j] + 2.0 * predict) / 2.0;
128 }
129#if VERBOSE
130 fprintf (stderr, "%u ", ret);
131#endif
132 total += ret;
133 }
134 fprintf (stderr, "\n");
135 fprintf (stdout, "average %llu\n", total / ROUNDS);
136 return 0;
137}
138
139
140/* TODO: should calculate stddev of the results to also be able to
141 say something about the stability of the results, outside of
142 large-scale averages -- gaining 8% precision at the expense of
143 50% additional variance might not be worth it... */
int main(int argc, char **argv)
Definition: ibf_sim.c:54
static int ret
Final status code.
Definition: gnunet-arm.c:94
#define MAX_IBF_DECODE
Definition: ibf_sim.c:34
#define ROUNDS
Definition: ibf_sim.c:37