1 #include "test/jemalloc_test.h" 2 3 #define MAX_REL_ERR 1.0e-9 4 #define MAX_ABS_ERR 1.0e-9 5 6 #include <float.h> 7 8 #ifndef INFINITY 9 #define INFINITY (DBL_MAX + DBL_MAX) 10 #endif 11 12 static bool 13 double_eq_rel(double a, double b, double max_rel_err, double max_abs_err) 14 { 15 double rel_err; 16 17 if (fabs(a - b) < max_abs_err) 18 return (true); 19 rel_err = (fabs(b) > fabs(a)) ? fabs((a-b)/b) : fabs((a-b)/a); 20 return (rel_err < max_rel_err); 21 } 22 23 static uint64_t 24 factorial(unsigned x) 25 { 26 uint64_t ret = 1; 27 unsigned i; 28 29 for (i = 2; i <= x; i++) 30 ret *= (uint64_t)i; 31 32 return (ret); 33 } 34 35 TEST_BEGIN(test_ln_gamma_factorial) 36 { 37 unsigned x; 38 39 /* exp(ln_gamma(x)) == (x-1)! for integer x. */ 40 for (x = 1; x <= 21; x++) { 41 assert_true(double_eq_rel(exp(ln_gamma(x)), 42 (double)factorial(x-1), MAX_REL_ERR, MAX_ABS_ERR), 43 "Incorrect factorial result for x=%u", x); 44 } 45 } 46 TEST_END 47 48 /* Expected ln_gamma([0.0..100.0] increment=0.25). */ 49 static const double ln_gamma_misc_expected[] = { 50 INFINITY, 51 1.28802252469807743, 0.57236494292470008, 0.20328095143129538, 52 0.00000000000000000, -0.09827183642181320, -0.12078223763524518, 53 -0.08440112102048555, 0.00000000000000000, 0.12487171489239651, 54 0.28468287047291918, 0.47521466691493719, 0.69314718055994529, 55 0.93580193110872523, 1.20097360234707429, 1.48681557859341718, 56 1.79175946922805496, 2.11445692745037128, 2.45373657084244234, 57 2.80857141857573644, 3.17805383034794575, 3.56137591038669710, 58 3.95781396761871651, 4.36671603662228680, 4.78749174278204581, 59 5.21960398699022932, 5.66256205985714178, 6.11591589143154568, 60 6.57925121201010121, 7.05218545073853953, 7.53436423675873268, 61 8.02545839631598312, 8.52516136106541467, 9.03318691960512332, 62 9.54926725730099690, 10.07315123968123949, 10.60460290274525086, 63 11.14340011995171231, 11.68933342079726856, 12.24220494005076176, 64 12.80182748008146909, 13.36802367147604720, 13.94062521940376342, 65 14.51947222506051816, 15.10441257307551943, 15.69530137706046524, 66 16.29200047656724237, 16.89437797963419285, 17.50230784587389010, 67 18.11566950571089407, 18.73434751193644843, 19.35823122022435427, 68 19.98721449566188468, 20.62119544270163018, 21.26007615624470048, 69 21.90376249182879320, 22.55216385312342098, 23.20519299513386002, 70 23.86276584168908954, 24.52480131594137802, 25.19122118273868338, 71 25.86194990184851861, 26.53691449111561340, 27.21604439872720604, 72 27.89927138384089389, 28.58652940490193828, 29.27775451504081516, 73 29.97288476399884871, 30.67186010608067548, 31.37462231367769050, 74 32.08111489594735843, 32.79128302226991565, 33.50507345013689076, 75 34.22243445715505317, 34.94331577687681545, 35.66766853819134298, 76 36.39544520803305261, 37.12659953718355865, 37.86108650896109395, 77 38.59886229060776230, 39.33988418719949465, 40.08411059791735198, 78 40.83150097453079752, 41.58201578195490100, 42.33561646075348506, 79 43.09226539146988699, 43.85192586067515208, 44.61456202863158893, 80 45.38013889847690052, 46.14862228684032885, 46.91997879580877395, 81 47.69417578616628361, 48.47118135183522014, 49.25096429545256882, 82 50.03349410501914463, 50.81874093156324790, 51.60667556776436982, 83 52.39726942748592364, 53.19049452616926743, 53.98632346204390586, 84 54.78472939811231157, 55.58568604486942633, 56.38916764371992940, 85 57.19514895105859864, 58.00360522298051080, 58.81451220059079787, 86 59.62784609588432261, 60.44358357816834371, 61.26170176100199427, 87 62.08217818962842927, 62.90499082887649962, 63.73011805151035958, 88 64.55753862700632340, 65.38723171073768015, 66.21917683354901385, 89 67.05335389170279825, 67.88974313718154008, 68.72832516833013017, 90 69.56908092082363737, 70.41199165894616385, 71.25703896716800045, 91 72.10420474200799390, 72.95347118416940191, 73.80482079093779646, 92 74.65823634883015814, 75.51370092648485866, 76.37119786778275454, 93 77.23071078519033961, 78.09222355331530707, 78.95572030266725960, 94 79.82118541361435859, 80.68860351052903468, 81.55795945611502873, 95 82.42923834590904164, 83.30242550295004378, 84.17750647261028973, 96 85.05446701758152983, 85.93329311301090456, 86.81397094178107920, 97 87.69648688992882057, 88.58082754219766741, 89.46697967771913795, 98 90.35493026581838194, 91.24466646193963015, 92.13617560368709292, 99 93.02944520697742803, 93.92446296229978486, 94.82121673107967297, 100 95.71969454214321615, 96.61988458827809723, 97.52177522288820910, 101 98.42535495673848800, 99.33061245478741341, 100.23753653310367895, 102 101.14611615586458981, 102.05634043243354370, 102.96819861451382394, 103 103.88168009337621811, 104.79677439715833032, 105.71347118823287303, 104 106.63176026064346047, 107.55163153760463501, 108.47307506906540198, 105 109.39608102933323153, 110.32063971475740516, 111.24674154146920557, 106 112.17437704317786995, 113.10353686902013237, 114.03421178146170689, 107 114.96639265424990128, 115.90007047041454769, 116.83523632031698014, 108 117.77188139974506953, 118.70999700805310795, 119.64957454634490830, 109 120.59060551569974962, 121.53308151543865279, 122.47699424143097247, 110 123.42233548443955726, 124.36909712850338394, 125.31727114935689826, 111 126.26684961288492559, 127.21782467361175861, 128.17018857322420899, 112 129.12393363912724453, 130.07905228303084755, 131.03553699956862033, 113 131.99338036494577864, 132.95257503561629164, 133.91311374698926784, 114 134.87498931216194364, 135.83819462068046846, 136.80272263732638294, 115 137.76856640092901785, 138.73571902320256299, 139.70417368760718091, 116 140.67392364823425055, 141.64496222871400732, 142.61728282114600574, 117 143.59087888505104047, 144.56574394634486680, 145.54187159633210058, 118 146.51925549072063859, 147.49788934865566148, 148.47776695177302031, 119 149.45888214327129617, 150.44122882700193600, 151.42480096657754984, 120 152.40959258449737490, 153.39559776128982094, 154.38281063467164245, 121 155.37122539872302696, 156.36083630307879844, 157.35163765213474107, 122 158.34362380426921391, 159.33678917107920370, 160.33112821663092973, 123 161.32663545672428995, 162.32330545817117695, 163.32113283808695314, 124 164.32011226319519892, 165.32023844914485267, 166.32150615984036790, 125 167.32391020678358018, 168.32744544842768164, 169.33210678954270634, 126 170.33788918059275375, 171.34478761712384198, 172.35279713916281707, 127 173.36191283062726143, 174.37212981874515094, 175.38344327348534080, 128 176.39584840699734514, 177.40934047306160437, 178.42391476654847793, 129 179.43956662288721304, 180.45629141754378111, 181.47408456550741107, 130 182.49294152078630304, 183.51285777591152737, 184.53382886144947861, 131 185.55585034552262869, 186.57891783333786861, 187.60302696672312095, 132 188.62817342367162610, 189.65435291789341932, 190.68156119837468054, 133 191.70979404894376330, 192.73904728784492590, 193.76931676731820176, 134 194.80059837318714244, 195.83288802445184729, 196.86618167288995096, 135 197.90047530266301123, 198.93576492992946214, 199.97204660246373464, 136 201.00931639928148797, 202.04757043027063901, 203.08680483582807597, 137 204.12701578650228385, 205.16819948264117102, 206.21035215404597807, 138 207.25347005962987623, 208.29754948708190909, 209.34258675253678916, 139 210.38857820024875878, 211.43552020227099320, 212.48340915813977858, 140 213.53224149456323744, 214.58201366511514152, 215.63272214993284592, 141 216.68436345542014010, 217.73693411395422004, 218.79043068359703739, 142 219.84484974781133815, 220.90018791517996988, 221.95644181913033322, 143 223.01360811766215875, 224.07168349307951871, 225.13066465172661879, 144 226.19054832372759734, 227.25133126272962159, 228.31301024565024704, 145 229.37558207242807384, 230.43904356577689896, 231.50339157094342113, 146 232.56862295546847008, 233.63473460895144740, 234.70172344281823484, 147 235.76958639009222907, 236.83832040516844586, 237.90792246359117712, 148 238.97838956183431947, 240.04971871708477238, 241.12190696702904802, 149 242.19495136964280846, 243.26884900298270509, 244.34359696498191283, 150 245.41919237324782443, 246.49563236486270057, 247.57291409618682110, 151 248.65103474266476269, 249.72999149863338175, 250.80978157713354904, 152 251.89040220972316320, 252.97185064629374551, 254.05412415488834199, 153 255.13722002152300661, 256.22113555000953511, 257.30586806178126835, 154 258.39141489572085675, 259.47777340799029844, 260.56494097186322279, 155 261.65291497755913497, 262.74169283208021852, 263.83127195904967266, 156 264.92164979855277807, 266.01282380697938379, 267.10479145686849733, 157 268.19755023675537586, 269.29109765101975427, 270.38543121973674488, 158 271.48054847852881721, 272.57644697842033565, 273.67312428569374561, 159 274.77057798174683967, 275.86880566295326389, 276.96780494052313770, 160 278.06757344036617496, 279.16810880295668085, 280.26940868320008349, 161 281.37147075030043197, 282.47429268763045229, 283.57787219260217171, 162 284.68220697654078322, 285.78729476455760050, 286.89313329542699194, 163 287.99972032146268930, 289.10705360839756395, 290.21513093526289140, 164 291.32395009427028754, 292.43350889069523646, 293.54380514276073200, 165 294.65483668152336350, 295.76660135076059532, 296.87909700685889902, 166 297.99232151870342022, 299.10627276756946458, 300.22094864701409733, 167 301.33634706277030091, 302.45246593264130297, 303.56930318639643929, 168 304.68685676566872189, 305.80512462385280514, 306.92410472600477078, 169 308.04379504874236773, 309.16419358014690033, 310.28529831966631036, 170 311.40710727801865687, 312.52961847709792664, 313.65282994987899201, 171 314.77673974032603610, 315.90134590329950015, 317.02664650446632777, 172 318.15263962020929966, 319.27932333753892635, 320.40669575400545455, 173 321.53475497761127144, 322.66349912672620803, 323.79292633000159185, 174 324.92303472628691452, 326.05382246454587403, 327.18528770377525916, 175 328.31742861292224234, 329.45024337080525356, 330.58373016603343331, 176 331.71788719692847280, 332.85271267144611329, 333.98820480709991898, 177 335.12436183088397001, 336.26118197919845443, 337.39866349777429377, 178 338.53680464159958774, 339.67560367484657036, 340.81505887079896411, 179 341.95516851178109619, 343.09593088908627578, 344.23734430290727460, 180 345.37940706226686416, 346.52211748494903532, 347.66547389743118401, 181 348.80947463481720661, 349.95411804077025408, 351.09940246744753267, 182 352.24532627543504759, 353.39188783368263103, 354.53908551944078908, 183 355.68691771819692349, 356.83538282361303118, 357.98447923746385868, 184 359.13420536957539753 185 }; 186 187 TEST_BEGIN(test_ln_gamma_misc) 188 { 189 unsigned i; 190 191 for (i = 1; i < sizeof(ln_gamma_misc_expected)/sizeof(double); i++) { 192 double x = (double)i * 0.25; 193 assert_true(double_eq_rel(ln_gamma(x), 194 ln_gamma_misc_expected[i], MAX_REL_ERR, MAX_ABS_ERR), 195 "Incorrect ln_gamma result for i=%u", i); 196 } 197 } 198 TEST_END 199 200 /* Expected pt_norm([0.01..0.99] increment=0.01). */ 201 static const double pt_norm_expected[] = { 202 -INFINITY, 203 -2.32634787404084076, -2.05374891063182252, -1.88079360815125085, 204 -1.75068607125216946, -1.64485362695147264, -1.55477359459685305, 205 -1.47579102817917063, -1.40507156030963221, -1.34075503369021654, 206 -1.28155156554460081, -1.22652812003661049, -1.17498679206608991, 207 -1.12639112903880045, -1.08031934081495606, -1.03643338949378938, 208 -0.99445788320975281, -0.95416525314619416, -0.91536508784281390, 209 -0.87789629505122846, -0.84162123357291418, -0.80642124701824025, 210 -0.77219321418868492, -0.73884684918521371, -0.70630256284008752, 211 -0.67448975019608171, -0.64334540539291685, -0.61281299101662701, 212 -0.58284150727121620, -0.55338471955567281, -0.52440051270804067, 213 -0.49585034734745320, -0.46769879911450812, -0.43991316567323380, 214 -0.41246312944140462, -0.38532046640756751, -0.35845879325119373, 215 -0.33185334643681652, -0.30548078809939738, -0.27931903444745404, 216 -0.25334710313579978, -0.22754497664114931, -0.20189347914185077, 217 -0.17637416478086135, -0.15096921549677725, -0.12566134685507399, 218 -0.10043372051146975, -0.07526986209982976, -0.05015358346473352, 219 -0.02506890825871106, 0.00000000000000000, 0.02506890825871106, 220 0.05015358346473366, 0.07526986209982990, 0.10043372051146990, 221 0.12566134685507413, 0.15096921549677739, 0.17637416478086146, 222 0.20189347914185105, 0.22754497664114931, 0.25334710313579978, 223 0.27931903444745404, 0.30548078809939738, 0.33185334643681652, 224 0.35845879325119373, 0.38532046640756762, 0.41246312944140484, 225 0.43991316567323391, 0.46769879911450835, 0.49585034734745348, 226 0.52440051270804111, 0.55338471955567303, 0.58284150727121620, 227 0.61281299101662701, 0.64334540539291685, 0.67448975019608171, 228 0.70630256284008752, 0.73884684918521371, 0.77219321418868492, 229 0.80642124701824036, 0.84162123357291441, 0.87789629505122879, 230 0.91536508784281423, 0.95416525314619460, 0.99445788320975348, 231 1.03643338949378938, 1.08031934081495606, 1.12639112903880045, 232 1.17498679206608991, 1.22652812003661049, 1.28155156554460081, 233 1.34075503369021654, 1.40507156030963265, 1.47579102817917085, 234 1.55477359459685394, 1.64485362695147308, 1.75068607125217102, 235 1.88079360815125041, 2.05374891063182208, 2.32634787404084076 236 }; 237 238 TEST_BEGIN(test_pt_norm) 239 { 240 unsigned i; 241 242 for (i = 1; i < sizeof(pt_norm_expected)/sizeof(double); i++) { 243 double p = (double)i * 0.01; 244 assert_true(double_eq_rel(pt_norm(p), pt_norm_expected[i], 245 MAX_REL_ERR, MAX_ABS_ERR), 246 "Incorrect pt_norm result for i=%u", i); 247 } 248 } 249 TEST_END 250 251 /* 252 * Expected pt_chi2(p=[0.01..0.99] increment=0.07, 253 * df={0.1, 1.1, 10.1, 100.1, 1000.1}). 254 */ 255 static const double pt_chi2_df[] = {0.1, 1.1, 10.1, 100.1, 1000.1}; 256 static const double pt_chi2_expected[] = { 257 1.168926411457320e-40, 1.347680397072034e-22, 3.886980416666260e-17, 258 8.245951724356564e-14, 2.068936347497604e-11, 1.562561743309233e-09, 259 5.459543043426564e-08, 1.114775688149252e-06, 1.532101202364371e-05, 260 1.553884683726585e-04, 1.239396954915939e-03, 8.153872320255721e-03, 261 4.631183739647523e-02, 2.473187311701327e-01, 2.175254800183617e+00, 262 263 0.0003729887888876379, 0.0164409238228929513, 0.0521523015190650113, 264 0.1064701372271216612, 0.1800913735793082115, 0.2748704281195626931, 265 0.3939246282787986497, 0.5420727552260817816, 0.7267265822221973259, 266 0.9596554296000253670, 1.2607440376386165326, 1.6671185084541604304, 267 2.2604828984738705167, 3.2868613342148607082, 6.9298574921692139839, 268 269 2.606673548632508, 4.602913725294877, 5.646152813924212, 270 6.488971315540869, 7.249823275816285, 7.977314231410841, 271 8.700354939944047, 9.441728024225892, 10.224338321374127, 272 11.076435368801061, 12.039320937038386, 13.183878752697167, 273 14.657791935084575, 16.885728216339373, 23.361991680031817, 274 275 70.14844087392152, 80.92379498849355, 85.53325420085891, 276 88.94433120715347, 91.83732712857017, 94.46719943606301, 277 96.96896479994635, 99.43412843510363, 101.94074719829733, 278 104.57228644307247, 107.43900093448734, 110.71844673417287, 279 114.76616819871325, 120.57422505959563, 135.92318818757556, 280 281 899.0072447849649, 937.9271278858220, 953.8117189560207, 282 965.3079371501154, 974.8974061207954, 983.4936235182347, 283 991.5691170518946, 999.4334123954690, 1007.3391826856553, 284 1015.5445154999951, 1024.3777075619569, 1034.3538789836223, 285 1046.4872561869577, 1063.5717461999654, 1107.0741966053859 286 }; 287 288 TEST_BEGIN(test_pt_chi2) 289 { 290 unsigned i, j; 291 unsigned e = 0; 292 293 for (i = 0; i < sizeof(pt_chi2_df)/sizeof(double); i++) { 294 double df = pt_chi2_df[i]; 295 double ln_gamma_df = ln_gamma(df * 0.5); 296 for (j = 1; j < 100; j += 7) { 297 double p = (double)j * 0.01; 298 assert_true(double_eq_rel(pt_chi2(p, df, ln_gamma_df), 299 pt_chi2_expected[e], MAX_REL_ERR, MAX_ABS_ERR), 300 "Incorrect pt_chi2 result for i=%u, j=%u", i, j); 301 e++; 302 } 303 } 304 } 305 TEST_END 306 307 /* 308 * Expected pt_gamma(p=[0.1..0.99] increment=0.07, 309 * shape=[0.5..3.0] increment=0.5). 310 */ 311 static const double pt_gamma_shape[] = {0.5, 1.0, 1.5, 2.0, 2.5, 3.0}; 312 static const double pt_gamma_expected[] = { 313 7.854392895485103e-05, 5.043466107888016e-03, 1.788288957794883e-02, 314 3.900956150232906e-02, 6.913847560638034e-02, 1.093710833465766e-01, 315 1.613412523825817e-01, 2.274682115597864e-01, 3.114117323127083e-01, 316 4.189466220207417e-01, 5.598106789059246e-01, 7.521856146202706e-01, 317 1.036125427911119e+00, 1.532450860038180e+00, 3.317448300510606e+00, 318 319 0.01005033585350144, 0.08338160893905107, 0.16251892949777497, 320 0.24846135929849966, 0.34249030894677596, 0.44628710262841947, 321 0.56211891815354142, 0.69314718055994529, 0.84397007029452920, 322 1.02165124753198167, 1.23787435600161766, 1.51412773262977574, 323 1.89711998488588196, 2.52572864430825783, 4.60517018598809091, 324 325 0.05741590094955853, 0.24747378084860744, 0.39888572212236084, 326 0.54394139997444901, 0.69048812513915159, 0.84311389861296104, 327 1.00580622221479898, 1.18298694218766931, 1.38038096305861213, 328 1.60627736383027453, 1.87396970522337947, 2.20749220408081070, 329 2.65852391865854942, 3.37934630984842244, 5.67243336507218476, 330 331 0.1485547402532659, 0.4657458011640391, 0.6832386130709406, 332 0.8794297834672100, 1.0700752852474524, 1.2629614217350744, 333 1.4638400448580779, 1.6783469900166610, 1.9132338090606940, 334 2.1778589228618777, 2.4868823970010991, 2.8664695666264195, 335 3.3724415436062114, 4.1682658512758071, 6.6383520679938108, 336 337 0.2771490383641385, 0.7195001279643727, 0.9969081732265243, 338 1.2383497880608061, 1.4675206597269927, 1.6953064251816552, 339 1.9291243435606809, 2.1757300955477641, 2.4428032131216391, 340 2.7406534569230616, 3.0851445039665513, 3.5043101122033367, 341 4.0575997065264637, 4.9182956424675286, 7.5431362346944937, 342 343 0.4360451650782932, 0.9983600902486267, 1.3306365880734528, 344 1.6129750834753802, 1.8767241606994294, 2.1357032436097660, 345 2.3988853336865565, 2.6740603137235603, 2.9697561737517959, 346 3.2971457713883265, 3.6731795898504660, 4.1275751617770631, 347 4.7230515633946677, 5.6417477865306020, 8.4059469148854635 348 }; 349 350 TEST_BEGIN(test_pt_gamma_shape) 351 { 352 unsigned i, j; 353 unsigned e = 0; 354 355 for (i = 0; i < sizeof(pt_gamma_shape)/sizeof(double); i++) { 356 double shape = pt_gamma_shape[i]; 357 double ln_gamma_shape = ln_gamma(shape); 358 for (j = 1; j < 100; j += 7) { 359 double p = (double)j * 0.01; 360 assert_true(double_eq_rel(pt_gamma(p, shape, 1.0, 361 ln_gamma_shape), pt_gamma_expected[e], MAX_REL_ERR, 362 MAX_ABS_ERR), 363 "Incorrect pt_gamma result for i=%u, j=%u", i, j); 364 e++; 365 } 366 } 367 } 368 TEST_END 369 370 TEST_BEGIN(test_pt_gamma_scale) 371 { 372 double shape = 1.0; 373 double ln_gamma_shape = ln_gamma(shape); 374 375 assert_true(double_eq_rel( 376 pt_gamma(0.5, shape, 1.0, ln_gamma_shape) * 10.0, 377 pt_gamma(0.5, shape, 10.0, ln_gamma_shape), MAX_REL_ERR, 378 MAX_ABS_ERR), 379 "Scale should be trivially equivalent to external multiplication"); 380 } 381 TEST_END 382 383 int 384 main(void) 385 { 386 387 return (test( 388 test_ln_gamma_factorial, 389 test_ln_gamma_misc, 390 test_pt_norm, 391 test_pt_chi2, 392 test_pt_gamma_shape, 393 test_pt_gamma_scale)); 394 } 395