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 
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