1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: math_Arithmetic.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: 27154 $
14 *---------------------------------------------------------------------------*/
15
16 #ifndef NN_MATH_ARITHMETIC_H_
17 #define NN_MATH_ARITHMETIC_H_
18
19 #include <nn/assert.h>
20 #include <nn/math/math_Config.h>
21 #include <nn/math/math_Constant.h>
22 #include <nn/math/ARMv6/math_Arithmetic.h>
23
24 #include <cmath>
25
26 #pragma push
27 #pragma Otime
28
29 namespace nn { namespace math {
30
31
32
33 /* =======================================================================
34 浮動少数に関する数学関数
35 ======================================================================== */
36
37 /*!
38 @name 浮動小数に関する数学関数
39 @{
40 */
41
42 // u32 F32AsU32(f32 x)
43 //
44 // 説明: f32 型の値をビット列を変更することなく u32 型にします
45 // 引数: x: u32型 にする値。
46 // 返値: x と等しいビット表現を持つ u32 型の値。
47 inline u32
F32AsU32(f32 x)48 F32AsU32(f32 x)
49 {
50 return *reinterpret_cast<u32*>(&x);
51 }
52
53
54
55 /*!--------------------------------------------------------------------------*
56 @brief u32 型の値をビット列を変更することなく f32 型にします
57
58 @param[in] x f32型にする値。
59
60 @return x と等しいビット表現を持つ f32 型の値。
61 *---------------------------------------------------------------------------*/
62 inline f32
U32AsF32(u32 x)63 U32AsF32(u32 x)
64 {
65 return *reinterpret_cast<f32*>(&x);
66 }
67
68
69 /*!--------------------------------------------------------------------------*
70 @brief 浮動小数点数の指数部を取得します。
71
72 @param[in] f 指数部を取得する数。
73
74 @return f の指数部を返します。ただし負の値はオフセット表現ではなく 2 の補数表現です。
75 *---------------------------------------------------------------------------*/
76 inline s32
FGetExpPart(f32 f)77 FGetExpPart(f32 f)
78 {
79 s32 s = static_cast<s32>((F32AsU32(f) >> 23) & 0xFF);
80 return s - 127;
81 }
82
83
84 /*!--------------------------------------------------------------------------*
85 @brief 浮動小数点数の仮数部を求めます。
86
87 @param[in] f 仮数部を取得する数。
88
89 @return f の仮数部を返します。返り値は f と同じ符号を持っています。
90 *---------------------------------------------------------------------------*/
91 inline f32
FGetMantPart(f32 f)92 FGetMantPart(f32 f)
93 {
94 // 指数部を 127 にする
95 u32 u = (F32AsU32(f) & 0x807FFFFF) | 0x3F800000;
96 return U32AsF32(u);
97 }
98
99
100 /*!--------------------------------------------------------------------------*
101 @brief 数の正負に応じて値を選択します。
102
103 @param[in] cond 返り値を選択する条件。
104 @param[in] ifPos cond が0以上の場合の返り値。
105 @param[in] ifNeg cond が負の場合の返り値。
106
107 @return cond が 0 以上であれば ifPos を、そうでなければ ifNeg を返します。
108 *---------------------------------------------------------------------------*/
109 inline f32
FSelect(f32 cond,f32 ifPos,f32 ifNeg)110 FSelect(f32 cond, f32 ifPos, f32 ifNeg)
111 {
112 f32 ret;
113
114 ret = (cond >= 0) ? ifPos: ifNeg;
115
116
117 return ret;
118 }
119
120
121 /*!--------------------------------------------------------------------------*
122 @brief 絶対値を求めます
123
124 @param[in] x 絶対値を求める値
125
126 @return x の絶対値を返します
127 *---------------------------------------------------------------------------*/
128 inline f32
FAbs(f32 x)129 FAbs(f32 x)
130 {
131 f32 ret;
132
133 ret = ::std::fabsf(x);
134
135
136 return ret;
137 }
138
139
140 /*!--------------------------------------------------------------------------*
141 @brief 絶対値が等しく、符号が負である数を求めます
142
143 @param[in] x 元の数。
144
145 @return x と絶対値が等しく、符号が負である数を返します
146 *---------------------------------------------------------------------------*/
147 inline f32
FNAbs(f32 x)148 FNAbs(f32 x)
149 {
150 f32 ret;
151
152 ret = - FAbs(x);
153
154
155 return ret;
156 }
157
158
159 /*!--------------------------------------------------------------------------*
160 @brief 一方の数の符号を他方の数にコピーします
161
162 @param[in] abs 絶対値の元となる数。
163 @param[in] sign 符号を採用する数。
164
165 @return abs の絶対値と sign の符号を持った数を返します。
166 *---------------------------------------------------------------------------*/
167 inline f32
FCopySign(f32 abs,f32 sign)168 FCopySign(f32 abs, f32 sign)
169 {
170 f32 pos = FAbs(abs);
171 f32 neg = FNAbs(abs);
172
173 return FSelect(sign, pos, neg);
174 }
175
176 namespace internal
177 {
178 f32 FExp(f32 x);
179 f32 FLog(f32 x);
180 }
181
182
183 /*!--------------------------------------------------------------------------*
184 @brief e^x を求めます
185
186 @param[in] x 指数の値
187
188 @return e^x を返します
189 *---------------------------------------------------------------------------*/
190 inline f32
FExp(f32 x)191 FExp(f32 x)
192 {
193 return ::std::expf(x);
194
195 }
196
197
198 /*!--------------------------------------------------------------------------*
199 @brief 自然対数を求めます
200
201 @param[in] x 自然対数を求める値
202
203 @return x の自然対数を返します
204 *---------------------------------------------------------------------------*/
205 inline f32
FLog(f32 x)206 FLog(f32 x)
207 {
208 NN_MATH_WARNING(x > 0, "FLog: Input is out of the domain.");
209
210 return ::std::logf(x);
211
212 }
213
214
215 /*!--------------------------------------------------------------------------*
216 @brief 常用対数を求めます
217
218 @param[in] x 常用対数を求める値
219
220 @return x の常用対数を返します
221 *---------------------------------------------------------------------------*/
222 inline f32
FLog10(f32 x)223 FLog10(f32 x)
224 {
225 NN_MATH_WARNING(x > 0, "FLog10: Input is out of the domain.");
226
227 return ::std::log10f(x);
228 }
229
230
231 /*!--------------------------------------------------------------------------*
232 @brief 剰余を計算します
233
234 @param[in] x 割られる数
235 @param[in] y 割る数
236
237 @return x / y の剰余を返します
238 *---------------------------------------------------------------------------*/
239 inline f32
FMod(f32 x,f32 y)240 FMod(f32 x, f32 y)
241 {
242 return ::std::fmodf(x, y);
243 }
244
245
246 /*!--------------------------------------------------------------------------*
247 @brief 浮動小数点数を整数部と小数部に分けます。整数部、小数部共に x と同じ符号を持ちます。
248
249 @param[in] x 元の浮動小数点数。
250 @param[out] y 整数部を格納するバッファへのポインタ。
251
252 @return 小数部を返します
253 *---------------------------------------------------------------------------*/
254 inline f32
FModf(f32 x,f32 * y)255 FModf(f32 x, f32* y)
256 {
257 return ::std::modff(x, y);
258 }
259
260
261 /*!--------------------------------------------------------------------------*
262 @brief x を下回らない最小の整数値を求めます
263
264 @param[in] x 対象の値
265
266 @return x を下回らない最小の整数値を返します
267 *---------------------------------------------------------------------------*/
268 inline f32
FCeil(f32 x)269 FCeil(f32 x)
270 {
271 return ::std::ceilf(x);
272 }
273
274
275 /*!--------------------------------------------------------------------------*
276 @brief x を超えない最大の整数値を求めます
277
278 @param[in] x 対象の値
279
280 @return x を超えない最大の整数値を返します
281 *---------------------------------------------------------------------------*/
282 inline f32
FFloor(f32 x)283 FFloor(f32 x)
284 {
285 return ::std::floorf(x);
286 }
287
288
289 /*!--------------------------------------------------------------------------*
290 @brief f32型からs16型に変換します
291
292 @param[in] x s16型に変換する値
293
294 @return x と同じ値を持ったs16型の値を返します
295 *---------------------------------------------------------------------------*/
296 inline s16
F32ToS16(f32 x)297 F32ToS16(f32 x)
298 {
299 return s16(x);
300
301 }
302
303
304 /*!--------------------------------------------------------------------------*
305 @brief f32型からu16型に変換します
306
307 @param[in] x u16型に変換する値
308
309 @return x と同じ値を持ったu16型の値を返します
310 *---------------------------------------------------------------------------*/
311 inline u16
F32ToU16(f32 x)312 F32ToU16(f32 x)
313 {
314 return u16(x);
315
316 }
317
318
319 /*!--------------------------------------------------------------------------*
320 @brief u16型からf32型に変換します
321
322 @param[in] x f32型に変換する値
323
324 @return x と同じ値を持ったf32型の値を返します
325 *---------------------------------------------------------------------------*/
326 inline f32
U16ToF32(u16 x)327 U16ToF32(u16 x)
328 {
329 return f32(x);
330
331 }
332
333
334 /*!--------------------------------------------------------------------------*
335 @brief s16型からf32型に変換します
336
337 @param[in] x f32型に変換する値
338
339 @return x と同じ値を持ったf32型の値を返します
340 *---------------------------------------------------------------------------*/
341 inline f32
S16ToF32(s16 x)342 S16ToF32(s16 x)
343 {
344 return f32(x);
345
346 }
347
348
349
350 /*!--------------------------------------------------------------------------*
351 @brief 逆数を高速低精度に求めます
352
353 @param[in] x 逆数を求める値
354
355 @return x の逆数を返します
356 *---------------------------------------------------------------------------*/
357 inline f32
FInv(f32 x)358 FInv(f32 x)
359 {
360 f32 ix;
361
362 ix = 1.0f / x;
363
364
365 return ix;
366 }
367
368
369 /*!--------------------------------------------------------------------------*
370 @brief 平方根の逆数を求めます。
371
372 @param[in] x 平方根の逆数を求める値。
373
374 @return x の平方根の逆数を返します。
375 *---------------------------------------------------------------------------*/
376 inline f32
FrSqrt(f32 x)377 FrSqrt(f32 x)
378 {
379 NN_MATH_WARNING(x > 0, "FrSqrt: Input is out of the domain.");
380
381 return 1.f / ::std::sqrtf(x);
382 }
383
384
385 /*!--------------------------------------------------------------------------*
386 @brief 平方根を求めます
387
388 @param[in] x 平方根を求める値
389
390 @return x の平方根を返します
391 *---------------------------------------------------------------------------*/
392 inline f32
FSqrt(f32 x)393 FSqrt(f32 x)
394 {
395 NN_MATH_WARNING(x >= 0, "FSqrt: Input is out of the domain.");
396
397 return ::std::sqrtf(x);
398 }
399
400
401 /*!--------------------------------------------------------------------------*
402 @brief 立方根を求めます
403
404 @param[in] x 立方根を求める値
405
406 @return x の立方根を返します
407 *---------------------------------------------------------------------------*/
408 inline f32
FCbrt(f32 x)409 FCbrt(f32 x)
410 {
411 #if defined(NN_CW3)
412 return ::std::cbrtf(x);
413 #else
414 return ::std::pow(x, 1/3.f);
415 #endif
416 }
417
418
419 /*!--------------------------------------------------------------------------*
420 @brief エルミート補間を行います
421
422 @param[in] v0 点1での値。
423 @param[in] t0 点1での傾き。
424 @param[in] v1 点2での値。
425 @param[in] t1 点2での傾き。
426 @param[in] s 補間対象位置。(点1:0.0~1.0:点2)
427
428 @return 補間結果の値。
429 *---------------------------------------------------------------------------*/
430 inline f32
Hermite(f32 v0,f32 t0,f32 v1,f32 t1,f32 s)431 Hermite(f32 v0, f32 t0, f32 v1, f32 t1, f32 s)
432 {
433 #if defined( NN_HARDWARE_CTR )
434 #if (HERMITE_5_CONFIG == D_ORG)
435 return ARMv6::HermiteC(v0, t0, v1, t1, s);
436 #elif (HERMITE_5_CONFIG == D_FAST_C)
437 return ARMv6::HermiteC_FAST(v0, t0, v1, t1, s);
438 #elif (HERMITE_5_CONFIG == D_FAST_ASM)
439 #elif (HERMITE_5_CONFIG == D_FAST_C_ALGO)
440 #elif (HERMITE_5_CONFIG == D_FAST_ASM_ALGO)
441 #endif
442 #else
443 #endif
444 }
445
446
447 /*!--------------------------------------------------------------------------*
448 @brief エルミート補間計算です。
449
450 @param[in] v0 点1での値。
451 @param[in] t0 点1での傾き。
452 @param[in] v1 点2での値。
453 @param[in] t1 点2での傾き。
454 @param[in] p 点1から補間対象位置の距離。
455 @param[in] d 点1と点2の距離。
456
457 @return エルミート補間の結果です。
458 *---------------------------------------------------------------------------*/
459 NN_FORCE_INLINE f32
Hermite(f32 v0,f32 t0,f32 v1,f32 t1,f32 p,f32 d)460 Hermite(f32 v0, f32 t0, f32 v1, f32 t1, f32 p, f32 d)
461 {
462 #if defined( NN_HARDWARE_CTR )
463 #if (HERMITE_6_CONFIG == D_ORG)
464 return ARMv6::HermiteC(v0, t0, v1, t1, p, d);
465 #elif (HERMITE_6_CONFIG == D_FAST_C)
466 return ARMv6::HermiteC_FAST(v0, t0, v1, t1, p, d);
467 #elif (HERMITE_6_CONFIG == D_FAST_ASM)
468 return ARMv6::HermiteAsm(v0, t0, v1, t1, p, d);
469 #elif (HERMITE_6_CONFIG == D_FAST_C_ALGO)
470 #elif (HERMITE_6_CONFIG == D_FAST_ASM_ALGO)
471 #endif
472 #else
473 #endif
474 }
475
476
477 f32 Bezier(f32 p1, f32 p2, f32 p3, f32 p4, f32 s);
478 f32 CatmullRom(f32 p0, f32 p1, f32 p2, f32 p3, f32 s);
479
480 /*!
481 @}
482 */
483
484 /* =======================================================================
485 整数関連
486 ======================================================================== */
487
488 /*!
489 @name 整数に関する数学関数
490 @{
491 */
492
493 // 非インライン関数
494
495 u32 CntBit1(u32 x);
496 u32 CntBit1(const u32* first, const u32* last);
497 u32 DistBit(const u32* first1, const u32* last1, const u32* first2);
498 u32 RevBit(u32 x);
499 int IExp(int x, u32 n);
500 u32 ILog10(u32 x);
501
502 #ifndef NN_PROCESSOR_ARM
503 namespace internal
504 {
505 u32 CntLz_(u32 x);
506 }
507 #endif
508
509 /*!--------------------------------------------------------------------------*
510 @brief MSBからの連続する 0 のビットを数えます。
511
512 @param[in] x 対象のビット列
513
514 @return MSBからの連続する 0 のビット数を返します。
515 *---------------------------------------------------------------------------*/
516 inline u32
CntLz(u32 x)517 CntLz(u32 x)
518 {
519 #ifdef NN_PROCESSOR_ARM
520 return __clz(x);
521 #else
522 return internal::CntLz_(x);
523 #endif
524 }
525
526
527 /*!--------------------------------------------------------------------------*
528 @brief 整数値が2の整数乗かどうかを判定します。
529
530 @param[in] x 判定対象の整数値
531
532 @return x が 2 の累乗であれば true を、そうでなければ false を返します。
533 *---------------------------------------------------------------------------*/
534 // ただし x が 0 の場合は true を返します。
IsPwr2(int x)535 inline bool IsPwr2(int x) { return 0 == (x & (x - 1)); }
536
537 /*!--------------------------------------------------------------------------*
538 @brief 1 になっているビットで一番右(LSB側)のビットを取得します。
539
540 @param[in] x 対象とするビット列
541
542 @return x で一番右の 1 となっているビット位置のみが 1 となっているビット列を返します。
543 *---------------------------------------------------------------------------*/
Rightmost1(int x)544 inline int Rightmost1(int x) { return x & (-x); }
Rightmost1(bit32 x)545 inline bit32 Rightmost1(bit32 x) { return x & (-x); }
Rightmost1(bit64 x)546 inline bit64 Rightmost1(bit64 x) { return x & (-x); }
547
548 /*!--------------------------------------------------------------------------*
549 @brief 0 になっているビットで一番右(LSB側)のビットを取得します。
550
551 @param[in] x 対象とするビット列
552
553 @return x で一番右の 0 となっているビット位置のみが 1 となっているビット列を返します。
554 *---------------------------------------------------------------------------*/
Rightmost0(int x)555 inline int Rightmost0(int x) { return ~x & (x + 1); }
Rightmost0(bit32 x)556 inline bit32 Rightmost0(bit32 x) { return ~x & (x + 1); }
Rightmost0(bit64 x)557 inline bit64 Rightmost0(bit64 x) { return ~x & (x + 1); }
558
559 /*!--------------------------------------------------------------------------*
560 @brief ビット列同士の距離を計算します。
561
562 @param[in] x ビット列 1
563 @param[in] y ビット列 2
564
565 @return ビット列 1 とビット列 2 の距離を返します。
566 *---------------------------------------------------------------------------*/
DistBit(u32 x,u32 y)567 inline u32 DistBit(u32 x, u32 y) { return CntBit1(x ^ y); }
568
569 /*!--------------------------------------------------------------------------*
570 @brief LSBからの連続する 0 のビットを数えます。
571
572 @param[in] x 対象のビット列
573
574 @return LSBからの連続する 0 のビット数を返します。
575 *---------------------------------------------------------------------------*/
CntTz(u32 x)576 inline u32 CntTz(u32 x) { return 32 - CntLz(~x & (x - 1)); }
577
578 /*!--------------------------------------------------------------------------*
579 @brief 整数の 2 を底とする対数を計算し、結果を整数で返します。
580
581 @param[in] x 真数
582
583 @return 整数の 2 を底とする対数を整数で返します。
584 *---------------------------------------------------------------------------*/
ILog2(u32 x)585 inline u32 ILog2(u32 x) { return 31 - CntLz(x); }
586
587 /*!--------------------------------------------------------------------------*
588 @brief 与えられた整数以下の最大の 2 の累乗を計算します。
589
590 @param[in] x 対象の整数
591
592 @return x 以下の最大の2の累乗を返します。
593 *---------------------------------------------------------------------------*/
FloorPwr2(u32 x)594 inline u32 FloorPwr2(u32 x) { return 0x80000000 >> CntLz(x); }
595
596 /*!--------------------------------------------------------------------------*
597 @brief 与えられた整数以上の最小の 2 の累乗を計算します。
598
599 @param[in] x 対象の整数
600
601 @return x 以上の最小の 2 の累乗を返します。
602 *---------------------------------------------------------------------------*/
CeilPwr2(u32 x)603 inline u32 CeilPwr2(u32 x) { return 0x80000000 >> (CntLz(x - 1) - 1); }
604
605 /*!
606 @}
607 */
608
609 }} // nn::math
610
611 #pragma pop
612
613 /* NN_MATH_ARITHMETIC_H_ */
614 #endif
615