Merge pull request #238 from neoflex/patch-1
[vuplus_xbmc] / xbmc / utils / MathUtils.h
1 #pragma once
2 /*
3  *      Copyright (C) 2005-2008 Team XBMC
4  *      http://www.xbmc.org
5  *
6  *  This Program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2, or (at your option)
9  *  any later version.
10  *
11  *  This Program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with XBMC; see the file COPYING.  If not, write to
18  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19  *  http://www.gnu.org/copyleft/gpl.html
20  *
21  */
22
23 #include <stdint.h>
24 #include <cassert>
25 #include <climits>
26 #include <cmath>
27
28 namespace MathUtils
29 {
30   // GCC does something stupid with optimization on release builds if we try
31   // to assert in these functions
32   inline int round_int (double x)
33   {
34     assert(x > static_cast<double>(INT_MIN / 2) - 1.0);
35     assert(x < static_cast <double>(INT_MAX / 2) + 1.0);
36     const float round_to_nearest = 0.5f;
37     int i;
38
39 #ifndef _LINUX
40     __asm
41     {
42       fld x
43       fadd st, st (0)
44       fadd round_to_nearest
45       fistp i
46       sar i, 1
47     }
48 #else
49 #if defined(__powerpc__) || defined(__ppc__)
50     i = floor(x + round_to_nearest);
51 #elif defined(__arm__)
52     __asm__ __volatile__ (
53                           "vmov.F64 d1,%[rnd_val]             \n\t" // Copy round_to_nearest into a working register
54                           "vadd.F64 %P[value],%P[value],d1    \n\t" // Add round_to_nearest to value
55                           "vcvt.S32.F64 %[result],%P[value]   \n\t" // Truncate(round towards zero) and store the result
56                           : [result] "=w"(i), [value] "+w"(x)  // Outputs
57                           : [rnd_val] "Dv" (round_to_nearest)  // Inputs
58                           : "d1");                             // Clobbers
59 #else
60     __asm__ __volatile__ (
61                           "fadd %%st\n\t"
62                           "fadd %%st(1)\n\t"
63                           "fistpl %0\n\t"
64                           "sarl $1, %0\n"
65                           : "=m"(i) : "u"(round_to_nearest), "t"(x) : "st"
66                           );
67 #endif
68 #endif
69     return (i);
70   }
71
72   inline int truncate_int(double x)
73   {
74     assert(x > static_cast<double>(INT_MIN / 2) - 1.0);
75     assert(x < static_cast <double>(INT_MAX / 2) + 1.0);
76
77 #if !defined(__powerpc__) && !defined(__ppc__) && !defined(__arm__)
78     const float round_towards_m_i = -0.5f;
79 #endif
80     int i;
81
82 #ifndef _LINUX
83     __asm
84     {
85       fld x
86       fadd st, st (0)
87       fabs
88       fadd round_towards_m_i
89       fistp i
90       sar i, 1
91     }
92 #else
93 #if defined(__powerpc__) || defined(__ppc__) || defined(__arm__)
94     return (int)x;
95 #else
96     __asm__ __volatile__ (
97                           "fadd %%st\n\t"
98                           "fabs\n\t"
99                           "fadd %%st(1)\n\t"
100                           "fistpl %0\n\t"
101                           "sarl $1, %0\n"
102                           : "=m"(i) : "u"(round_towards_m_i), "t"(x) : "st"
103                           );
104 #endif
105 #endif
106     if (x < 0)
107       i = -i;
108     return (i);
109   }
110
111   inline int64_t abs(int64_t a)
112   {
113     return (a < 0) ? -a : a;
114   }
115
116   inline void hack()
117   {
118     // stupid hack to keep compiler from dropping these
119     // functions as unused
120     MathUtils::round_int(0.0);
121     MathUtils::truncate_int(0.0);
122     MathUtils::abs(0);
123   }
124 } // namespace MathUtils
125