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) {
44 gdouble ves_icall_System_Math_Round (gdouble x) {
45 double int_part, dec_part;
48 dec_part = x - int_part;
49 if (((dec_part == 0.5) &&
50 ((2.0 * ((int_part / 2.0) - floor(int_part / 2.0))) != 0.0)) ||
57 gdouble ves_icall_System_Math_Round2 (gdouble value, gint32 digits, gboolean away_from_zero) {
58 #if !defined (HAVE_ROUND) || !defined (HAVE_RINT)
59 double int_part, dec_part;
63 if (value == HUGE_VAL)
65 if (value == -HUGE_VAL)
68 #if defined (HAVE_ROUND) && defined (HAVE_RINT)
70 return round (value * p) / p;
72 return rint (value * p) / p;
74 dec_part = modf (value, &int_part);
75 dec_part *= 1000000000000000ULL;
76 if (away_from_zero && dec_part > 0)
77 dec_part = ceil (dec_part);
79 dec_part = floor (dec_part);
80 dec_part /= (1000000000000000ULL / p);
83 dec_part = floor (dec_part + 0.5);
85 dec_part = ceil (dec_part - 0.5);
87 dec_part = ves_icall_System_Math_Round (dec_part);
89 return ves_icall_System_Math_Round ((int_part + dec_part) * p) / p;
94 ves_icall_System_Math_Sin (gdouble x)
100 ves_icall_System_Math_Cos (gdouble x)
106 ves_icall_System_Math_Tan (gdouble x)
112 ves_icall_System_Math_Sinh (gdouble x)
118 ves_icall_System_Math_Cosh (gdouble x)
124 ves_icall_System_Math_Tanh (gdouble x)
130 ves_icall_System_Math_Acos (gdouble x)
139 ves_icall_System_Math_Asin (gdouble x)
148 ves_icall_System_Math_Atan (gdouble x)
154 ves_icall_System_Math_Atan2 (gdouble y, gdouble x)
158 if ((y == HUGE_VAL && x == HUGE_VAL) ||
159 (y == HUGE_VAL && x == -HUGE_VAL) ||
160 (y == -HUGE_VAL && x == HUGE_VAL) ||
161 (y == -HUGE_VAL && x == -HUGE_VAL)) {
164 result = atan2 (y, x);
165 return (result == -0)? 0: result;
169 ves_icall_System_Math_Exp (gdouble x)
175 ves_icall_System_Math_Log (gdouble x)
186 ves_icall_System_Math_Log10 (gdouble x)
197 ves_icall_System_Math_Pow (gdouble x, gdouble y)
201 if (isnan(x) || isnan(y)) {
205 if ((x == 1 || x == -1) && (y == HUGE_VAL || y == -HUGE_VAL)) {
209 /* This code is for return the same results as MS.NET for certain
211 if (x < -9007199254740991.0) {
212 if (y > 9007199254740991.0)
214 if (y < -9007199254740991.0)
220 /* This code is for return the same results as MS.NET for certain
224 ((y > 9007199254740991.0) || (y < -9007199254740991.0))) {
228 return (result == -0)? 0: result;
232 ves_icall_System_Math_Sqrt (gdouble x)