X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fsysmath.c;h=6627009eebb98644ad62238f196cb4bbb7d41e1b;hb=d500a604e1bfd87b5e3273785fb5ea3df76acc55;hp=bb8d683852e4494c3740b41fa9f28e289f5c81e6;hpb=d725fa75612e86352eabc5858ccacb7aa9d0d111;p=mono.git diff --git a/mono/metadata/sysmath.c b/mono/metadata/sysmath.c index bb8d683852e..6627009eebb 100644 --- a/mono/metadata/sysmath.c +++ b/mono/metadata/sysmath.c @@ -1,116 +1,243 @@ -/* math.c - these are based on bob smith's csharp routines */ - -#include -#include - -static const gdouble MONO_NAN = 0.0 / 0.0; -static const gdouble MONO_INF = 1.0 / 0.0; - -gdouble -ves_icall_System_Math_Sin (gdouble x) -{ - return sin (x); -} - -gdouble -ves_icall_System_Math_Cos (gdouble x) -{ - return cos (x); -} - -gdouble -ves_icall_System_Math_Tan (gdouble x) -{ - return tan (x); -} - -gdouble -ves_icall_System_Math_Sinh (gdouble x) -{ - return sinh (x); -} - -gdouble -ves_icall_System_Math_Cosh (gdouble x) -{ - return cosh (x); -} - -gdouble -ves_icall_System_Math_Tanh (gdouble x) -{ - return tanh (x); -} - -gdouble -ves_icall_System_Math_Acos (gdouble x) -{ - if (x < -1 || x > 1) - return MONO_NAN; - - return acos (x); -} - -gdouble -ves_icall_System_Math_Asin (gdouble x) -{ - if (x < -1 || x > 1) - return MONO_NAN; - - return asin (x); -} - -gdouble -ves_icall_System_Math_Atan (gdouble x) -{ - return atan (x); -} - -gdouble -ves_icall_System_Math_Atan2 (gdouble y, gdouble x) -{ - return atan2 (y, x); -} - -gdouble -ves_icall_System_Math_Exp (gdouble x) -{ - return exp (x); -} - -gdouble -ves_icall_System_Math_Log (gdouble x) -{ - if (x == 0) - return -MONO_INF; - else if (x < 0) - return MONO_NAN; - - return log (x); -} - -gdouble -ves_icall_System_Math_Log10 (gdouble x) -{ - if (x == 0) - return -MONO_INF; - else if (x < 0) - return MONO_NAN; - - return log10 (x); -} - -gdouble -ves_icall_System_Math_Pow (gdouble x, gdouble y) -{ - return pow (x, y); -} - -gdouble -ves_icall_System_Math_Sqrt (gdouble x) -{ - if (x < 0) - return MONO_NAN; - - return sqrt (x); -} +/* math.c - these are based on bob smith's csharp routines */ + +#define __USE_ISOC99 +#include +#include +#include + +#ifndef NAN +# if G_BYTE_ORDER == G_BIG_ENDIAN +# define __nan_bytes { 0x7f, 0xc0, 0, 0 } +# endif +# if G_BYTE_ORDER == G_LITTLE_ENDIAN +# define __nan_bytes { 0, 0, 0xc0, 0x7f } +# endif + +static union { unsigned char __c[4]; float __d; } __nan_union = { __nan_bytes }; +# define NAN (__nan_union.__d) +#endif + +#ifndef HUGE_VAL +#define __huge_val_t union { unsigned char __c[8]; double __d; } +# if G_BYTE_ORDER == G_BIG_ENDIAN +# define __HUGE_VAL_bytes { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } +# endif +# if G_BYTE_ORDER == G_LITTLE_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } +# endif +static __huge_val_t __huge_val = { __HUGE_VAL_bytes }; +# define HUGE_VAL (__huge_val.__d) +#endif + + +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) && + ((2.0 * ((int_part / 2.0) - floor(int_part / 2.0))) != 0.0)) || + (dec_part > 0.5)) { + int_part++; + } + return int_part; +} + +gdouble ves_icall_System_Math_Round2 (gdouble value, gint32 digits) { + double p, int_part, dec_part; + MONO_ARCH_SAVE_REGS; + 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); + dec_part = modf (value, &int_part); + dec_part *= 1000000000000000ULL; + dec_part = floor(dec_part); + dec_part /= (1000000000000000ULL / p); + dec_part = ves_icall_System_Math_Round(dec_part); + dec_part /= p; + return int_part + dec_part; +} + +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; + + return acos (x); +} + +gdouble +ves_icall_System_Math_Asin (gdouble x) +{ + MONO_ARCH_SAVE_REGS; + + if (x < -1 || x > 1) + return NAN; + + return asin (x); +} + +gdouble +ves_icall_System_Math_Atan (gdouble x) +{ + MONO_ARCH_SAVE_REGS; + + return atan (x); +} + +gdouble +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) || + (y == -HUGE_VAL && x == HUGE_VAL) || + (y == -HUGE_VAL && x == -HUGE_VAL)) { + return NAN; + } + result = atan2 (y, x); + return (result == -0)? 0: result; +} + +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) + return NAN; + + return log (x); +} + +gdouble +ves_icall_System_Math_Log10 (gdouble x) +{ + MONO_ARCH_SAVE_REGS; + + if (x == 0) + return -HUGE_VAL; + else if (x < 0) + return NAN; + + return log10 (x); +} + +gdouble +ves_icall_System_Math_Pow (gdouble x, gdouble y) +{ + double result; + MONO_ARCH_SAVE_REGS; + + if (isnan(x) || isnan(y)) { + return NAN; + } + + if ((x == 1 || x == -1) && (y == HUGE_VAL || y == -HUGE_VAL)) { + return NAN; + } + + /* This code is for return the same results as MS.NET for certain + * limit values */ + if (x < -9007199254740991.0) { + if (y > 9007199254740991.0) + return HUGE_VAL; + if (y < -9007199254740991.0) + return 0; + } + + result = pow (x, y); + + /* This code is for return the same results as MS.NET for certain + * limit values */ + if (isnan(result) && + (x == -1.0) && + ((y > 9007199254740991.0) || (y < -9007199254740991.0))) { + return 1; + } + + return (result == -0)? 0: result; +} + +gdouble +ves_icall_System_Math_Sqrt (gdouble x) +{ + MONO_ARCH_SAVE_REGS; + + if (x < 0) + return NAN; + + return sqrt (x); +}