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         Arithmetic functions related to floating-point numbers
35    ======================================================================== */
36 
37 /* Please see man pages for details
38 
39 
40 */
41 
42 // u32 F32AsU32(f32 x)
43 //
44 // Description: Converts an f32 type value into a u32 type without changing the bit array.
45 // Arguments: x: The value to convert to a u32 type.
46 // Return value: A u32-type value that has a bit expression equivalent to x.
47 inline u32
F32AsU32(f32 x)48 F32AsU32(f32 x)
49 {
50     return *reinterpret_cast<u32*>(&x);
51 }
52 
53 
54 
55 /*
56 
57 
58 
59 
60 
61  */
62 inline f32
U32AsF32(u32 x)63 U32AsF32(u32 x)
64 {
65     return *reinterpret_cast<f32*>(&x);
66 }
67 
68 
69 /*
70 
71 
72 
73 
74 
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 
86 
87 
88 
89 
90  */
91 inline f32
FGetMantPart(f32 f)92 FGetMantPart(f32 f)
93 {
94     // Sets the exponent portion to 127
95     u32 u = (F32AsU32(f) & 0x807FFFFF) | 0x3F800000;
96     return U32AsF32(u);
97 }
98 
99 
100 /*
101 
102 
103 
104 
105 
106 
107 
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 
123 
124 
125 
126 
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 
142 
143 
144 
145 
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 
161 
162 
163 
164 
165 
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 
185 
186 
187 
188 
189  */
190 inline f32
FExp(f32 x)191 FExp(f32 x)
192 {
193     return ::std::expf(x);
194 
195 }
196 
197 
198 /*
199 
200 
201 
202 
203 
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 
217 
218 
219 
220 
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 
233 
234 
235 
236 
237 
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 
248 
249 
250 
251 
252 
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 
263 
264 
265 
266 
267  */
268 inline f32
FCeil(f32 x)269 FCeil(f32 x)
270 {
271     return ::std::ceilf(x);
272 }
273 
274 
275 /*
276 
277 
278 
279 
280 
281  */
282 inline f32
FFloor(f32 x)283 FFloor(f32 x)
284 {
285     return ::std::floorf(x);
286 }
287 
288 
289 /*
290 
291 
292 
293 
294 
295  */
296 inline s16
F32ToS16(f32 x)297 F32ToS16(f32 x)
298 {
299     return s16(x);
300 
301 }
302 
303 
304 /*
305 
306 
307 
308 
309 
310  */
311 inline u16
F32ToU16(f32 x)312 F32ToU16(f32 x)
313 {
314     return u16(x);
315 
316 }
317 
318 
319 /*
320 
321 
322 
323 
324 
325  */
326 inline f32
U16ToF32(u16 x)327 U16ToF32(u16 x)
328 {
329     return f32(x);
330 
331 }
332 
333 
334 /*
335 
336 
337 
338 
339 
340  */
341 inline f32
S16ToF32(s16 x)342 S16ToF32(s16 x)
343 {
344     return f32(x);
345 
346 }
347 
348 
349 
350 /*
351 
352 
353 
354 
355 
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 
371 
372 
373 
374 
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 
387 
388 
389 
390 
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 
403 
404 
405 
406 
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 
421 
422 
423 
424 
425 
426 
427 
428 
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 
449 
450 
451 
452 
453 
454 
455 
456 
457 
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         Integer-related
486    ======================================================================== */
487 
488 /* Please see man pages for details
489 
490 
491 */
492 
493 // Non-Inline Functions
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 
511 
512 
513 
514 
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 
529 
530 
531 
532 
533  */
534 //          However, the function returns TRUE if x is 0.
IsPwr2(int x)535 inline bool IsPwr2(int x) { return 0 == (x & (x - 1)); }
536 
537 /*
538 
539 
540 
541 
542 
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 
550 
551 
552 
553 
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 
561 
562 
563 
564 
565 
566  */
DistBit(u32 x,u32 y)567 inline u32 DistBit(u32 x, u32 y) { return CntBit1(x ^ y); }
568 
569 /*
570 
571 
572 
573 
574 
575  */
CntTz(u32 x)576 inline u32 CntTz(u32 x) { return 32 - CntLz(~x & (x - 1)); }
577 
578 /*
579 
580 
581 
582 
583 
584  */
ILog2(u32 x)585 inline u32 ILog2(u32 x) { return 31 - CntLz(x); }
586 
587 /*
588 
589 
590 
591 
592 
593  */
FloorPwr2(u32 x)594 inline u32 FloorPwr2(u32 x) { return 0x80000000 >> CntLz(x); }
595 
596 /*
597 
598 
599 
600 
601 
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