From c957d5769a919c27ebbda67daf3851f7f4769a80 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Fri, 29 Aug 2008 02:11:53 +0200 Subject: msvcrt: Don't depend on the system's implementation of acos() & asin() glibc implements acos() as the FPU equivalent of atan2(sqrt(1 - x ^ 2), x). asin() uses a similar construction. This is bad because as x gets nearer to 1 the error in the expression "1 - x^2" can get relatively large due to cancellation. The sqrt() makes things worse. A safer way to calculate acos() is to use atan2(sqrt((1 - x) * (1 + x)), x). This should be fixed on the glibc side as well, but for Wine it's probably a good idea not to rely on the acos() and asin() implementations of the underlying platform. This patch fixes a "CRCMismatch" issue in C&C Generals between Windows and Wine hosts. diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index b449af5..7ac9ee7 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -57,7 +57,7 @@ static MSVCRT_matherr_func MSVCRT_default_matherr_func = NULL; double CDECL MSVCRT_acos( double x ) { if (x < -1.0 || x > 1.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM; - return acos(x); + return atan2(sqrt((1 - x) * (1 + x)), x); } /********************************************************************* @@ -66,7 +66,7 @@ double CDECL MSVCRT_acos( double x ) double CDECL MSVCRT_asin( double x ) { if (x < -1.0 || x > 1.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM; - return asin(x); + return atan2(x, sqrt((1 - x) * (1 + x))); } /********************************************************************* -- 1.5.6.4