[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mono / utils / mono-math.h
blob0f535e8ca28629e474da2e724883dc6cf6ad3073
1 /**
2 * \file
3 */
5 #ifndef __MONO_MATH_H__
6 #define __MONO_MATH_H__
8 #include <math.h>
9 #include <mono/utils/mono-publib.h>
11 // Instead of isfinite, isinf, isnan, etc.,
12 // use mono_isfininite, mono_isinf, mono_isnan, etc.
13 // These functions are implemented in C in order to avoid
14 // a C++ runtime dependency and for more portable binding
15 // from C++, esp. across Android versions/architectures.
16 // WebAssembly, and Win32/gcc.
17 // See https://github.com/mono/mono/pull/10701 for what
18 // this systematically and more portably cleans up.
20 #if defined (__cplusplus) || defined (MONO_MATH_DECLARE_ALL)
22 // These declarations are usually hidden, in order
23 // to encourage using the overloaded names instead of
24 // the type-specific names.
26 G_EXTERN_C int mono_isfinite_float (float);
27 G_EXTERN_C int mono_isfinite_double (double);
28 G_EXTERN_C int mono_isinf_float (float);
29 G_EXTERN_C int mono_isinf_double (double);
30 G_EXTERN_C int mono_isnan_float (float);
31 G_EXTERN_C int mono_isnan_double (double);
32 G_EXTERN_C int mono_isunordered_float (float, float);
33 G_EXTERN_C int mono_isunordered_double (double, double);
34 G_EXTERN_C int mono_signbit_float (float a);
35 G_EXTERN_C int mono_signbit_double (double a);
36 G_EXTERN_C float mono_trunc_float (float);
37 G_EXTERN_C double mono_trunc_double (double);
39 #endif
41 #ifdef __cplusplus
43 // There are three or four possible approaches here.
44 // 1. C++ mono_foo => foo
45 // 2. C++ mono_foo => std::foo
46 // 3. C++ mono_foo => C mono_foo_[float,double] => C foo
47 // 4. using std::foo -- this works mostly but not quite -- it doesn't
48 // work when there is already a global foo.
50 // Approach 1 works on non-wasm, non-android non-Win32/gcc.
51 // Approach 2 should work everywhere, but might incur a new dependency, might.
52 // Approach 3 should work everywhere, with identical dependencies as mono/C.
53 // This is approach 3.
54 // Approach 4 lets code keep calling foo instead of mono_foo.
55 // Approaches 1, 2, 4 are most efficient. 1, 2 require inlining, 4 does not.
57 inline int mono_isfinite (float a) { return mono_isfinite_float (a); }
58 inline int mono_isfinite (double a) { return mono_isfinite_double (a); }
59 inline int mono_isinf (float a) { return mono_isinf_float (a); }
60 inline int mono_isinf (double a) { return mono_isinf_double (a); }
61 inline int mono_isnan (float a) { return mono_isnan_float (a); }
62 inline int mono_isnan (double a) { return mono_isnan_double (a); }
63 inline int mono_isunordered (float a, float b) { return mono_isunordered_float (a, b); }
64 inline int mono_isunordered (double a, double b) { return mono_isunordered_double (a, b); }
65 inline int mono_signbit (float a) { return mono_signbit_float (a); }
66 inline int mono_signbit (double a) { return mono_signbit_double (a); }
67 inline float mono_trunc (float a) { return mono_trunc_float (a); }
68 inline double mono_trunc (double a) { return mono_trunc_double (a); }
70 #else
72 // Direct macros for C.
73 // This will also work for many C++ platforms, i.e. other than Android and WebAssembly and Win32/gcc.
74 #define mono_isfinite isfinite
75 #define mono_isinf isinf
76 #define mono_isnan isnan
77 #define mono_isunordered isunordered
78 #define mono_signbit signbit
79 #define mono_trunc trunc
81 #endif
83 static inline double
84 mono_round_to_even (double x)
86 double floor_tmp;
88 /* If the number has no fractional part do nothing This shortcut is necessary
89 * to workaround precision loss in borderline cases on some platforms */
90 if (x == (double)(int64_t) x)
91 return x;
93 floor_tmp = floor (x + 0.5);
95 if ((x == (floor (x) + 0.5)) && (fmod (floor_tmp, 2.0) != 0)) {
96 floor_tmp -= 1.0;
99 return copysign (floor_tmp, x);
102 #endif