/* math.c - these are based on bob smith's csharp routines */\r
\r
+#define __USE_ISOC99\r
#include <math.h>\r
#include <mono/metadata/sysmath.h>\r
+#include <mono/metadata/exception.h>\r
+\r
+#ifndef NAN\r
+# if G_BYTE_ORDER == G_BIG_ENDIAN\r
+# define __nan_bytes { 0x7f, 0xc0, 0, 0 }\r
+# endif\r
+# if G_BYTE_ORDER == G_LITTLE_ENDIAN\r
+# define __nan_bytes { 0, 0, 0xc0, 0x7f }\r
+# endif\r
+\r
+static union { unsigned char __c[4]; float __d; } __nan_union = { __nan_bytes };\r
+# define NAN (__nan_union.__d)\r
+#endif\r
+\r
+#ifndef HUGE_VAL\r
+#define __huge_val_t union { unsigned char __c[8]; double __d; }\r
+# if G_BYTE_ORDER == G_BIG_ENDIAN\r
+# define __HUGE_VAL_bytes { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }\r
+# endif\r
+# if G_BYTE_ORDER == G_LITTLE_ENDIAN\r
+# define __HUGE_VAL_bytes { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }\r
+# endif\r
+static __huge_val_t __huge_val = { __HUGE_VAL_bytes };\r
+# define HUGE_VAL (__huge_val.__d)\r
+#endif\r
+\r
+\r
+gdouble ves_icall_System_Math_Floor (gdouble x) {\r
+ MONO_ARCH_SAVE_REGS;\r
+ return floor(x);\r
+}\r
+\r
+gdouble ves_icall_System_Math_Round (gdouble x) {\r
+ double int_part, dec_part;\r
+ MONO_ARCH_SAVE_REGS;\r
+ int_part = floor(x);\r
+ dec_part = x - int_part;\r
+ if (((dec_part == 0.5) &&\r
+ ((2.0 * ((int_part / 2.0) - floor(int_part / 2.0))) != 0.0)) ||\r
+ (dec_part > 0.5)) {\r
+ int_part++;\r
+ }\r
+ return int_part;\r
+}\r
\r
-static const gdouble MONO_NAN = 0.0 / 0.0;\r
-static const gdouble MONO_INF = 1.0 / 0.0;\r
+gdouble ves_icall_System_Math_Round2 (gdouble value, gint32 digits) {\r
+ double p, int_part, dec_part;\r
+ MONO_ARCH_SAVE_REGS;\r
+ if (value == HUGE_VAL)\r
+ return HUGE_VAL;\r
+ if (value == -HUGE_VAL)\r
+ return -HUGE_VAL;\r
+ if (digits == 0)\r
+ return ves_icall_System_Math_Round(value);\r
+ p = pow(10, digits);\r
+ int_part = floor(value);\r
+ dec_part = value - int_part;\r
+ dec_part *= 1000000000000000;\r
+ dec_part = floor(dec_part);\r
+ dec_part /= (1000000000000000 / p);\r
+ dec_part = ves_icall_System_Math_Round(dec_part);\r
+ dec_part /= p;\r
+ return int_part + dec_part;\r
+}\r
\r
gdouble \r
ves_icall_System_Math_Sin (gdouble x)\r
{\r
+ MONO_ARCH_SAVE_REGS;\r
+\r
return sin (x);\r
}\r
\r
gdouble \r
ves_icall_System_Math_Cos (gdouble x)\r
{\r
+ MONO_ARCH_SAVE_REGS;\r
+\r
return cos (x);\r
}\r
\r
gdouble \r
ves_icall_System_Math_Tan (gdouble x)\r
{\r
+ MONO_ARCH_SAVE_REGS;\r
+\r
return tan (x);\r
}\r
\r
gdouble \r
ves_icall_System_Math_Sinh (gdouble x)\r
{\r
+ MONO_ARCH_SAVE_REGS;\r
+\r
return sinh (x);\r
}\r
\r
gdouble \r
ves_icall_System_Math_Cosh (gdouble x)\r
{\r
+ MONO_ARCH_SAVE_REGS;\r
+\r
return cosh (x);\r
}\r
\r
gdouble \r
ves_icall_System_Math_Tanh (gdouble x)\r
{\r
+ MONO_ARCH_SAVE_REGS;\r
+\r
return tanh (x);\r
}\r
\r
gdouble \r
ves_icall_System_Math_Acos (gdouble x)\r
{\r
+ MONO_ARCH_SAVE_REGS;\r
+\r
if (x < -1 || x > 1)\r
- return MONO_NAN;\r
+ return NAN;\r
\r
return acos (x);\r
}\r
gdouble \r
ves_icall_System_Math_Asin (gdouble x)\r
{\r
+ MONO_ARCH_SAVE_REGS;\r
+\r
if (x < -1 || x > 1)\r
- return MONO_NAN;\r
+ return NAN;\r
\r
- return acos (x);\r
+ return asin (x);\r
}\r
\r
gdouble \r
ves_icall_System_Math_Atan (gdouble x)\r
{\r
+ MONO_ARCH_SAVE_REGS;\r
+\r
return atan (x);\r
}\r
\r
gdouble \r
ves_icall_System_Math_Atan2 (gdouble y, gdouble x)\r
{\r
- return atan2 (y, x);\r
+ double result;\r
+ MONO_ARCH_SAVE_REGS;\r
+\r
+ if ((y == HUGE_VAL && x == HUGE_VAL) ||\r
+ (y == HUGE_VAL && x == -HUGE_VAL) ||\r
+ (y == -HUGE_VAL && x == HUGE_VAL) ||\r
+ (y == -HUGE_VAL && x == -HUGE_VAL)) {\r
+ return NAN;\r
+ }\r
+ result = atan2 (y, x);\r
+ return (result == -0)? 0: result;\r
}\r
\r
gdouble \r
ves_icall_System_Math_Exp (gdouble x)\r
{\r
+ MONO_ARCH_SAVE_REGS;\r
+\r
return exp (x);\r
}\r
\r
gdouble \r
ves_icall_System_Math_Log (gdouble x)\r
{\r
+ MONO_ARCH_SAVE_REGS;\r
+\r
if (x == 0)\r
- return -MONO_INF;\r
+ return -HUGE_VAL;\r
else if (x < 0)\r
- return MONO_NAN;\r
+ return NAN;\r
\r
return log (x);\r
}\r
gdouble \r
ves_icall_System_Math_Log10 (gdouble x)\r
{\r
+ MONO_ARCH_SAVE_REGS;\r
+\r
if (x == 0)\r
- return -MONO_INF;\r
+ return -HUGE_VAL;\r
else if (x < 0)\r
- return MONO_NAN;\r
+ return NAN;\r
\r
return log10 (x);\r
}\r
gdouble \r
ves_icall_System_Math_Pow (gdouble x, gdouble y)\r
{\r
- return pow (x, y);\r
+ double result;\r
+ MONO_ARCH_SAVE_REGS;\r
+\r
+ if (isnan(x) || isnan(y)) {\r
+ return NAN;\r
+ }\r
+\r
+ if ((x == 1 || x == -1) && (y == HUGE_VAL || y == -HUGE_VAL)) {\r
+ return NAN;\r
+ }\r
+\r
+ /* This code is for return the same results as MS.NET for certain\r
+ * limit values */\r
+ if (x < -9007199254740991.0) {\r
+ if (y > 9007199254740991.0)\r
+ return HUGE_VAL;\r
+ if (y < -9007199254740991.0)\r
+ return 0;\r
+ }\r
+\r
+ result = pow (x, y);\r
+\r
+ /* This code is for return the same results as MS.NET for certain\r
+ * limit values */\r
+ if (isnan(result) &&\r
+ (x == -1.0) &&\r
+ ((y > 9007199254740991.0) || (y < -9007199254740991.0))) {\r
+ return 1;\r
+ }\r
+\r
+ return (result == -0)? 0: result;\r
}\r
\r
gdouble \r
ves_icall_System_Math_Sqrt (gdouble x)\r
{\r
+ MONO_ARCH_SAVE_REGS;\r
+\r
if (x < 0)\r
return NAN;\r
\r