1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: math_Arithmetic.cpp
4
5 Copyright (C)2009-2012 Nintendo Co., Ltd. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Rev: 46347 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nn/math.h>
17
18 #include <nn/math/math_Arithmetic.h>
19 #include <cstdlib>
20
21 namespace nn { namespace math {
22
23 namespace
24 {
25 //---- Table of exponential functions
26 struct ExpTbl
27 {
28 f32 exp_val;
29 f32 exp_delta;
30 };
31 struct ExpTbl sExpTbl[32+1] =
32 {
33 { 0.500000000f, 0.022136891f }, // Exp(-0.693147181) = Exp(ln2 * (-16)/16)
34 { 0.522136891f, 0.023116975f }, // Exp(-0.649825482) = Exp(ln2 * (-15)/16)
35 { 0.545253866f, 0.024140451f }, // Exp(-0.606503783)
36 { 0.569394317f, 0.025209240f }, // Exp(-0.563182084)
37 { 0.594603558f, 0.026325349f }, // Exp(-0.519860385)
38 { 0.620928906f, 0.027490871f }, // Exp(-0.476538687)
39 { 0.648419777f, 0.028707996f }, // Exp(-0.433216988)
40 { 0.677127773f, 0.029979008f }, // Exp(-0.389895289)
41 { 0.707106781f, 0.031306292f }, // Exp(-0.346573590)
42 { 0.738413073f, 0.032692340f }, // Exp(-0.303251891)
43 { 0.771105413f, 0.034139753f }, // Exp(-0.259930193)
44 { 0.805245166f, 0.035651249f }, // Exp(-0.216608494)
45 { 0.840896415f, 0.037229665f }, // Exp(-0.173286795)
46 { 0.878126080f, 0.038877963f }, // Exp(-0.129965096)
47 { 0.917004043f, 0.040599237f }, // Exp(-0.086643398)
48 { 0.957603281f, 0.042396719f }, // Exp(-0.043321699) = Exp(ln2 * (-1)/16)
49 { 1.000000000f, 0.044273782f }, // Exp(0.000000000) = Exp(ln2 * (0)/16)
50 { 1.044273782f, 0.046233950f }, // Exp(0.043321699) = Exp(ln2 * (1)/16)
51 { 1.090507733f, 0.048280902f }, // Exp(0.086643398)
52 { 1.138788635f, 0.050418480f }, // Exp(0.129965096)
53 { 1.189207115f, 0.052650697f }, // Exp(0.173286795)
54 { 1.241857812f, 0.054981743f }, // Exp(0.216608494)
55 { 1.296839555f, 0.057415992f }, // Exp(0.259930193)
56 { 1.354255547f, 0.059958015f }, // Exp(0.303251891)
57 { 1.414213562f, 0.062612584f }, // Exp(0.346573590)
58 { 1.476826146f, 0.065384679f }, // Exp(0.389895289)
59 { 1.542210825f, 0.068279507f }, // Exp(0.433216988)
60 { 1.610490332f, 0.071302499f }, // Exp(0.476538687)
61 { 1.681792831f, 0.074459330f }, // Exp(0.519860385)
62 { 1.756252160f, 0.077755926f }, // Exp(0.563182084)
63 { 1.834008086f, 0.081198475f }, // Exp(0.606503783)
64 { 1.915206561f, 0.084793439f }, // Exp(0.649825482) = Exp(ln2 * 15/16)
65 { 2.000000000f, 0.088547565f }, // Exp(0.693147181) = Exp(ln2 * 16/16)
66 };
67
68
69
70 //---- Logarithmic function table
71 struct LogTbl
72 {
73 f32 log_val;
74 f32 log_delta;
75 };
76 struct LogTbl sLogTbl[256+1] =
77 {
78 { 0.000000000f, 0.003898640f }, // Log(1.00000000)
79 { 0.003898640f, 0.003883500f }, // Log(1.00390625)
80 { 0.007782140f, 0.003868477f }, // Log(1.00781250)
81 { 0.011650617f, 0.003853569f }, // Log(1.01171875)
82 { 0.015504187f, 0.003838776f }, // Log(1.01562500)
83 { 0.019342963f, 0.003824096f }, // Log(1.01953125)
84 { 0.023167059f, 0.003809528f }, // Log(1.02343750)
85 { 0.026976588f, 0.003795071f }, // Log(1.02734375)
86 { 0.030771659f, 0.003780723f }, // Log(1.03125000)
87 { 0.034552382f, 0.003766483f }, // Log(1.03515625)
88 { 0.038318864f, 0.003752350f }, // Log(1.03906250)
89 { 0.042071214f, 0.003738322f }, // Log(1.04296875)
90 { 0.045809536f, 0.003724399f }, // Log(1.04687500)
91 { 0.049533935f, 0.003710579f }, // Log(1.05078125)
92 { 0.053244515f, 0.003696862f }, // Log(1.05468750)
93 { 0.056941376f, 0.003683245f }, // Log(1.05859375)
94 { 0.060624622f, 0.003669729f }, // Log(1.06250000)
95 { 0.064294351f, 0.003656311f }, // Log(1.06640625)
96 { 0.067950662f, 0.003642991f }, // Log(1.07031250)
97 { 0.071593653f, 0.003629768f }, // Log(1.07421875)
98 { 0.075223421f, 0.003616640f }, // Log(1.07812500)
99 { 0.078840062f, 0.003603608f }, // Log(1.08203125)
100 { 0.082443669f, 0.003590668f }, // Log(1.08593750)
101 { 0.086034337f, 0.003577821f }, // Log(1.08984375)
102 { 0.089612159f, 0.003565066f }, // Log(1.09375000)
103 { 0.093177225f, 0.003552402f }, // Log(1.09765625)
104 { 0.096729626f, 0.003539827f }, // Log(1.10156250)
105 { 0.100269453f, 0.003527341f }, // Log(1.10546875)
106 { 0.103796794f, 0.003514942f }, // Log(1.10937500)
107 { 0.107311736f, 0.003502631f }, // Log(1.11328125)
108 { 0.110814366f, 0.003490405f }, // Log(1.11718750)
109 { 0.114304771f, 0.003478264f }, // Log(1.12109375)
110 { 0.117783036f, 0.003466208f }, // Log(1.12500000)
111 { 0.121249244f, 0.003454235f }, // Log(1.12890625)
112 { 0.124703479f, 0.003442344f }, // Log(1.13281250)
113 { 0.128145823f, 0.003430535f }, // Log(1.13671875)
114 { 0.131576358f, 0.003418807f }, // Log(1.14062500)
115 { 0.134995165f, 0.003407158f }, // Log(1.14453125)
116 { 0.138402323f, 0.003395589f }, // Log(1.14843750)
117 { 0.141797912f, 0.003384098f }, // Log(1.15234375)
118 { 0.145182010f, 0.003372684f }, // Log(1.15625000)
119 { 0.148554694f, 0.003361348f }, // Log(1.16015625)
120 { 0.151916042f, 0.003350087f }, // Log(1.16406250)
121 { 0.155266129f, 0.003338901f }, // Log(1.16796875)
122 { 0.158605030f, 0.003327790f }, // Log(1.17187500)
123 { 0.161932820f, 0.003316753f }, // Log(1.17578125)
124 { 0.165249573f, 0.003305788f }, // Log(1.17968750)
125 { 0.168555361f, 0.003294896f }, // Log(1.18359375)
126 { 0.171850257f, 0.003284075f }, // Log(1.18750000)
127 { 0.175134332f, 0.003273325f }, // Log(1.19140625)
128 { 0.178407657f, 0.003262646f }, // Log(1.19531250)
129 { 0.181670303f, 0.003252035f }, // Log(1.19921875)
130 { 0.184922338f, 0.003241494f }, // Log(1.20312500)
131 { 0.188163832f, 0.003231021f }, // Log(1.20703125)
132 { 0.191394853f, 0.003220615f }, // Log(1.21093750)
133 { 0.194615468f, 0.003210276f }, // Log(1.21484375)
134 { 0.197825743f, 0.003200003f }, // Log(1.21875000)
135 { 0.201025746f, 0.003189795f }, // Log(1.22265625)
136 { 0.204215541f, 0.003179653f }, // Log(1.22656250)
137 { 0.207395194f, 0.003169575f }, // Log(1.23046875)
138 { 0.210564769f, 0.003159560f }, // Log(1.23437500)
139 { 0.213724329f, 0.003149609f }, // Log(1.23828125)
140 { 0.216873938f, 0.003139720f }, // Log(1.24218750)
141 { 0.220013658f, 0.003129893f }, // Log(1.24609375)
142 { 0.223143551f, 0.003120127f }, // Log(1.25000000)
143 { 0.226263679f, 0.003110422f }, // Log(1.25390625)
144 { 0.229374101f, 0.003100778f }, // Log(1.25781250)
145 { 0.232474879f, 0.003091193f }, // Log(1.26171875)
146 { 0.235566071f, 0.003081667f }, // Log(1.26562500)
147 { 0.238647738f, 0.003072199f }, // Log(1.26953125)
148 { 0.241719937f, 0.003062790f }, // Log(1.27343750)
149 { 0.244782726f, 0.003053437f }, // Log(1.27734375)
150 { 0.247836164f, 0.003044142f }, // Log(1.28125000)
151 { 0.250880306f, 0.003034904f }, // Log(1.28515625)
152 { 0.253915210f, 0.003025721f }, // Log(1.28906250)
153 { 0.256940931f, 0.003016594f }, // Log(1.29296875)
154 { 0.259957524f, 0.003007521f }, // Log(1.29687500)
155 { 0.262965046f, 0.002998503f }, // Log(1.30078125)
156 { 0.265963548f, 0.002989539f }, // Log(1.30468750)
157 { 0.268953087f, 0.002980628f }, // Log(1.30859375)
158 { 0.271933715f, 0.002971770f }, // Log(1.31250000)
159 { 0.274905486f, 0.002962965f }, // Log(1.31640625)
160 { 0.277868451f, 0.002954212f }, // Log(1.32031250)
161 { 0.280822663f, 0.002945510f }, // Log(1.32421875)
162 { 0.283768173f, 0.002936860f }, // Log(1.32812500)
163 { 0.286705033f, 0.002928260f }, // Log(1.33203125)
164 { 0.289633293f, 0.002919710f }, // Log(1.33593750)
165 { 0.292553003f, 0.002911210f }, // Log(1.33984375)
166 { 0.295464213f, 0.002902760f }, // Log(1.34375000)
167 { 0.298366973f, 0.002894358f }, // Log(1.34765625)
168 { 0.301261331f, 0.002886005f }, // Log(1.35156250)
169 { 0.304147335f, 0.002877700f }, // Log(1.35546875)
170 { 0.307025035f, 0.002869442f }, // Log(1.35937500)
171 { 0.309894478f, 0.002861232f }, // Log(1.36328125)
172 { 0.312755710f, 0.002853069f }, // Log(1.36718750)
173 { 0.315608779f, 0.002844952f }, // Log(1.37109375)
174 { 0.318453731f, 0.002836881f }, // Log(1.37500000)
175 { 0.321290612f, 0.002828856f }, // Log(1.37890625)
176 { 0.324119469f, 0.002820876f }, // Log(1.38281250)
177 { 0.326940345f, 0.002812941f }, // Log(1.38671875)
178 { 0.329753286f, 0.002805051f }, // Log(1.39062500)
179 { 0.332558337f, 0.002797205f }, // Log(1.39453125)
180 { 0.335355542f, 0.002789402f }, // Log(1.39843750)
181 { 0.338144944f, 0.002781643f }, // Log(1.40234375)
182 { 0.340926587f, 0.002773927f }, // Log(1.40625000)
183 { 0.343700514f, 0.002766253f }, // Log(1.41015625)
184 { 0.346466767f, 0.002758622f }, // Log(1.41406250)
185 { 0.349225390f, 0.002751033f }, // Log(1.41796875)
186 { 0.351976423f, 0.002743486f }, // Log(1.42187500)
187 { 0.354719909f, 0.002735980f }, // Log(1.42578125)
188 { 0.357455889f, 0.002728515f }, // Log(1.42968750)
189 { 0.360184404f, 0.002721090f }, // Log(1.43359375)
190 { 0.362905494f, 0.002713706f }, // Log(1.43750000)
191 { 0.365619200f, 0.002706362f }, // Log(1.44140625)
192 { 0.368325561f, 0.002699057f }, // Log(1.44531250)
193 { 0.371024618f, 0.002691792f }, // Log(1.44921875)
194 { 0.373716410f, 0.002684565f }, // Log(1.45312500)
195 { 0.376400975f, 0.002677378f }, // Log(1.45703125)
196 { 0.379078353f, 0.002670229f }, // Log(1.46093750)
197 { 0.381748581f, 0.002663117f }, // Log(1.46484375)
198 { 0.384411699f, 0.002656044f }, // Log(1.46875000)
199 { 0.387067743f, 0.002649008f }, // Log(1.47265625)
200 { 0.389716751f, 0.002642009f }, // Log(1.47656250)
201 { 0.392358761f, 0.002635048f }, // Log(1.48046875)
202 { 0.394993808f, 0.002628122f }, // Log(1.48437500)
203 { 0.397621931f, 0.002621233f }, // Log(1.48828125)
204 { 0.400243164f, 0.002614381f }, // Log(1.49218750)
205 { 0.402857545f, 0.002607563f }, // Log(1.49609375)
206 { 0.405465108f, 0.002600782f }, // Log(1.50000000)
207 { 0.408065890f, 0.002594035f }, // Log(1.50390625)
208 { 0.410659925f, 0.002587324f }, // Log(1.50781250)
209 { 0.413247249f, 0.002580647f }, // Log(1.51171875)
210 { 0.415827895f, 0.002574004f }, // Log(1.51562500)
211 { 0.418401899f, 0.002567396f }, // Log(1.51953125)
212 { 0.420969295f, 0.002560821f }, // Log(1.52343750)
213 { 0.423530116f, 0.002554280f }, // Log(1.52734375)
214 { 0.426084395f, 0.002547772f }, // Log(1.53125000)
215 { 0.428632167f, 0.002541297f }, // Log(1.53515625)
216 { 0.431173465f, 0.002534856f }, // Log(1.53906250)
217 { 0.433708320f, 0.002528446f }, // Log(1.54296875)
218 { 0.436236767f, 0.002522069f }, // Log(1.54687500)
219 { 0.438758836f, 0.002515725f }, // Log(1.55078125)
220 { 0.441274561f, 0.002509412f }, // Log(1.55468750)
221 { 0.443783972f, 0.002503130f }, // Log(1.55859375)
222 { 0.446287103f, 0.002496880f }, // Log(1.56250000)
223 { 0.448783983f, 0.002490661f }, // Log(1.56640625)
224 { 0.451274644f, 0.002484473f }, // Log(1.57031250)
225 { 0.453759117f, 0.002478316f }, // Log(1.57421875)
226 { 0.456237433f, 0.002472189f }, // Log(1.57812500)
227 { 0.458709623f, 0.002466092f }, // Log(1.58203125)
228 { 0.461175715f, 0.002460026f }, // Log(1.58593750)
229 { 0.463635741f, 0.002453989f }, // Log(1.58984375)
230 { 0.466089730f, 0.002447982f }, // Log(1.59375000)
231 { 0.468537712f, 0.002442004f }, // Log(1.59765625)
232 { 0.470979715f, 0.002436055f }, // Log(1.60156250)
233 { 0.473415770f, 0.002430135f }, // Log(1.60546875)
234 { 0.475845905f, 0.002424244f }, // Log(1.60937500)
235 { 0.478270148f, 0.002418381f }, // Log(1.61328125)
236 { 0.480688529f, 0.002412546f }, // Log(1.61718750)
237 { 0.483101076f, 0.002406740f }, // Log(1.62109375)
238 { 0.485507816f, 0.002400962f }, // Log(1.62500000)
239 { 0.487908777f, 0.002395211f }, // Log(1.62890625)
240 { 0.490303988f, 0.002389487f }, // Log(1.63281250)
241 { 0.492693475f, 0.002383791f }, // Log(1.63671875)
242 { 0.495077267f, 0.002378122f }, // Log(1.64062500)
243 { 0.497455389f, 0.002372480f }, // Log(1.64453125)
244 { 0.499827870f, 0.002366865f }, // Log(1.64843750)
245 { 0.502194735f, 0.002361276f }, // Log(1.65234375)
246 { 0.504556011f, 0.002355714f }, // Log(1.65625000)
247 { 0.506911724f, 0.002350177f }, // Log(1.66015625)
248 { 0.509261902f, 0.002344667f }, // Log(1.66406250)
249 { 0.511606569f, 0.002339182f }, // Log(1.66796875)
250 { 0.513945751f, 0.002333723f }, // Log(1.67187500)
251 { 0.516279474f, 0.002328290f }, // Log(1.67578125)
252 { 0.518607764f, 0.002322881f }, // Log(1.67968750)
253 { 0.520930646f, 0.002317498f }, // Log(1.68359375)
254 { 0.523248144f, 0.002312140f }, // Log(1.68750000)
255 { 0.525560284f, 0.002306806f }, // Log(1.69140625)
256 { 0.527867090f, 0.002301497f }, // Log(1.69531250)
257 { 0.530168587f, 0.002296212f }, // Log(1.69921875)
258 { 0.532464799f, 0.002290952f }, // Log(1.70312500)
259 { 0.534755751f, 0.002285715f }, // Log(1.70703125)
260 { 0.537041466f, 0.002280503f }, // Log(1.71093750)
261 { 0.539321969f, 0.002275314f }, // Log(1.71484375)
262 { 0.541597282f, 0.002270149f }, // Log(1.71875000)
263 { 0.543867431f, 0.002265007f }, // Log(1.72265625)
264 { 0.546132438f, 0.002259888f }, // Log(1.72656250)
265 { 0.548392326f, 0.002254792f }, // Log(1.73046875)
266 { 0.550647118f, 0.002249720f }, // Log(1.73437500)
267 { 0.552896838f, 0.002244670f }, // Log(1.73828125)
268 { 0.555141508f, 0.002239643f }, // Log(1.74218750)
269 { 0.557381150f, 0.002234638f }, // Log(1.74609375)
270 { 0.559615788f, 0.002229655f }, // Log(1.75000000)
271 { 0.561845443f, 0.002224695f }, // Log(1.75390625)
272 { 0.564070138f, 0.002219757f }, // Log(1.75781250)
273 { 0.566289895f, 0.002214840f }, // Log(1.76171875)
274 { 0.568504735f, 0.002209946f }, // Log(1.76562500)
275 { 0.570714681f, 0.002205073f }, // Log(1.76953125)
276 { 0.572919754f, 0.002200221f }, // Log(1.77343750)
277 { 0.575119974f, 0.002195391f }, // Log(1.77734375)
278 { 0.577315365f, 0.002190581f }, // Log(1.78125000)
279 { 0.579505946f, 0.002185793f }, // Log(1.78515625)
280 { 0.581691740f, 0.002181026f }, // Log(1.78906250)
281 { 0.583872766f, 0.002176279f }, // Log(1.79296875)
282 { 0.586049045f, 0.002171554f }, // Log(1.79687500)
283 { 0.588220599f, 0.002166848f }, // Log(1.80078125)
284 { 0.590387447f, 0.002162163f }, // Log(1.80468750)
285 { 0.592549610f, 0.002157498f }, // Log(1.80859375)
286 { 0.594707108f, 0.002152853f }, // Log(1.81250000)
287 { 0.596859961f, 0.002148229f }, // Log(1.81640625)
288 { 0.599008190f, 0.002143624f }, // Log(1.82031250)
289 { 0.601151813f, 0.002139038f }, // Log(1.82421875)
290 { 0.603290851f, 0.002134473f }, // Log(1.82812500)
291 { 0.605425324f, 0.002129926f }, // Log(1.83203125)
292 { 0.607555250f, 0.002125399f }, // Log(1.83593750)
293 { 0.609680650f, 0.002120892f }, // Log(1.83984375)
294 { 0.611801541f, 0.002116403f }, // Log(1.84375000)
295 { 0.613917944f, 0.002111933f }, // Log(1.84765625)
296 { 0.616029877f, 0.002107482f }, // Log(1.85156250)
297 { 0.618137360f, 0.002103050f }, // Log(1.85546875)
298 { 0.620240410f, 0.002098637f }, // Log(1.85937500)
299 { 0.622339046f, 0.002094242f }, // Log(1.86328125)
300 { 0.624433288f, 0.002089865f }, // Log(1.86718750)
301 { 0.626523153f, 0.002085506f }, // Log(1.87109375)
302 { 0.628608659f, 0.002081166f }, // Log(1.87500000)
303 { 0.630689826f, 0.002076844f }, // Log(1.87890625)
304 { 0.632766670f, 0.002072540f }, // Log(1.88281250)
305 { 0.634839209f, 0.002068253f }, // Log(1.88671875)
306 { 0.636907462f, 0.002063984f }, // Log(1.89062500)
307 { 0.638971446f, 0.002059733f }, // Log(1.89453125)
308 { 0.641031179f, 0.002055499f }, // Log(1.89843750)
309 { 0.643086679f, 0.002051283f }, // Log(1.90234375)
310 { 0.645137961f, 0.002047084f }, // Log(1.90625000)
311 { 0.647185045f, 0.002042902f }, // Log(1.91015625)
312 { 0.649227947f, 0.002038737f }, // Log(1.91406250)
313 { 0.651266683f, 0.002034589f }, // Log(1.91796875)
314 { 0.653301272f, 0.002030458f }, // Log(1.92187500)
315 { 0.655331730f, 0.002026343f }, // Log(1.92578125)
316 { 0.657358073f, 0.002022245f }, // Log(1.92968750)
317 { 0.659380318f, 0.002018164f }, // Log(1.93359375)
318 { 0.661398482f, 0.002014099f }, // Log(1.93750000)
319 { 0.663412582f, 0.002010051f }, // Log(1.94140625)
320 { 0.665422633f, 0.002006019f }, // Log(1.94531250)
321 { 0.667428651f, 0.002002003f }, // Log(1.94921875)
322 { 0.669430654f, 0.001998003f }, // Log(1.95312500)
323 { 0.671428657f, 0.001994019f }, // Log(1.95703125)
324 { 0.673422675f, 0.001990050f }, // Log(1.96093750)
325 { 0.675412726f, 0.001986098f }, // Log(1.96484375)
326 { 0.677398824f, 0.001982161f }, // Log(1.96875000)
327 { 0.679380985f, 0.001978240f }, // Log(1.97265625)
328 { 0.681359225f, 0.001974334f }, // Log(1.97656250)
329 { 0.683333559f, 0.001970444f }, // Log(1.98046875)
330 { 0.685304003f, 0.001966569f }, // Log(1.98437500)
331 { 0.687270572f, 0.001962709f }, // Log(1.98828125)
332 { 0.689233281f, 0.001958864f }, // Log(1.99218750)
333 { 0.691192146f, 0.001955035f }, // Log(1.99609375)
334 { 0.693147181f, 0.001951220f }, // Log(2.00000000)
335 };
336
337
338
339 /*!--------------------------------------------------------------------------*
340 Name: FExpLn2
341
342
343
344
345
346
347
348
349 *---------------------------------------------------------------------------*/
350 NN_MATH_INLINE f32
FExpLn2(f32 x)351 FExpLn2(f32 x)
352 {
353 f32 fidx;
354 u16 idx;
355 f32 r;
356
357 // |x| must be less than ln2
358 // map [-ln2, ln2) -> [0, 32)
359 fidx = (x + F_LN2) * (32 / (2 * F_LN2));
360 idx = F32ToU16(fidx);
361 r = fidx - U16ToF32(idx);
362
363 return sExpTbl[idx].exp_val + r * sExpTbl[idx].exp_delta;
364 }
365
366
367
368 /*!--------------------------------------------------------------------------*
369 Name: FLog1_2
370
371
372
373
374
375
376
377 *---------------------------------------------------------------------------*/
378 NN_MATH_INLINE f32
FLog1_2(f32 x)379 FLog1_2(f32 x)
380 {
381 f32 fidx;
382 u16 idx;
383 f32 r;
384
385 // Make sure that 1 <= x < 2
386 // map [1, 2) -> [0, 256)
387 fidx = (x - 1) * 256.f; // 0 <= fidx < 256
388 idx = F32ToU16(fidx);
389 r = fidx - U16ToF32(idx);
390
391 return sLogTbl[idx].log_val + r * sLogTbl[idx].log_delta;
392 }
393
394
395 } // End of anonymous namespace
396
397
398 namespace internal
399 {
400
401
402 /*!--------------------------------------------------------------------------*
403 Name: FExp
404
405
406
407
408
409
410
411 *---------------------------------------------------------------------------*/
412 // Divide by 2^16 from -10 to 10, including both ends, and calculate the error at each sample point.
413 // For sExpTbl[32] Maximum relative error for std is 0.0235 % Average relative error is 0.0156 %
414 // For sExpTbl[256] Maximum relative error for std is 0.000427 % Average relative error is 0.000245 %
415 f32
FExp(f32 x)416 FExp(f32 x)
417 {
418 /*
419 exp(x) = exp(xn + k * ln2)
420 = exp(xn) * exp(k * ln2)
421 = exp(xn) * 2^k
422
423 |xn| ln2
424 */
425
426 s16 k;
427 f32 kf;
428 f32 xn;
429 f32 expxn;
430
431 // Converts x to the form xn + k * ln2
432 // However, |xn| < ln2, and k is an integer
433 // Make sure that -128 <= k <= 127
434 k = F32ToS16(F_INVLN2 * x);
435 kf = S16ToF32(k);
436 xn = x - kf * F_LN2;
437
438 // Finds exp(xn) by table lookup.
439 expxn = FExpLn2(xn);
440
441 // exp(x) = exp(xn) * 2^k
442 // Add directly to exponent
443 // Since the exp result will not be negative, mask the carry part and erase.
444 u32 expx = (F32AsU32(expxn) + (k << 23)) & 0x7FFFFFFF;
445 return U32AsF32(expx);
446 }
447
448
449
450
451
452 /*!--------------------------------------------------------------------------*
453 Name: FLog
454
455
456
457
458
459
460 *---------------------------------------------------------------------------*/
461 // Divide by 2^16 from 0.001 to 10, including both ends, and calculate the error at each sample point.
462 // For sLogTbl[32] Maximum relative error for std is 1.528 % Average relative error is 0.00857 %
463 // For sLogTbl[128] Maximum relative error for std is 0.386 % Average relative error is 0.000623 %
464 // For sLogTbl[256] Maximum relative error for std is 0.192 % Average relative error is 0.000167 %
465 // The relative error is maximized around x = 1.
466 f32
FLog(f32 x)467 FLog(f32 x)
468 {
469 /*
470 log(x) = log(xn * 2^k)
471 = log(xn) + log(2^k)
472 = log(xn) + k * ln2
473
474 1 xn 2
475 */
476
477 s32 k;
478 f32 kf;
479 f32 xn;
480 f32 logxn;
481
482 // Converts x to the form xn * 2^k
483 k = FGetExpPart(x);
484 xn = FGetMantPart(x);
485 kf = S16ToF32(static_cast<s16>(k));
486
487 // Finds log(xn) by table lookup.
488 logxn = FLog1_2(xn);
489
490 // log(x) = log(xn) + k * ln2
491 return logxn + kf * F_LN2;
492 }
493
494 } // end of namespace internal
495
496
497
498 /*!--------------------------------------------------------------------------*
499 Name: Bezier
500
501
502
503
504
505
506
507
508
509
510 *---------------------------------------------------------------------------*/
Bezier(f32 p1,f32 p2,f32 p3,f32 p4,f32 s)511 f32 Bezier(f32 p1, f32 p2, f32 p3, f32 p4, f32 s)
512 {
513 // Be sure to use a better method of calculation
514 f32 t = 1.f - s;
515 f32 tt = t * t;
516 f32 ss = s * s;
517
518 f32 a1 = tt * t;
519 f32 a2 = tt * s * 3.f;
520 f32 a3 = ss * t * 3.f;
521 f32 a4 = ss * s;
522
523 return a1*p1 + a2*p2 + a3*p3 + a4*p4;
524 }
525
526
527 /*!--------------------------------------------------------------------------*
528 Name: CatmullRom
529
530
531
532
533
534
535
536
537
538
539 *---------------------------------------------------------------------------*/
CatmullRom(f32 p0,f32 p1,f32 p2,f32 p3,f32 s)540 f32 CatmullRom(f32 p0, f32 p1, f32 p2, f32 p3, f32 s)
541 {
542 // Be sure to use a better method of calculation
543 return Hermite(p1, 0.5f * (p0 + p2),
544 p2, 0.5f * (p1 + p3),
545 s);
546 }
547
548
549
550 /*!--------------------------------------------------------------------------*
551 Name: CntBit1
552
553
554
555
556
557
558 *---------------------------------------------------------------------------*/
CntBit1(u32 x)559 u32 CntBit1(u32 x)
560 {
561 x = x - ((x >> 1) & 0x55555555);
562 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
563 x = (x + (x >> 4)) & 0x0f0f0f0f;
564 x = x + (x >> 8);
565 x = x + (x >> 16);
566 return x & 0x0000003f;
567 }
568
569
570
571 /*!--------------------------------------------------------------------------*
572 Name: CntBit1
573
574
575
576
577
578
579
580 *---------------------------------------------------------------------------*/
CntBit1(const u32 * first,const u32 * last)581 u32 CntBit1(const u32* first, const u32* last)
582 {
583 const u32 n = u32(last - first);
584
585 u32 i, j, lim;
586 unsigned int s = 0;
587 unsigned int ss, x;
588
589 for (i = 0; i < n; i += 31)
590 {
591 lim = (n < i + 31) ? n : (i + 31);
592 ss = 0;
593 for (j = i; j < lim; ++j)
594 {
595 x = *(first + j);
596 x -= ((x >> 1) & 0x55555555);
597 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
598 x = (x + (x >> 4)) & 0x0f0f0f0f;
599 ss += x;
600 }
601 x = (ss & 0x00ff00ff) + ((ss >> 8) & 0x00ff00ff);
602 x = (x & 0x0000ffff) + (x >> 16);
603 s += x;
604 }
605 return s;
606 }
607
608
609 /*!--------------------------------------------------------------------------*
610 Name: DistBit
611
612
613
614
615
616
617
618
619
620
621 *---------------------------------------------------------------------------*/
DistBit(const u32 * first1,const u32 * last1,const u32 * first2)622 u32 DistBit(const u32* first1, const u32* last1, const u32* first2)
623 {
624 unsigned int n = 0;
625 while(first1 != last1)
626 {
627 n += DistBit(*first1, *first2);
628 ++first1;
629 ++first2;
630 }
631 return n;
632 }
633
634
635 /*!--------------------------------------------------------------------------*
636 Name: RevBit
637
638
639
640
641
642
643 *---------------------------------------------------------------------------*/
RevBit(u32 x)644 u32 RevBit(u32 x)
645 {
646 x = ((x & 0x55555555) << 1) | ((x >> 1) & 0x55555555);
647 x = ((x & 0x33333333) << 2) | ((x >> 2) & 0x33333333);
648 x = ((x & 0x0f0f0f0f) << 4) | ((x >> 4) & 0x0f0f0f0f);
649 x = (x << 24) | ((x & 0xff00) << 8) | ((x >> 8) & 0xff00) | (x >> 24);
650
651 return x;
652 }
653
654
655 /*!--------------------------------------------------------------------------*
656 Name: IExp
657
658
659
660
661
662
663
664 *---------------------------------------------------------------------------*/
665 int
IExp(int x,u32 n)666 IExp(int x, u32 n)
667 {
668 int p, y;
669
670 y = 1;
671 p = x;
672 for (;;)
673 {
674 if (n & 1) { y *= p; }
675 n >>= 1;
676 if (n == 0) { return y; }
677 p *= p;
678 }
679 }
680
681
682 /*!--------------------------------------------------------------------------*
683 Name: ILog10
684
685
686
687
688
689
690 *---------------------------------------------------------------------------*/
ILog10(u32 x)691 u32 ILog10(u32 x)
692 {
693 u32 y;
694 static u32 table2[11] = {
695 0, 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, 0xFFFFFFFF
696 };
697
698 y = (19 * (31 - CntLz(x))) >> 6;
699 y += ((table2[y + 1] - x) >> 31);
700
701 return y;
702 }
703
704
705 namespace internal
706 {
707
708 /*!--------------------------------------------------------------------------*
709
710
711 Name: CntLz_
712
713
714
715
716
717 *---------------------------------------------------------------------------*/
718 u32
CntLz_(u32 x)719 CntLz_(u32 x)
720 {
721 unsigned int y;
722 int n, c;
723
724 n = 32;
725 c = 16;
726 do {
727 y = x >> c;
728 if (y != 0)
729 {
730 n -= c; x = y;
731 }
732 c >>= 1;
733 } while(c != 0);
734 return n - x;
735 }
736
737 } // internal
738
739
740 }} // nw::math
741