1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: math_Arithmetic.cpp
4 Copyright (C)2009 Nintendo Co., Ltd. All rights reserved.
5 These coded instructions, statements, and computer programs contain
6 proprietary information of Nintendo of America Inc. and/or Nintendo
7 Company Ltd., and are protected by Federal copyright law. They may
8 not be disclosed to third parties or copied or duplicated in any form,
9 in whole or in part, without the prior written consent of Nintendo.
10 $Rev: 24106 $
11 *---------------------------------------------------------------------------
12
13
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
404
405 Name: FExp
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 |xn| ln2
423
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 1 xn 2
474
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