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