1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: math_Triangular.h
4
5 Copyright (C)2009-2010 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 $Revision: 19123 $
14 *---------------------------------------------------------------------------*/
15
16 #ifndef NN_MATH_TRIANGULAR_H_
17 #define NN_MATH_TRIANGULAR_H_
18
19 #include <nn/math/math_Config.h>
20 #include <nn/math/math_Constant.h>
21 #include <nn/math/math_Arithmetic.h>
22
23 #include <cmath>
24
25
26 namespace nn {
27 namespace math {
28 namespace internal {
29
30 struct SinCosSample
31 {
32 f32 sin_val;
33 f32 cos_val;
34 f32 sin_delta; // 次のsin_valとの差
35 f32 cos_delta; // 次のcos_valとの差
36 };
37
38 extern const SinCosSample gSinCosTbl[256 + 1];
39
40 } // namespace internal
41 } // namespace math
42 } // namespace nn
43
44
45 namespace nn {
46 namespace math {
47
48
49 /* =======================================================================
50 sin/cos/tan
51 ======================================================================== */
52 /*!
53 @name 三角関数
54 @{
55 */
56
57 #define NN_MATH_RAD_TO_FIDX(rad) ((rad) * (256.f / (2.0f * ::nn::math::F_PI)))
58 #define NN_MATH_DEG_TO_FIDX(deg) ((deg) * (256.f / 360.f) )
59 #define NN_MATH_DEG_TO_RAD(deg) ((deg) * (::nn::math::F_PI / 180.0f) )
60 #define NN_MATH_RAD_TO_DEG(rad) ((rad) * (180.0f / ::nn::math::F_PI) )
61 #define NN_MATH_FIDX_TO_RAD(fidx) ((fidx) * ((2.0f * ::nn::math::F_PI) / 256.f))
62 #define NN_MATH_FIDX_TO_DEG(fidx) ((fidx) * (360.f / 256.f) )
63
64
65 /*!--------------------------------------------------------------------------*
66 @brief 正弦の値を求めます
67
68 @param[in] fidx 1 円周を 256.0 とする角度
69
70 @return fidx に対する正弦の値を返します。
71 *---------------------------------------------------------------------------*/
72 f32 SinFIdx(f32 fidx);
73
74 /*!--------------------------------------------------------------------------*
75 @brief 余弦の値を求めます
76
77 @param[in] fidx 1 円周を 256.0 とする角度
78
79 @return fidx に対する余弦の値を返します。
80 *---------------------------------------------------------------------------*/
81 f32 CosFIdx(f32 fidx);
82
83 /*!--------------------------------------------------------------------------*
84 @brief 正弦と余弦の値を求めます
85
86 @param[out] pSin 正弦の値を格納するバッファへのポインタ
87 @param[out] pCos 余弦の値を格納するバッファへのポインタ
88 @param[in] fidx 1 円周を 256.0 とする角度
89
90 @return なし
91 *---------------------------------------------------------------------------*/
92 void SinCosFIdx(f32* pSin, f32* pCos, f32 fidx);
93
94 /*!--------------------------------------------------------------------------*
95 @brief 正接の値を求めます
96
97 @param[in] fidx 1 円周を 256.0 とする角度
98
99 @return fidx に対する正接の値を返します。
100 *---------------------------------------------------------------------------*/
101 inline f32
TanFIdx(f32 fidx)102 TanFIdx(f32 fidx)
103 {
104 return ::std::tanf(NN_MATH_FIDX_TO_RAD(fidx));
105 }
106
107
108 /*!--------------------------------------------------------------------------*
109 @brief 正弦の値を求めます。
110
111 @param[in] rad ラジアン単位の角度
112
113 @return rad に対する正弦の値を返します。
114 *---------------------------------------------------------------------------*/
SinRad(f32 rad)115 inline f32 SinRad(f32 rad) { return SinFIdx(NN_MATH_RAD_TO_FIDX(rad)); }
116
117 /*!--------------------------------------------------------------------------*
118 @brief 余弦の値を求めます。
119
120 @param[in] rad ラジアン単位の角度
121
122 @return rad に対する余弦の値を返します。
123 *---------------------------------------------------------------------------*/
CosRad(f32 rad)124 inline f32 CosRad(f32 rad) { return CosFIdx(NN_MATH_RAD_TO_FIDX(rad)); }
125
126 /*!--------------------------------------------------------------------------*
127 @brief 正弦と余弦の値を求めます。
128
129 @param[out] s 正弦の値を格納するバッファへのポインタ
130 @param[out] c 余弦の値を格納するバッファへのポインタ
131 @param[in] rad ラジアン単位の角度
132
133 @return なし
134 *---------------------------------------------------------------------------*/
SinCosRad(f32 * s,f32 * c,f32 rad)135 inline void SinCosRad(f32* s, f32* c, f32 rad) { SinCosFIdx(s, c, NN_MATH_RAD_TO_FIDX(rad)); }
136
137 /*!--------------------------------------------------------------------------*
138 @brief 正接の値を求めます。
139
140 @param[in] rad ラジアン単位の角度
141
142 @return rad に対する正接の値を返します。
143 *---------------------------------------------------------------------------*/
TanRad(f32 rad)144 inline f32 TanRad(f32 rad) { return TanFIdx(NN_MATH_RAD_TO_FIDX(rad)); }
145
146
147
148
149 /*!--------------------------------------------------------------------------*
150 @brief 正弦の値を求めます。
151
152 @param[in] deg 1 円周を 360.0 とする角度
153
154 @return deg に対する正弦の値を返します。
155 *---------------------------------------------------------------------------*/
SinDeg(f32 deg)156 inline f32 SinDeg(f32 deg) { return SinFIdx(NN_MATH_DEG_TO_FIDX(deg)); }
157
158 /*!--------------------------------------------------------------------------*
159 @brief 余弦の値を求めます。
160
161 @param[in] deg 1 円周を 360.0 とする角度
162
163 @return deg に対する余弦の値を返します。
164 *---------------------------------------------------------------------------*/
CosDeg(f32 deg)165 inline f32 CosDeg(f32 deg) { return CosFIdx(NN_MATH_DEG_TO_FIDX(deg)); }
166
167 /*!--------------------------------------------------------------------------*
168 @brief 正弦と余弦の値を求めます。
169
170 @param[out] s 正弦の値を格納するバッファへのポインタ
171 @param[out] c 余弦の値を格納するバッファへのポインタ
172 @param[in] deg 1 円周を 360.0 とする角度
173
174 @return なし
175 *---------------------------------------------------------------------------*/
SinCosDeg(f32 * s,f32 * c,f32 deg)176 inline void SinCosDeg(f32* s, f32* c, f32 deg) { SinCosFIdx(s, c, NN_MATH_DEG_TO_FIDX(deg)); }
177
178 /*!--------------------------------------------------------------------------*
179 @brief 正接の値を求めます。
180
181 @param[in] deg 1 円周を 360.0 とする角度
182
183 @return deg に対する正接の値を返します。
184 *---------------------------------------------------------------------------*/
TanDeg(f32 deg)185 inline f32 TanDeg(f32 deg) { return TanFIdx(NN_MATH_DEG_TO_FIDX(deg)); }
186
187 #if 1
188 /* 16bitインデックスのものを使うことになったら、この関数の実装を置き換える */
189
190 /*!--------------------------------------------------------------------------*
191 @brief 正弦の値を求めます。
192
193 @param[in] idx 1 円周を 65536 とする角度
194
195 @return idx に対する正弦の値を返します。
196 *---------------------------------------------------------------------------*/
197 f32 SinIdx(u16 idx);
198
199 /*!--------------------------------------------------------------------------*
200 @brief 余弦の値を求めます。
201
202 @param[in] idx 1 円周を 65536 とする角度
203
204 @return idx に対する余弦の値を返します。
205 *---------------------------------------------------------------------------*/
206 f32 CosIdx(u16 idx);
207
208 /*!--------------------------------------------------------------------------*
209 @brief 正弦と余弦の値を求めます。
210
211 @param[out] s 正弦の値を格納するバッファへのポインタ
212 @param[out] c 余弦の値を格納するバッファへのポインタ
213 @param[in] idx 1 円周を 65536 とする角度
214
215 @return なし
216 *---------------------------------------------------------------------------*/
217 void SinCosIdx(f32* s, f32* c, u16 idx);
218
219 /*!--------------------------------------------------------------------------*
220 @brief 正接の値を求めます。
221
222 @param[in] idx 1 円周を 65536 とする角度
223
224 @return idx に対する正接の値を返します。
225 *---------------------------------------------------------------------------*/
TanIdx(u16 idx)226 inline f32 TanIdx(u16 idx) { return TanFIdx(U16ToF32(idx) * (1.f / 256.f)); }
227 #endif
228
NN_fAcos(f32 x)229 inline f32 NN_fAcos(f32 x) { return ::std::acosf(x); }
NN_fAsin(f32 x)230 inline f32 NN_fAsin(f32 x) { return ::std::asinf(x); }
NN_fAtan(f32 x)231 inline f32 NN_fAtan(f32 x) { return ::std::atanf(x); }
NN_fAtan2(f32 y,f32 x)232 inline f32 NN_fAtan2(f32 y, f32 x) { return ::std::atan2f(y, x); }
233
234
235 /*!--------------------------------------------------------------------------*
236 @brief 逆正弦の値を求めます。
237
238 @param[in] x 逆正弦を求める値
239
240 @return 1 円周を 256.0 とする角度で逆正弦の値を返します。
241 *---------------------------------------------------------------------------*/
242 inline f32
AsinFIdx(f32 x)243 AsinFIdx(f32 x)
244 {
245 NN_MATH_WARNING(x <= 1.f && x >= -1.f, "AsinFIdx: Input is out of the domain.");
246 return NN_MATH_RAD_TO_FIDX(::std::asin(x));
247 }
248
249 /*!--------------------------------------------------------------------------*
250 @brief 逆余弦の値を求めます。
251
252 @param[in] x 逆余弦を求める値
253
254 @return 1 円周を 256.0 とする角度で逆余弦の値を返します。
255 *---------------------------------------------------------------------------*/
256 inline f32
AcosFIdx(f32 x)257 AcosFIdx(f32 x)
258 {
259 NN_MATH_WARNING(x <= 1.f && x >= -1.f, "AcosFIdx: Input is out of the domain.");
260 return NN_MATH_RAD_TO_FIDX(::std::acosf(x));
261 }
262
263
264 f32 AtanFIdx(f32 x);
265 f32 Atan2FIdx(f32 y, f32 x);
266
267
268 /*!--------------------------------------------------------------------------*
269 @brief 逆正弦の値を求めます。
270
271 @param[in] x 逆正弦を求める値
272
273 @return x に対する逆正弦の値をラジアン単位で返します
274 *---------------------------------------------------------------------------*/
AsinRad(f32 x)275 inline f32 AsinRad(f32 x)
276 {
277 NN_MATH_WARNING(x <= 1.f && x >= -1.f, "AsinRad: Input is out of the domain.");
278 return ::std::asin(x);
279 }
280
281 /*!--------------------------------------------------------------------------*
282 @brief 逆余弦の値を求めます。
283
284 @param[in] x 逆余弦を求める値
285
286 @return x に対する逆余弦の値をラジアン単位で返します
287 *---------------------------------------------------------------------------*/
AcosRad(f32 x)288 inline f32 AcosRad(f32 x)
289 {
290 NN_MATH_WARNING(x <= 1.f && x >= -1.f, "AcosRad: Input is out of the domain.");
291 return ::std::acos(x);
292 }
293
294 /*!--------------------------------------------------------------------------*
295 @brief 逆正接の値を求めます。
296
297 @param[in] x 逆正接を求める値
298
299 @return x に対する逆正接の値をラジアン単位で返します
300 *---------------------------------------------------------------------------*/
AtanRad(f32 x)301 inline f32 AtanRad(f32 x) { return NN_MATH_FIDX_TO_RAD(AtanFIdx(x)); }
302
303 /*!--------------------------------------------------------------------------*
304 @brief 逆正接の値を求めます。
305
306 @param[in] y 正接の値の分子
307 @param[in] x 正接の値の分母
308
309 @return y/x の逆正接の値をラジアン単位で返します
310 *---------------------------------------------------------------------------*/
Atan2Rad(f32 y,f32 x)311 inline f32 Atan2Rad(f32 y, f32 x) { return NN_MATH_FIDX_TO_RAD(Atan2FIdx(y, x)); }
312
313
314
315
316
317
318 /*!--------------------------------------------------------------------------*
319 @brief 逆正弦の値を求めます。
320
321 @param[in] x 逆正弦を求める値
322
323 @return x に対する逆正弦の値を 360.0 を 1 円周とする単位で返します
324 *---------------------------------------------------------------------------*/
AsinDeg(f32 x)325 inline f32 AsinDeg(f32 x)
326 {
327 NN_MATH_WARNING(x <= 1.f && x >= -1.f, "AsinDeg: Input is out of the domain.");
328 return NN_MATH_RAD_TO_DEG(::std::asin(x));
329 }
330
331 /*!--------------------------------------------------------------------------*
332 @brief 逆余弦の値を求めます。
333
334 @param[in] x 逆余弦を求める値
335
336 @return x に対する逆余弦の値を 360.0 を 1 円周とする単位で返します
337 *---------------------------------------------------------------------------*/
AcosDeg(f32 x)338 inline f32 AcosDeg(f32 x)
339 {
340 NN_MATH_WARNING(x <= 1.f && x >= -1.f, "AcosDeg: Input is out of the domain.");
341 return NN_MATH_RAD_TO_DEG(::std::acos(x));
342 }
343
344 /*!--------------------------------------------------------------------------*
345 @brief 逆正接の値を求めます。
346
347 @param[in] x 逆正接を求める値
348
349 @return x に対する逆正接の値を 360.0 を 1 円周とする単位で返します
350 *---------------------------------------------------------------------------*/
AtanDeg(f32 x)351 inline f32 AtanDeg(f32 x) { return NN_MATH_FIDX_TO_DEG(AtanFIdx(x)); }
352
353 /*!--------------------------------------------------------------------------*
354 @brief 逆正接の値を求めます。
355
356 @param[in] y 正接の値の分子
357 @param[in] x 正接の値の分母
358
359 @return y/x の逆正接の値を 360.0 を 1 円周とする単位で返します
360 *---------------------------------------------------------------------------*/
Atan2Deg(f32 y,f32 x)361 inline f32 Atan2Deg(f32 y, f32 x) { return NN_MATH_FIDX_TO_DEG(Atan2FIdx(y, x)); }
362
363 #if 1
364 /* 16bitインデックスのものを使うことになったら、この関数の実装を置き換える */
365
366
367 /*!--------------------------------------------------------------------------*
368 @brief 逆正弦の値を求めます。
369
370 @param[in] x 逆正弦を求める値
371
372 @return x に対する逆正弦の値を 65536 を 1 円周とする単位で返します
373 *---------------------------------------------------------------------------*/
374 // 0°~ 90°と 270°~ 360°の範囲のインデックスを返します
AsinIdx(f32 x)375 inline u16 AsinIdx(f32 x) { f32 fidx = AsinFIdx(x); return F32ToU16((fidx < 0 ? fidx + 256.f : fidx) * 256.f); }
376
377 /*!--------------------------------------------------------------------------*
378 @brief 逆余弦の値を求めます。
379
380 @param[in] x 逆余弦を求める値
381
382 @return x に対する逆余弦の値を 65536 を 1 円周とする単位で返します
383 *---------------------------------------------------------------------------*/
384 // [0,PI] の範囲のインデックスを返します
AcosIdx(f32 x)385 inline u16 AcosIdx(f32 x) { return F32ToU16(AcosFIdx(x) * 256.f); }
386
387 /*!--------------------------------------------------------------------------*
388 @brief 逆正接の値を求めます。
389
390 @param[in] x 逆正接を求める値
391
392 @return x に対する逆正接の値を 65536 を 1 円周とする単位で返します
393 *---------------------------------------------------------------------------*/
394 // 0°~ 90°と 270°~ 360°の範囲のインデックスを返します
395 u16 AtanIdx(f32 x);
396
397 /*!--------------------------------------------------------------------------*
398 @brief 逆正接の値を求めます。
399
400 @param[in] y 正接の値の分子
401 @param[in] x 正接の値の分母
402
403 @return y/x の逆正接の値を 65536 を 1 円周とする単位で返します
404 *---------------------------------------------------------------------------*/
405 // 0°~ 360°の範囲のインデックスを返します
406 u16 Atan2Idx(f32 y, f32 x);
407 #endif
408
409 /*!
410 @}
411 */
412
413 } // namespace math
414 } // namespace nn
415
416
417 /* NN_MATH_TRIANGULAR_H_ */
418 #endif
419