1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: math_Arithmetic.h
4
5 Copyright (C)2009-2012 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: 48334 $
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 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); }
545 /*
546
547
548
549
550
551 */
Rightmost1(bit32 x)552 inline bit32 Rightmost1(bit32 x) { return x & (-x); }
553 /*
554
555
556
557
558
559 */
Rightmost1(bit64 x)560 inline bit64 Rightmost1(bit64 x) { return x & (-x); }
561
562 /*
563
564
565
566
567
568 */
Rightmost0(int x)569 inline int Rightmost0(int x) { return ~x & (x + 1); }
570 /*
571
572
573
574
575
576 */
Rightmost0(bit32 x)577 inline bit32 Rightmost0(bit32 x) { return ~x & (x + 1); }
578 /*
579
580
581
582
583
584 */
Rightmost0(bit64 x)585 inline bit64 Rightmost0(bit64 x) { return ~x & (x + 1); }
586
587 /*
588
589
590
591
592
593
594 */
DistBit(u32 x,u32 y)595 inline u32 DistBit(u32 x, u32 y) { return CntBit1(x ^ y); }
596
597 /*
598
599
600
601
602
603 */
CntTz(u32 x)604 inline u32 CntTz(u32 x) { return 32 - CntLz(~x & (x - 1)); }
605
606 /*
607
608
609
610
611
612 */
ILog2(u32 x)613 inline u32 ILog2(u32 x) { return 31 - CntLz(x); }
614
615 /*
616
617
618
619
620
621 */
FloorPwr2(u32 x)622 inline u32 FloorPwr2(u32 x) { return 0x80000000 >> CntLz(x); }
623
624 /*
625
626
627
628
629
630 */
CeilPwr2(u32 x)631 inline u32 CeilPwr2(u32 x) { return 0x80000000 >> (CntLz(x - 1) - 1); }
632
633 /*
634
635 */
636
637 }} // nn::math
638
639 #pragma pop
640
641 /* NN_MATH_ARITHMETIC_H_ */
642 #endif
643