1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: math_Arithmetic.cpp
4
5 Copyright (C)2009 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: 24106 $
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 //---- 指数関数のテーブル
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 //---- 対数関数のテーブル
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 @brief 指数関数の値をテーブル引きで求めます。
343 e^x を求めます。
344
345 @param[in] x 指数の値。
346 - loge(2) < x < loge(2) でなければなりません。
347
348 @return e^x の近似値。
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| < 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 @brief 対数関数の値をテーブル引きで求めます。
372
373 @param[in] x 対数を求める値。
374 1 <= x < 2 でなければなりません。
375
376 @return loge(x) の近似値。
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 // 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 @brief 指数関数の値をテーブル引きで求めます。
406 e^x を求めます。
407
408 @param[in] x 指数の値。
409
410 @return e^x の近似値。
411 *---------------------------------------------------------------------------*/
412 // -10 から 10 までを両端を含んで2^16分割し、各サンプル点において誤差を計測
413 // sExpTbl[32]の場合 std に対する最大相対誤差 0.0235 % 平均相対誤差 0.0156 %
414 // sExpTbl[256]の場合 std に対する最大相対誤差 0.000427 % 平均相対誤差 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 // x を xn + k * ln2 の形に変形します
432 // ただし |xn| < ln2, k は整数 です
433 // -128 <= k <= 127 でなければなりません
434 k = F32ToS16(F_INVLN2 * x);
435 kf = S16ToF32(k);
436 xn = x - kf * F_LN2;
437
438 // exp(xn) をテーブル引きで求めます
439 expxn = FExpLn2(xn);
440
441 // exp(x) = exp(xn) * 2^k
442 // 直接指数部に足しこみます
443 // Expの結果は負にならないので桁上がり分はマスクして消します
444 u32 expx = (F32AsU32(expxn) + (k << 23)) & 0x7FFFFFFF;
445 return U32AsF32(expx);
446 }
447
448
449
450
451
452 /*!--------------------------------------------------------------------------*
453 Name: FLog
454
455 @brief 対数関数の値をテーブル引きで求めます。
456
457 @param[in] x 対数を求める値。
458
459 @return loge(x) の近似値。
460 *---------------------------------------------------------------------------*/
461 // 0.001 から 10 までを両端を含んで2^16分割し、各サンプル点において誤差を計測
462 // sLogTbl[32]の場合 std に対する最大相対誤差 1.528 % 平均相対誤差 0.00857 %
463 // sLogTbl[128]の場合 std に対する最大相対誤差 0.386 % 平均相対誤差 0.000623 %
464 // sLogTbl[256]の場合 std に対する最大相対誤差 0.192 % 平均相対誤差 0.000167 %
465 // 相対誤差は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 // x を xn * 2^k の形に変形します
483 k = FGetExpPart(x);
484 xn = FGetMantPart(x);
485 kf = S16ToF32(static_cast<s16>(k));
486
487 // log(xn) をテーブル引きで求めます
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 @brief ベジェ補間を行います
502
503 @param[in] p1 点1での値
504 @param[in] p2 点1での制御値
505 @param[in] p3 点2での制御値
506 @param[in] p4 点2での値
507 @param[in] s 補間対象位置。(点1:0.0~1.0:点2)
508
509 @return 補間結果の値。
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 // もう少しマシな計算方法にすること
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 @brief Catmull-Rom 補間 を行います
531
532 @param[in] p0 点1での制御値
533 @param[in] p1 点1での値
534 @param[in] p2 点2での値
535 @param[in] p3 点2での制御値
536 @param[in] s 補間対象位置。(点1:0.0~1.0:点2)
537
538 @return 補間結果の値。
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 // もう少しマシな計算方法にすること
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 @brief ビット列の中で1となっているビットの数を数えます。
554
555 @param[in] x 走査するビット列。
556
557 @return x 中で1となっているビットの数を返します。
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 @brief ビット列の中で 1 となっているビットの数を数えます。
575
576 @param[in] first ビット列の先頭ワードへのポインタ。
577 @param[in] last ビット列の最終ワードの次のワードへのポインタ。
578
579 @return ビット列中で1となっているビットの数を返します。
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 @brief ビット列間の距離を求めます。
613 ビット列間の距離はビット列同士をビットごとに比較した場合の
614 等しいビットの数です。
615
616 @param[in] first1 ビット列 1 の先頭ワードへのポインタ。
617 @param[in] last1 ビット列 1 の最終ワードの次のワードへのポインタ。
618 @param[in] first2 ビット列 2 の先頭ワードへのポインタ。
619
620 @return ビット列 1 とビット列 2 の距離を返します。
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 @brief ビット列の順序を反転します。
639
640 @param[in] x 反転するビット列
641
642 @return x のビット順序を逆順にしたビット列を返します。
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 @brief 整数の非負整数乗を求めます。
659
660 @param[in] x 底となる値
661 @param[in] n 指数の値。非負でなければなりません。
662
663 @return x^n を返します
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 @brief 整数の常用対数を計算し、結果を整数で返します。
686
687 @param[in] x 常用対数を求める値。
688
689 @return x の常用対数を整数で返します。
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 Name: CntLz_
710
711 @brief ビット列の左側からの連続する 0 のビットの数を数えます。
712 専用の命令を持たない PC 用です。
713
714 @param[in] x ビット列。
715
716 @return x 中で左側からの 0 のビットが連続する数を返します。
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