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