2 * sysmath.c: these are based on bob smith's csharp routines
5 * Mono Project (http://www.mono-project.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 #include <mono/metadata/sysmath.h>
13 #include <mono/metadata/exception.h>
16 # if G_BYTE_ORDER == G_BIG_ENDIAN
17 # define __nan_bytes { 0x7f, 0xc0, 0, 0 }
19 # if G_BYTE_ORDER == G_LITTLE_ENDIAN
20 # define __nan_bytes { 0, 0, 0xc0, 0x7f }
23 static union { unsigned char __c
[4]; float __d
; } __nan_union
= { __nan_bytes
};
24 # define NAN (__nan_union.__d)
28 #define __huge_val_t union { unsigned char __c[8]; double __d; }
29 # if G_BYTE_ORDER == G_BIG_ENDIAN
30 # define __HUGE_VAL_bytes { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }
32 # if G_BYTE_ORDER == G_LITTLE_ENDIAN
33 # define __HUGE_VAL_bytes { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }
35 static __huge_val_t __huge_val
= { __HUGE_VAL_bytes
};
36 # define HUGE_VAL (__huge_val.__d)
40 gdouble
ves_icall_System_Math_Floor (gdouble x
) {
45 gdouble
ves_icall_System_Math_Round (gdouble x
) {
46 double int_part
, dec_part
;
49 dec_part
= x
- int_part
;
50 if (((dec_part
== 0.5) &&
51 ((2.0 * ((int_part
/ 2.0) - floor(int_part
/ 2.0))) != 0.0)) ||
58 gdouble
ves_icall_System_Math_Round2 (gdouble value
, gint32 digits
, gboolean away_from_zero
) {
59 #if !defined (HAVE_ROUND) || !defined (HAVE_RINT)
60 double int_part
, dec_part
;
65 if (value
== HUGE_VAL
)
67 if (value
== -HUGE_VAL
)
70 #if defined (HAVE_ROUND) && defined (HAVE_RINT)
72 return round (value
* p
) / p
;
74 return rint (value
* p
) / p
;
76 dec_part
= modf (value
, &int_part
);
77 dec_part
*= 1000000000000000ULL;
78 if (away_from_zero
&& dec_part
> 0)
79 dec_part
= ceil (dec_part
);
81 dec_part
= floor (dec_part
);
82 dec_part
/= (1000000000000000ULL / p
);
85 dec_part
= floor (dec_part
+ 0.5);
87 dec_part
= ceil (dec_part
- 0.5);
89 dec_part
= ves_icall_System_Math_Round (dec_part
);
91 return ves_icall_System_Math_Round ((int_part
+ dec_part
) * p
) / p
;
96 ves_icall_System_Math_Sin (gdouble x
)
104 ves_icall_System_Math_Cos (gdouble x
)
112 ves_icall_System_Math_Tan (gdouble x
)
120 ves_icall_System_Math_Sinh (gdouble x
)
128 ves_icall_System_Math_Cosh (gdouble x
)
136 ves_icall_System_Math_Tanh (gdouble x
)
144 ves_icall_System_Math_Acos (gdouble x
)
155 ves_icall_System_Math_Asin (gdouble x
)
166 ves_icall_System_Math_Atan (gdouble x
)
174 ves_icall_System_Math_Atan2 (gdouble y
, gdouble x
)
179 if ((y
== HUGE_VAL
&& x
== HUGE_VAL
) ||
180 (y
== HUGE_VAL
&& x
== -HUGE_VAL
) ||
181 (y
== -HUGE_VAL
&& x
== HUGE_VAL
) ||
182 (y
== -HUGE_VAL
&& x
== -HUGE_VAL
)) {
185 result
= atan2 (y
, x
);
186 return (result
== -0)? 0: result
;
190 ves_icall_System_Math_Exp (gdouble x
)
198 ves_icall_System_Math_Log (gdouble x
)
211 ves_icall_System_Math_Log10 (gdouble x
)
224 ves_icall_System_Math_Pow (gdouble x
, gdouble y
)
229 if (isnan(x
) || isnan(y
)) {
233 if ((x
== 1 || x
== -1) && (y
== HUGE_VAL
|| y
== -HUGE_VAL
)) {
237 /* This code is for return the same results as MS.NET for certain
239 if (x
< -9007199254740991.0) {
240 if (y
> 9007199254740991.0)
242 if (y
< -9007199254740991.0)
248 /* This code is for return the same results as MS.NET for certain
252 ((y
> 9007199254740991.0) || (y
< -9007199254740991.0))) {
256 return (result
== -0)? 0: result
;
260 ves_icall_System_Math_Sqrt (gdouble x
)