20 #ifndef BINOMIAL_BOUNDS_HPP_
21 #define BINOMIAL_BOUNDS_HPP_
40 static constexpr
double delta_of_num_std_devs[] = {
41 0.5000000000000000000,
42 0.1586553191586026479,
43 0.0227502618904135701,
47 static constexpr
double lb_equiv_table[] = {
49 0.78733703534118149, 3.14426768537558132, 13.56789685109913535,
50 0.94091379266077979, 2.64699271711145911, 6.29302733018320737,
51 0.96869128474958188, 2.46531676590527127, 4.97375283467403051,
52 0.97933572521046131, 2.37418810664669877, 4.44899975481712318,
53 0.98479165917274258, 2.31863116255024693, 4.16712379778553554,
54 0.98806033915698777, 2.28075536565225434, 3.99010556144099837,
55 0.99021896790580399, 2.25302005857281529, 3.86784477136922078,
56 0.99174267079089873, 2.23168103978522936, 3.77784896945266269,
57 0.99287147837287648, 2.21465899260871879, 3.70851932988722410,
58 0.99373900046805375, 2.20070155496262032, 3.65326029076638292,
59 0.99442519013851438, 2.18900651202670815, 3.60803817612955413,
60 0.99498066823221620, 2.17903457780744247, 3.57024330407946877,
61 0.99543899410224412, 2.17040883161922693, 3.53810982030634591,
62 0.99582322541263579, 2.16285726913676513, 3.51039837124298515,
63 0.99614973311747690, 2.15617827879603396, 3.48621230377099778,
64 0.99643042892560629, 2.15021897666090922, 3.46488605693562590,
65 0.99667418783778317, 2.14486114872480016, 3.44591466064832730,
66 0.99688774875812669, 2.14001181420209718, 3.42890765690452781,
67 0.99707632299691795, 2.13559675336844634, 3.41355809420343803,
68 0.99724399084971083, 2.13155592217421486, 3.39962113251016262,
69 0.99739400151915447, 2.12784018863251845, 3.38689892877548004,
70 0.99752896842633731, 2.12440890875851096, 3.37522975271599535,
71 0.99765101725122918, 2.12122815311133195, 3.36448003577621080,
72 0.99776189496810730, 2.11826934724291505, 3.35453840911279144,
73 0.99786304821586214, 2.11550823850916458, 3.34531123809287578,
74 0.99795568665180667, 2.11292409529477254, 3.33671916527694634,
75 0.99804083063483517, 2.11049908609763293, 3.32869446834217797,
76 0.99811933910984862, 2.10821776918189130, 3.32117898316676019,
77 0.99819195457286014, 2.10606671027090897, 3.31412243534683171,
78 0.99825930555178388, 2.10403415237001923, 3.30748113008135647,
79 0.99832193858154028, 2.10210975877822648, 3.30121691946897045,
80 0.99838032666573895, 2.10028440670842542, 3.29529629751144171,
81 0.99843488390555990, 2.09855000145353188, 3.28968974413223236,
82 0.99848596721417948, 2.09689934193824001, 3.28437111460505093,
83 0.99853390005924325, 2.09532599155502908, 3.27931717312372939,
84 0.99857895741078551, 2.09382418262592296, 3.27450718840060517,
85 0.99862138880970974, 2.09238872751677718, 3.26992261182860489,
86 0.99866141580770318, 2.09101494715108061, 3.26554677962434425,
87 0.99869923565267982, 2.08969860402822860, 3.26136468165239535,
88 0.99873502010169091, 2.08843585627218431, 3.25736275677081721,
89 0.99876893292508839, 2.08722321436752623, 3.25352872241415980,
90 0.99880111078502409, 2.08605749165553789, 3.24985141664350863,
91 0.99883168573342118, 2.08493577529222307, 3.24632068399498053,
92 0.99886077231613513, 2.08385540129560809, 3.24292724848112357,
93 0.99888847451828155, 2.08281392374021834, 3.23966263299664092,
94 0.99891488795844907, 2.08180908991394631, 3.23651906111521726,
95 0.99894010085196783, 2.08083882998420222, 3.23348939240611344,
96 0.99896419358239541, 2.07990122528650545, 3.23056705515594444,
97 0.99898723510594323, 2.07899450946285924, 3.22774598963252402,
98 0.99900929266780736, 2.07811704477046533, 3.22502059972006805,
99 0.99903043086155208, 2.07726730587160091, 3.22238570890294795,
100 0.99905070073845081, 2.07644388314946582, 3.21983651940365689,
101 0.99907015770423868, 2.07564546080757850, 3.21736857351049821,
102 0.99908884779227947, 2.07487081196367740, 3.21497773796417619,
103 0.99910681586905525, 2.07411879634256024, 3.21266015316183484,
104 0.99912410177549305, 2.07338834403498140, 3.21041222805715165,
105 0.99914074347179849, 2.07267845454973099, 3.20823061166797174,
106 0.99915677607464204, 2.07198819052374006, 3.20611216970604573,
107 0.99917223149395795, 2.07131667846186929, 3.20405396962596001,
108 0.99918714153457699, 2.07066309019154460, 3.20205326110445299,
109 0.99920153247185794, 2.07002665203046377, 3.20010746990493544,
110 0.99921543193525508, 2.06940663431663552, 3.19821417453343315,
111 0.99922886570365677, 2.06880235245998279, 3.19637109973109546,
112 0.99924185357357942, 2.06821315729285971, 3.19457610621114441,
113 0.99925441845175555, 2.06763843812092318, 3.19282717869864996,
114 0.99926658263325407, 2.06707761824370095, 3.19112241228646099,
115 0.99927836173816331, 2.06653015295219689, 3.18946001739936946,
116 0.99928977431994781, 2.06599552505539918, 3.18783829446098821,
117 0.99930083753795884, 2.06547324585920933, 3.18625564538041317,
118 0.99931156864562354, 2.06496285191821016, 3.18471055124089730,
119 0.99932197985521043, 2.06446390392778767, 3.18320157510865442,
120 0.99933208559809827, 2.06397598606787369, 3.18172735837393361,
121 0.99934190032416836, 2.06349869971447220, 3.18028661102792398,
122 0.99935143390791836, 2.06303166975550312, 3.17887810481605015,
123 0.99936070171270330, 2.06257453607466346, 3.17750067581857820,
124 0.99936971103502970, 2.06212696042919674, 3.17615321728274580,
125 0.99937847392385493, 2.06168861430600714, 3.17483467831510779,
126 0.99938700168914352, 2.06125918927764928, 3.17354405480557489,
127 0.99939530099953799, 2.06083838987589729, 3.17228039269048168,
128 0.99940338278830154, 2.06042593411496000, 3.17104278166036124,
129 0.99941125463777780, 2.06002155276328835, 3.16983035274597569,
130 0.99941892470027938, 2.05962498741951094, 3.16864227952240185,
131 0.99942640059737187, 2.05923599161263837, 3.16747776846497686,
132 0.99943368842187397, 2.05885433061945378, 3.16633606416374391,
133 0.99944079790603269, 2.05847977868873500, 3.16521644518826406,
134 0.99944773295734990, 2.05811212058944193, 3.16411821883858124,
135 0.99945450059186669, 2.05775114781260982, 3.16304072400711789,
136 0.99946110646314423, 2.05739666442039493, 3.16198332650733960,
137 0.99946755770463369, 2.05704847678819647, 3.16094541781455973,
138 0.99947385746861528, 2.05670640500335367, 3.15992641851471490,
139 0.99948001256305474, 2.05637027420314666, 3.15892576988736096,
140 0.99948602689656241, 2.05603991286400856, 3.15794293484717059,
141 0.99949190674294641, 2.05571516158917689, 3.15697740043813724,
142 0.99949765436329585, 2.05539586490317561, 3.15602867309343083,
143 0.99950327557880314, 2.05508187237845164, 3.15509627710042651,
144 0.99950877461972709, 2.05477304104951486, 3.15417975753007340,
145 0.99951415481862682, 2.05446923022574879, 3.15327867462917766,
146 0.99951942042375208, 2.05417030908833453, 3.15239260700215596,
147 0.99952457390890004, 2.05387614661762541, 3.15152114915238712,
148 0.99952962005008317, 2.05358662050909402, 3.15066390921020911,
149 0.99953456216121594, 2.05330161104427589, 3.14982051097524618,
150 0.99953940176368405, 2.05302100378725072, 3.14899059183684926,
151 0.99954414373920031, 2.05274468493067275, 3.14817379948561893,
152 0.99954879047621148, 2.05247255013657082, 3.14736979964868624,
153 0.99955334485656522, 2.05220449388099269, 3.14657826610371671,
154 0.99955780993869325, 2.05194041831310869, 3.14579888316276879,
155 0.99956218652590678, 2.05168022402710903, 3.14503134811607765,
156 0.99956647932785359, 2.05142381889103831, 3.14427536967733090,
157 0.99957069025060719, 2.05117111251445294, 3.14353066260227365,
158 0.99957482032178291, 2.05092201793428330, 3.14279695558593630,
159 0.99957887261450651, 2.05067645094720774, 3.14207398336887422,
160 0.99958284988383639, 2.05043432833224415, 3.14136149076028914,
161 0.99958675435604505, 2.05019557189746138, 3.14065923143530767,
162 0.99959058650074439, 2.04996010556124020, 3.13996696426707445,
163 0.99959434898201494, 2.04972785368377686, 3.13928445867830419,
164 0.99959804437042976, 2.04949874512311681, 3.13861149103462367,
165 0.99960167394553423, 2.04927271043337100, 3.13794784369528656,
166 0.99960523957651048, 2.04904968140490951, 3.13729330661277572,
167 0.99960874253329735, 2.04882959397491504, 3.13664767767019725,
168 0.99961218434327748, 2.04861238220240693, 3.13601075688413289
171 static constexpr
double ub_equiv_table[] = {
173 0.99067760836669549, 1.75460517119302040, 2.48055626001627161,
174 0.99270518097577565, 1.78855957509907171, 2.53863835259832626,
175 0.99402032633599902, 1.81047286499563143, 2.57811676180597260,
176 0.99492607629539975, 1.82625928017762362, 2.60759550546498531,
177 0.99558653966013821, 1.83839160339161367, 2.63086812358551470,
178 0.99608981951632813, 1.84812399034444752, 2.64993712523727254,
179 0.99648648035983456, 1.85617372053235385, 2.66598485907860550,
180 0.99680750790483330, 1.86298655802610824, 2.67976541374471822,
181 0.99707292880049181, 1.86885682585270274, 2.69178781407745760,
182 0.99729614928489241, 1.87398826101983218, 2.70241106542158604,
183 0.99748667952445658, 1.87852708449801753, 2.71189717290596377,
184 0.99765127712748836, 1.88258159501103250, 2.72044290303773550,
185 0.99779498340305395, 1.88623391878036273, 2.72819957382063194,
186 0.99792160418357412, 1.88954778748873764, 2.73528576807902368,
187 0.99803398604944960, 1.89257337682371940, 2.74179612106766513,
188 0.99813449883217231, 1.89535099316557876, 2.74780718300419835,
189 0.99822494122659577, 1.89791339232732525, 2.75338173141955167,
190 0.99830679915913834, 1.90028752122407241, 2.75857186416826039,
191 0.99838117410831728, 1.90249575897183831, 2.76342117562634826,
192 0.99844913407071090, 1.90455689090418900, 2.76796659454200267,
193 0.99851147736424650, 1.90648682834171268, 2.77223944710058845,
194 0.99856879856019987, 1.90829917277082473, 2.77626682032629901,
195 0.99862183849734265, 1.91000561415842185, 2.78007199816156003,
196 0.99867096266018507, 1.91161621560812023, 2.78367524259661536,
197 0.99871656986212543, 1.91313978579765376, 2.78709435016625662,
198 0.99875907577771272, 1.91458400425526065, 2.79034488416175463,
199 0.99879885565047744, 1.91595563175945927, 2.79344064132371273,
200 0.99883610756373287, 1.91726064301425936, 2.79639384757751941,
201 0.99887095169674467, 1.91850441099725799, 2.79921543574803877,
202 0.99890379414739527, 1.91969155477030995, 2.80191513182441554,
203 0.99893466279047516, 1.92082633358913313, 2.80450167352080371,
204 0.99896392088177777, 1.92191254955568525, 2.80698295731653502,
205 0.99899147889385631, 1.92295362479495680, 2.80936614404217266,
206 0.99901764688726757, 1.92395267400968351, 2.81165765979318394,
207 0.99904238606342233, 1.92491244978191389, 2.81386337393604435,
208 0.99906590152386343, 1.92583552644848055, 2.81598868034527072,
209 0.99908829040739988, 1.92672418013918900, 2.81803841726804194,
210 0.99910959420023460, 1.92758051694144683, 2.82001709302821268,
211 0.99912996403594434, 1.92840654943159961, 2.82192875763732332,
212 0.99914930224576892, 1.92920397044028391, 2.82377730628954282,
213 0.99916781270195543, 1.92997447498220254, 2.82556612075063640,
214 0.99918553179077207, 1.93071949211818605, 2.82729843191989971,
215 0.99920250730914972, 1.93144048613876862, 2.82897728689417249,
216 0.99921873345181211, 1.93213870990595638, 2.83060537017752267,
217 0.99923435180002684, 1.93281536508689555, 2.83218527795750674,
218 0.99924930425362390, 1.93347145882316340, 2.83371938965598247,
219 0.99926370394567243, 1.93410820221384938, 2.83520990872793277,
220 0.99927750755296074, 1.93472643138986200, 2.83665891945119597,
221 0.99929082941537217, 1.93532697329771963, 2.83806833931606661,
222 0.99930366295501472, 1.93591074716263734, 2.83943997143404658,
223 0.99931598804721489, 1.93647857274021362, 2.84077557836653227,
224 0.99932789059798210, 1.93703110239354714, 2.84207662106302905,
225 0.99933946180485123, 1.93756904936378760, 2.84334468086129277,
226 0.99935053819703512, 1.93809302131219852, 2.84458116874117195,
227 0.99936126637970801, 1.93860365411038060, 2.84578731838604426,
228 0.99937166229284458, 1.93910149816429112, 2.84696443486512862,
229 0.99938169190727422, 1.93958709548454067, 2.84811369085281285,
230 0.99939136927613959, 1.94006085573701625, 2.84923617230361970,
231 0.99940074328745254, 1.94052339623206649, 2.85033291216254270,
232 0.99940993070470086, 1.94097508636855309, 2.85140492437699322,
233 0.99941868577388959, 1.94141633372043998, 2.85245314430358121,
234 0.99942734443487780, 1.94184757038001976, 2.85347839582286156,
235 0.99943556385736088, 1.94226915100517772, 2.85448160365493209,
236 0.99944374522542034, 1.94268143723749631, 2.85546346373061510,
237 0.99945159955424856, 1.94308482059116727, 2.85642486111805738,
238 0.99945915301904620, 1.94347956957849988, 2.85736639994965458,
239 0.99946660663832176, 1.94386600964031686, 2.85828887832701639,
240 0.99947383703224091, 1.94424436597356021, 2.85919278275500233,
241 0.99948075442870277, 1.94461502153473020, 2.86007887186090670,
242 0.99948766082269458, 1.94497821937304138, 2.86094774077355396,
243 0.99949422748713346, 1.94533411296001191, 2.86179981848076181,
244 0.99950070756119658, 1.94568300035135167, 2.86263579405672886,
245 0.99950704321753392, 1.94602523449961495, 2.86345610449197352,
246 0.99951320334216121, 1.94636083782822311, 2.86426125541271404,
247 0.99951920293474927, 1.94669011080745236, 2.86505169255406145,
248 0.99952501670378524, 1.94701327348536779, 2.86582788270862920,
249 0.99953071209267819, 1.94733044372333097, 2.86659027602854621,
250 0.99953632734991515, 1.94764180764266825, 2.86733927778843167,
251 0.99954171164873173, 1.94794766430732125, 2.86807526143834934,
252 0.99954699274462655, 1.94824807472994621, 2.86879864789403882,
253 0.99955216611081710, 1.94854317889829076, 2.86950970901679625,
254 0.99955730019613043, 1.94883320227168610, 2.87020887436986527,
255 0.99956213770650493, 1.94911826561721568, 2.87089648477021342,
256 0.99956704264963037, 1.94939848545763539, 2.87157281693902178,
257 0.99957166306481327, 1.94967401618316671, 2.87223821840905202,
258 0.99957632713136491, 1.94994497791333288, 2.87289293193450135,
259 0.99958087233392234, 1.95021155752212394, 2.87353731228213860,
260 0.99958532555996271, 1.95047376805584349, 2.87417154907075201,
261 0.99958956246481989, 1.95073180380688882, 2.87479599765507032,
262 0.99959389351869277, 1.95098572880579013, 2.87541081987382086,
263 0.99959807862052230, 1.95123574036898617, 2.87601637401948551,
264 0.99960214057801977, 1.95148186921983324, 2.87661283691068093,
265 0.99960607527256684, 1.95172415829728152, 2.87720042968334155,
266 0.99960996433179616, 1.95196280898670693, 2.87777936649376898,
267 0.99961379137860717, 1.95219787713926962, 2.87834989933620022,
268 0.99961756088146103, 1.95242944583677058, 2.87891216133900230,
269 0.99962125605327401, 1.95265762420910960, 2.87946647367488140,
270 0.99962486179100551, 1.95288245314810638, 2.88001290210658567,
271 0.99962843240297161, 1.95310404286672679, 2.88055166523392359,
272 0.99963187276145504, 1.95332251980147475, 2.88108300006589957,
273 0.99963525453173929, 1.95353785898848287, 2.88160703591438505,
274 0.99963855412988778, 1.95375019354571577, 2.88212393551896184,
275 0.99964190254169694, 1.95395953472205974, 2.88263389761985422,
276 0.99964506565942202, 1.95416607430155409, 2.88313700661564098,
277 0.99964834424233118, 1.95436972855640079, 2.88363350163803034,
278 0.99965136548857458, 1.95457068540693513, 2.88412349413960101,
279 0.99965436594726498, 1.95476896383092935, 2.88460710620208260,
280 0.99965736463468602, 1.95496457504532373, 2.88508450078833789,
281 0.99966034130443404, 1.95515761150707590, 2.88555580586194083,
282 0.99966326130828520, 1.95534810382198998, 2.88602118761679094,
283 0.99966601446035952, 1.95553622237747504, 2.88648066384146773,
284 0.99966887679593697, 1.95572186728168163, 2.88693444915907094,
285 0.99967161286551232, 1.95590523410490391, 2.88738271495714116,
286 0.99967435412270333, 1.95608626483223702, 2.88782540459769166,
287 0.99967701261934394, 1.95626497627117146, 2.88826277189363623,
288 0.99967963265157778, 1.95644153684824573, 2.88869486674335008,
289 0.99968216317182623, 1.95661589936000269, 2.88912184353694101,
290 0.99968479674396349, 1.95678821614791332, 2.88954376359643561,
291 0.99968729031337489, 1.95695842061650183, 2.88996069422501023,
292 0.99968963358631413, 1.95712651709766305, 2.89037285320668502
295 class binomial_bounds {
298 static double get_lower_bound(
unsigned long long num_samples,
double theta,
unsigned num_std_devs) {
300 check_num_std_devs(num_std_devs);
301 const double estimate = num_samples / theta;
302 const double lb = compute_approx_binomial_lower_bound(num_samples, theta, num_std_devs);
303 return std::min(estimate, std::max(
static_cast<double>(num_samples), lb));
306 static double get_upper_bound(
unsigned long long num_samples,
double theta,
unsigned num_std_devs) {
308 check_num_std_devs(num_std_devs);
309 const double estimate = num_samples / theta;
310 const double ub = compute_approx_binomial_upper_bound(num_samples, theta, num_std_devs);
311 return std::max(estimate, ub);
316 static double cont_classic_lb(
unsigned long long num_samples,
double theta,
double num_std_devs) {
317 const double n_hat = (num_samples - 0.5) / theta;
318 const double b = num_std_devs * std::sqrt((1.0 - theta) / theta);
319 const double d = 0.5 * b * std::sqrt((b * b) + (4.0 * n_hat));
320 const double center = n_hat + (0.5 * (b * b));
325 static double cont_classic_ub(
unsigned long long num_samples,
double theta,
double num_std_devs) {
326 const double n_hat = (num_samples + 0.5) / theta;
327 const double b = num_std_devs * std::sqrt((1.0 - theta) / theta);
328 const double d = 0.5 * b * std::sqrt((b * b) + (4.0 * n_hat));
329 const double center = n_hat + (0.5 * (b * b));
342 static unsigned long long special_n_star(
unsigned long long num_samples,
double p,
double delta) {
343 const double q = 1.0 - p;
345 if ((num_samples / p) >= 500.0)
throw std::invalid_argument(
"out of range");
346 double cur_term = std::pow(p, num_samples);
347 if (cur_term <= 1e-100)
throw std::logic_error(
"out of range");
348 double tot = cur_term;
349 unsigned long long m = num_samples;
350 while (tot <= delta) {
351 cur_term = (cur_term * q * (m)) / ((m + 1) - num_samples);
361 static unsigned long long special_n_prime_b(
unsigned long long num_samples,
double p,
double delta) {
362 const double q = 1.0 - p;
363 const double one_minus_delta = 1.0 - delta;
364 double cur_term = std::pow(p, num_samples);
365 if (cur_term <= 1e-100)
throw std::logic_error(
"out of range");
366 double tot = cur_term;
367 unsigned long long m = num_samples;
368 while (tot < one_minus_delta) {
369 cur_term = (cur_term * q * (m)) / ((m + 1) - num_samples);
376 static unsigned long long special_n_prime_f(
unsigned long long num_samples,
double p,
double delta) {
378 if ((num_samples / p) >= 500.0)
throw std::invalid_argument(
"out of range");
379 return special_n_prime_b(num_samples + 1, p, delta);
384 static double compute_approx_binomial_lower_bound(
unsigned long long num_samples,
double theta,
unsigned num_std_devs) {
385 if (theta == 1)
return static_cast<double>(num_samples);
386 if (num_samples == 0)
return 0;
387 if (num_samples == 1) {
388 const double delta = delta_of_num_std_devs[num_std_devs];
389 const double raw_lb = std::log(1 - delta) / std::log(1 - theta);
390 return std::floor(raw_lb);
392 if (num_samples > 120) {
394 const double raw_lb = cont_classic_lb(num_samples, theta, num_std_devs);
395 return (raw_lb - 0.5);
398 if (theta > (1 - 1e-5)) {
399 return static_cast<double>(num_samples);
401 if (theta < (num_samples / 360.0)) {
403 const unsigned index = 3 *
static_cast<unsigned>(num_samples) + (num_std_devs - 1);
404 const double raw_lb = cont_classic_lb(num_samples, theta, lb_equiv_table[index]);
409 const double delta = delta_of_num_std_devs[num_std_devs];
410 return static_cast<double>(special_n_star(num_samples, theta, delta));
415 static double compute_approx_binomial_upper_bound(
unsigned long long num_samples,
double theta,
unsigned num_std_devs) {
416 if (theta == 1)
return static_cast<double>(num_samples);
417 if (num_samples == 0) {
418 const double delta = delta_of_num_std_devs[num_std_devs];
419 const double raw_ub = std::log(delta) / std::log(1 - theta);
420 return std::ceil(raw_ub);
422 if (num_samples > 120) {
424 const double raw_ub = cont_classic_ub(num_samples, theta, num_std_devs);
425 return (raw_ub + 0.5);
428 if (theta > (1 - 1e-5)) {
429 return static_cast<double>(num_samples + 1);
431 if (theta < (num_samples / 360.0)) {
433 const unsigned index = 3 *
static_cast<unsigned>(num_samples) + (num_std_devs - 1);
434 const double raw_ub = cont_classic_ub(num_samples, theta, ub_equiv_table[index]);
439 const double delta = delta_of_num_std_devs[num_std_devs];
440 return static_cast<double>(special_n_prime_f(num_samples, theta, delta));
443 static void check_theta(
double theta) {
444 if (theta < 0 || theta > 1) {
445 throw std::invalid_argument(
"theta must be in [0, 1]");
449 static void check_num_std_devs(
unsigned num_std_devs) {
450 if (num_std_devs < 1 || num_std_devs > 3) {
451 throw std::invalid_argument(
"num_std_devs must be 1, 2 or 3");
DataSketches namespace.
Definition: binomial_bounds.hpp:38