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