1 |
2 |
guangxi.li |
/*
|
2 |
|
|
* Piecewise polynomial approximation of
|
3 |
|
|
* inverse of the normal cumulative distribution function (CDF)
|
4 |
|
|
*/
|
5 |
|
|
|
6 |
|
|
/*
|
7 |
|
|
* Copyright (C) 2014, Guangxi Liu <guangxi.liu@opencores.org>
|
8 |
|
|
*
|
9 |
|
|
* This source file may be used and distributed without restriction provided
|
10 |
|
|
* that this copyright statement is not removed from the file and that any
|
11 |
|
|
* derivative work contains the original copyright notice and the associated
|
12 |
|
|
* disclaimer.
|
13 |
|
|
*
|
14 |
|
|
* This source file is free software; you can redistribute it and/or modify it
|
15 |
|
|
* under the terms of the GNU Lesser General Public License as published by
|
16 |
|
|
* the Free Software Foundation; either version 2.1 of the License,
|
17 |
|
|
* or (at your option) any later version.
|
18 |
|
|
*
|
19 |
|
|
* This source is distributed in the hope that it will be useful, but
|
20 |
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
21 |
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
22 |
|
|
* License for more details.
|
23 |
|
|
*
|
24 |
|
|
* You should have received a copy of the GNU Lesser General Public License
|
25 |
|
|
* along with this source; if not, download it from
|
26 |
|
|
* http://www.opencores.org/lgpl.shtml
|
27 |
|
|
*/
|
28 |
|
|
|
29 |
|
|
|
30 |
|
|
#include "icdf.h"
|
31 |
|
|
|
32 |
|
|
|
33 |
|
|
/* Coefficients table */
|
34 |
|
|
static const long C0[248] = {
|
35 |
|
|
11049, 8007, 5220, 2577, 18846, 16547, 14535, 12721, 25134, 23229,
|
36 |
|
|
21594, 20150, 30518, 28863, 27458, 26231, 35288, 33808, 32562, 31479,
|
37 |
|
|
39608, 38260, 37130, 36152, 43582, 42336, 41296, 40399, 47277, 46115,
|
38 |
|
|
45147, 44314, 50745, 49651, 48742, 47963, 54020, 52985, 52126, 51390,
|
39 |
|
|
57132, 56147, 55331, 54632, 60101, 59160, 58381, 57715, 62945, 62043,
|
40 |
|
|
61296, 60659, 65679, 64811, 64093, 63481, 68314, 67476, 66784, 66194,
|
41 |
|
|
70859, 70049, 69381, 68811, 73323, 72538, 71891, 71340, 75714, 74952,
|
42 |
|
|
74324, 73790, 78036, 77296, 76686, 76167, 80297, 79576, 78982, 78477,
|
43 |
|
|
82500, 81797, 81218, 80726, 84649, 83963, 83398, 82918, 86748, 86078,
|
44 |
|
|
85526, 85057, 88800, 88145, 87606, 87147, 90809, 90167, 89640, 89191,
|
45 |
|
|
92777, 92148, 91631, 91192, 94706, 94090, 93583, 93152, 96599, 95994,
|
46 |
|
|
95496, 95074, 98457, 97863, 97374, 96960, 100282, 99698, 99219, 98811,
|
47 |
|
|
102076, 101502, 101031, 100630, 103841, 103276, 102812, 102419, 105577, 105021,
|
48 |
|
|
104565, 104178, 107286, 106739, 106290, 105909, 108970, 108431, 107989, 107613,
|
49 |
|
|
110629, 110098, 109662, 109292, 112265, 111741, 111311, 110946, 113878, 113361,
|
50 |
|
|
112937, 112578, 115469, 114959, 114541, 114186, 117040, 116536, 116124, 115774,
|
51 |
|
|
118590, 118093, 117686, 117340, 120121, 119630, 119228, 118887, 121633, 121149,
|
52 |
|
|
120751, 120414, 123128, 122649, 122256, 121923, 124605, 124132, 123743, 123414,
|
53 |
|
|
126065, 125597, 125213, 124888, 127510, 127047, 126667, 126345, 128938, 128480,
|
54 |
|
|
128105, 127786, 130351, 129898, 129527, 129212, 131750, 131301, 130934, 130622,
|
55 |
|
|
133134, 132690, 132326, 132018, 134505, 134065, 133705, 133400, 135862, 135426,
|
56 |
|
|
135070, 134767, 137206, 136775, 136421, 136122, 138537, 138110, 137760, 137463,
|
57 |
|
|
139856, 139433, 139086, 138792, 141163, 140743, 140400, 140109, 142458, 142042,
|
58 |
|
|
141702, 141413, 143742, 143330, 142992, 142706, 145015, 144606, 144272, 143988,
|
59 |
|
|
146277, 145872, 145540, 145259, 150000, 148769, 147528, 146797
|
60 |
|
|
};
|
61 |
|
|
|
62 |
|
|
static const long C1[248] = {
|
63 |
|
|
-102514, -92199, -86162, -82951, -79070, -68105, -60693, -55396, -66134, -55839,
|
64 |
|
|
-48783, -43639, -57755, -48215, -41670, -36890, -51803, -42932, -36856, -32421,
|
65 |
|
|
-47313, -39012, -33338, -29203, -43778, -35964, -30631, -26751, -40907, -33511,
|
66 |
|
|
-28470, -24807, -38519, -31483, -26695, -23220, -36492, -29774, -25206, -21893,
|
67 |
|
|
-34747, -28307, -23933, -20765, -33223, -27032, -22831, -19789, -31878, -25911,
|
68 |
|
|
-21864, -18936, -30681, -24915, -21007, -18182, -29606, -24023, -20242, -17509,
|
69 |
|
|
-28634, -23218, -19552, -16903, -27750, -22488, -18927, -16356, -26942, -21821,
|
70 |
|
|
-18357, -15857, -26198, -21208, -17835, -15400, -25512, -20644, -17354, -14980,
|
71 |
|
|
-24876, -20121, -16909, -14591, -24285, -19636, -16496, -14231, -23733, -19184,
|
72 |
|
|
-16111, -13896, -23217, -18760, -15752, -13583, -22732, -18364, -15415, -13290,
|
73 |
|
|
-22276, -17991, -15099, -13015, -21846, -17639, -14801, -12756, -21440, -17307,
|
74 |
|
|
-14520, -12512, -21055, -16993, -14253, -12281, -20690, -16695, -14001, -12062,
|
75 |
|
|
-20342, -16412, -13762, -11854, -20012, -16143, -13534, -11656, -19697, -15886,
|
76 |
|
|
-13317, -11468, -19396, -15641, -13111, -11289, -19109, -15407, -12913, -11118,
|
77 |
|
|
-18834, -15183, -12724, -10954, -18570, -14969, -12543, -10797, -18317, -14763,
|
78 |
|
|
-12369, -10646, -18073, -14565, -12202, -10502, -17839, -14375, -12042, -10363,
|
79 |
|
|
-17614, -14193, -11888, -10230, -17397, -14016, -11739, -10102, -17188, -13847,
|
80 |
|
|
-11596, -9978, -16986, -13683, -11458, -9858, -16791, -13525, -11325, -9743,
|
81 |
|
|
-16603, -13372, -11196, -9632, -16421, -13224, -11072, -9524, -16244, -13081,
|
82 |
|
|
-10951, -9420, -16073, -12942, -10835, -9319, -15907, -12808, -10722, -9222,
|
83 |
|
|
-15747, -12678, -10612, -9127, -15591, -12552, -10506, -9035, -15440, -12429,
|
84 |
|
|
-10403, -8946, -15294, -12311, -10303, -8860, -15154, -12196, -10206, -8776,
|
85 |
|
|
-15020, -12086, -10113, -8695, -14894, -11982, -10024, -8618, -14779, -11885,
|
86 |
|
|
-9940, -8544, -14681, -11797, -9863, -8475, -13792, -11190, -9418, -8133,
|
87 |
|
|
0, 0, 0, 0, 0, 0, 0, 0
|
88 |
|
|
};
|
89 |
|
|
|
90 |
|
|
static const long C2[248] = {
|
91 |
|
|
83840, 48883, 25920, 8147, 88988, 59916, 42707, 31577, 83526, 57019,
|
92 |
|
|
41464, 31523, 77411, 52885, 38533, 29386, 71990, 49106, 35743, 27241,
|
93 |
|
|
67363, 45865, 33332, 25372, 63422, 43107, 31282, 23780, 60040, 40746,
|
94 |
|
|
29530, 22422, 57109, 38706, 28020, 21254, 54545, 36926, 26705, 20239,
|
95 |
|
|
52279, 35358, 25549, 19349, 50262, 33965, 24525, 18561, 48452, 32718,
|
96 |
|
|
23609, 17858, 46818, 31593, 22785, 17226, 45333, 30573, 22038, 16654,
|
97 |
|
|
43976, 29643, 21358, 16134, 42731, 28790, 20735, 15658, 41583, 28005,
|
98 |
|
|
20163, 15221, 40521, 27279, 19634, 14817, 39534, 26606, 19143, 14444,
|
99 |
|
|
38614, 25978, 18687, 14096, 37754, 25392, 18261, 13772, 36948, 24844,
|
100 |
|
|
17862, 13468, 36190, 24328, 17488, 13184, 35477, 23843, 17136, 12916,
|
101 |
|
|
34803, 23385, 16804, 12664, 34165, 22952, 16490, 12426, 33561, 22542,
|
102 |
|
|
16193, 12200, 32987, 22153, 15911, 11986, 32441, 21783, 15643, 11783,
|
103 |
|
|
31921, 21431, 15388, 11590, 31425, 21094, 15145, 11406, 30951, 20773,
|
104 |
|
|
14913, 11230, 30497, 20466, 14691, 11061, 30063, 20173, 14479, 10901,
|
105 |
|
|
29646, 19891, 14275, 10746, 29246, 19620, 14080, 10599, 28861, 19360,
|
106 |
|
|
13892, 10456, 28492, 19110, 13711, 10320, 28135, 18870, 13538, 10189,
|
107 |
|
|
27792, 18638, 13370, 10062, 27461, 18414, 13209, 9940, 27141, 18199,
|
108 |
|
|
13053, 9822, 26832, 17990, 12903, 9709, 26534, 17788, 12758, 9599,
|
109 |
|
|
26245, 17593, 12617, 9492, 25965, 17405, 12481, 9390, 25694, 17222,
|
110 |
|
|
12349, 9290, 25432, 17045, 12222, 9194, 25178, 16874, 12098, 9100,
|
111 |
|
|
24933, 16708, 11979, 9010, 24697, 16549, 11864, 8923, 24474, 16397,
|
112 |
|
|
11754, 8840, 24268, 16255, 11650, 8761, 24088, 16129, 11557, 8689,
|
113 |
|
|
23954, 16029, 11480, 8628, 23908, 15977, 11432, 8586, 24029, 16017,
|
114 |
|
|
11440, 8581, 24481, 16238, 11559, 8648, 0, 0, 0, 0,
|
115 |
|
|
0, 0, 0, 0, 0, 0, 0, 0
|
116 |
|
|
};
|
117 |
|
|
|
118 |
|
|
|
119 |
|
|
/* Calculate Inverse of the normal CDF */
|
120 |
|
|
long icdf(unsigned long long n)
|
121 |
|
|
{
|
122 |
|
|
unsigned long long t;
|
123 |
|
|
int i;
|
124 |
|
|
unsigned num_lzd;
|
125 |
|
|
unsigned addr;
|
126 |
|
|
long c0, c1, c2;
|
127 |
|
|
long x;
|
128 |
|
|
long long y;
|
129 |
|
|
int carry;
|
130 |
|
|
|
131 |
|
|
t = n;
|
132 |
|
|
num_lzd = 0;
|
133 |
|
|
for (i = 0; i < 61; i++) {
|
134 |
|
|
if (t & 0x8000000000000000ULL)
|
135 |
|
|
break;
|
136 |
|
|
else {
|
137 |
|
|
++num_lzd;
|
138 |
|
|
t <<= 1;
|
139 |
|
|
}
|
140 |
|
|
}
|
141 |
|
|
addr = num_lzd << 2;
|
142 |
|
|
if (n & 2ULL)
|
143 |
|
|
addr += 2;
|
144 |
|
|
if (n & 4ULL)
|
145 |
|
|
++addr;
|
146 |
|
|
|
147 |
|
|
c0 = C0[addr];
|
148 |
|
|
c1 = C1[addr];
|
149 |
|
|
c2 = C2[addr];
|
150 |
|
|
|
151 |
|
|
if (num_lzd <= 60)
|
152 |
|
|
n &= ~(1ULL << (63 - num_lzd));
|
153 |
|
|
|
154 |
|
|
t = n >> 3;
|
155 |
|
|
x = 0;
|
156 |
|
|
for (i = 0; i < 15; i++) {
|
157 |
|
|
x <<= 1;
|
158 |
|
|
if (t & 1ULL)
|
159 |
|
|
++x;
|
160 |
|
|
t >>= 1;
|
161 |
|
|
}
|
162 |
|
|
|
163 |
|
|
y = (long long)c2 * (long long)x;
|
164 |
|
|
y += ((long long)c1 << 19);
|
165 |
|
|
y >>= 20;
|
166 |
|
|
y *= (long long)x;
|
167 |
|
|
y >>= 19;
|
168 |
|
|
y += (long long)c0;
|
169 |
|
|
carry = (y & 4ULL) ? 1 : 0;
|
170 |
|
|
y >>= 3;
|
171 |
|
|
y += carry;
|
172 |
|
|
if (n & 1ULL)
|
173 |
|
|
y = -y;
|
174 |
|
|
|
175 |
|
|
return (long)y;
|
176 |
|
|
}
|