-/* math.c - these are based on bob smith's csharp routines */
-
+/*
+ * sysmath.c: these are based on bob smith's csharp routines
+ *
+ * Author:
+ * Mono Project (http://www.mono-project.com)
+ *
+ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+ * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ */
#define __USE_ISOC99
#include <math.h>
#include <mono/metadata/sysmath.h>
gdouble ves_icall_System_Math_Floor (gdouble x) {
- MONO_ARCH_SAVE_REGS;
return floor(x);
}
gdouble ves_icall_System_Math_Round (gdouble x) {
double int_part, dec_part;
- MONO_ARCH_SAVE_REGS;
+
int_part = floor(x);
dec_part = x - int_part;
if (((dec_part == 0.5) &&
return int_part;
}
-gdouble ves_icall_System_Math_Round2 (gdouble value, gint32 digits) {
- double p, int_part, dec_part;
- MONO_ARCH_SAVE_REGS;
+gdouble ves_icall_System_Math_Round2 (gdouble value, gint32 digits, gboolean away_from_zero) {
+#if !defined (HAVE_ROUND) || !defined (HAVE_RINT)
+ double int_part, dec_part;
+#endif
+ double p;
+
if (value == HUGE_VAL)
return HUGE_VAL;
if (value == -HUGE_VAL)
return -HUGE_VAL;
- if (digits == 0)
- return ves_icall_System_Math_Round(value);
p = pow(10, digits);
+#if defined (HAVE_ROUND) && defined (HAVE_RINT)
+ if (away_from_zero)
+ return round (value * p) / p;
+ else
+ return rint (value * p) / p;
+#else
dec_part = modf (value, &int_part);
dec_part *= 1000000000000000ULL;
- dec_part = floor(dec_part);
+ if (away_from_zero && dec_part > 0)
+ dec_part = ceil (dec_part);
+ else
+ dec_part = floor (dec_part);
dec_part /= (1000000000000000ULL / p);
- dec_part = ves_icall_System_Math_Round(dec_part);
+ if (away_from_zero) {
+ if (dec_part > 0)
+ dec_part = floor (dec_part + 0.5);
+ else
+ dec_part = ceil (dec_part - 0.5);
+ } else
+ dec_part = ves_icall_System_Math_Round (dec_part);
dec_part /= p;
- return int_part + dec_part;
+ return ves_icall_System_Math_Round ((int_part + dec_part) * p) / p;
+#endif
}
gdouble
ves_icall_System_Math_Sin (gdouble x)
{
- MONO_ARCH_SAVE_REGS;
-
return sin (x);
}
gdouble
ves_icall_System_Math_Cos (gdouble x)
{
- MONO_ARCH_SAVE_REGS;
-
return cos (x);
}
gdouble
ves_icall_System_Math_Tan (gdouble x)
{
- MONO_ARCH_SAVE_REGS;
-
return tan (x);
}
gdouble
ves_icall_System_Math_Sinh (gdouble x)
{
- MONO_ARCH_SAVE_REGS;
-
return sinh (x);
}
gdouble
ves_icall_System_Math_Cosh (gdouble x)
{
- MONO_ARCH_SAVE_REGS;
-
return cosh (x);
}
gdouble
ves_icall_System_Math_Tanh (gdouble x)
{
- MONO_ARCH_SAVE_REGS;
-
return tanh (x);
}
gdouble
ves_icall_System_Math_Acos (gdouble x)
{
- MONO_ARCH_SAVE_REGS;
-
if (x < -1 || x > 1)
return NAN;
gdouble
ves_icall_System_Math_Asin (gdouble x)
{
- MONO_ARCH_SAVE_REGS;
-
if (x < -1 || x > 1)
return NAN;
gdouble
ves_icall_System_Math_Atan (gdouble x)
{
- MONO_ARCH_SAVE_REGS;
-
return atan (x);
}
ves_icall_System_Math_Atan2 (gdouble y, gdouble x)
{
double result;
- MONO_ARCH_SAVE_REGS;
if ((y == HUGE_VAL && x == HUGE_VAL) ||
(y == HUGE_VAL && x == -HUGE_VAL) ||
gdouble
ves_icall_System_Math_Exp (gdouble x)
{
- MONO_ARCH_SAVE_REGS;
-
return exp (x);
}
gdouble
ves_icall_System_Math_Log (gdouble x)
{
- MONO_ARCH_SAVE_REGS;
-
if (x == 0)
return -HUGE_VAL;
else if (x < 0)
gdouble
ves_icall_System_Math_Log10 (gdouble x)
{
- MONO_ARCH_SAVE_REGS;
-
if (x == 0)
return -HUGE_VAL;
else if (x < 0)
ves_icall_System_Math_Pow (gdouble x, gdouble y)
{
double result;
- MONO_ARCH_SAVE_REGS;
if (isnan(x) || isnan(y)) {
return NAN;
gdouble
ves_icall_System_Math_Sqrt (gdouble x)
{
- MONO_ARCH_SAVE_REGS;
-
if (x < 0)
return NAN;