| #include <math.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #define WIN32_LEAN_AND_MEAN | |
| #include <windows.h> | |
| /* mingw-w64 headers */ | |
| #include "libtest.h" | |
| #ifndef __MSVCRT_VERSION__ | |
| #define __MSVCRT_VERSION__ 0x0000 | |
| #endif | |
| #if defined(_UCRT) || __MSVCRT_VERSION__ >= 0x0E00 | |
| #define CRT_FILENAME "ucrtbase.dll" | |
| #elif __MSVCRT_VERSION__ >= 0x0C00 | |
| #define CRT_FILENAME "msvcr120.dll" | |
| #elif __MSVCRT_VERSION__ >= 0x0B00 | |
| #define CRT_FILENAME "msvcr110.dll" | |
| #elif __MSVCRT_VERSION__ >= 0x0A00 | |
| #define CRT_FILENAME "msvcr100.dll" | |
| #elif __MSVCRT_VERSION__ >= 0x0900 | |
| #define CRT_FILENAME "msvcr90.dll" | |
| #elif __MSVCRT_VERSION__ >= 0x0800 | |
| #define CRT_FILENAME "msvcr80.dll" | |
| #elif __MSVCRT_VERSION__ >= 0x0710 | |
| #define CRT_FILENAME "msvcr71.dll" | |
| #elif __MSVCRT_VERSION__ >= 0x0700 | |
| #define CRT_FILENAME "msvcr70.dll" | |
| #elif __MSVCRT_VERSION__ >= 0x0410 | |
| #define CRT_FILENAME "msvcrt.dll" | |
| #elif __MSVCRT_VERSION__ >= 0x0400 | |
| #define CRT_FILENAME "msvcrt40.dll" | |
| #elif __MSVCRT_VERSION__ >= 0x0200 | |
| #define CRT_FILENAME "msvcrt20.dll" | |
| #elif __MSVCRT_VERSION__ >= 0x0100 | |
| #define CRT_FILENAME "msvcrt10.dll" | |
| #else | |
| #define CRT_FILENAME "crtdll.dll" | |
| #endif | |
| /* All CRT functions have __cdecl calling convention */ | |
| typedef double (__cdecl *my_pow)(double, double); | |
| /* The `pow` implementation to test */ | |
| static my_pow fpow = pow; | |
| /* Set `fpow` to CRT's `pow` */ | |
| static void set_pow_crt(void) | |
| { | |
| my_pow ptr_pow = NULL; | |
| HMODULE hMod = GetModuleHandleA (CRT_FILENAME); | |
| if (hMod != NULL) { | |
| ptr_pow = (my_pow) (UINT_PTR) GetProcAddress (hMod, "pow"); | |
| } | |
| fpow = ptr_pow; | |
| } | |
| /* `pow` implementation using `exp` and `log` */ | |
| static __attribute__((noinline)) double __cdecl pow_by_log_exp (double x, double y) | |
| { | |
| /* pow(x, n) = exp(n * log(x)) */ | |
| if (x < 0.0) | |
| { | |
| long v = (long) y; | |
| x = exp(y * log (-x)); | |
| if ((double) v == y && (v&1) != 0) | |
| { | |
| x = -x; | |
| } | |
| return x; | |
| } | |
| return exp(y * log(x)); | |
| } | |
| static __attribute__((noinline)) void test(int cnt) | |
| { | |
| double x, y, z; | |
| unsigned int tiS = GetTickCount(); | |
| x = 1.0; | |
| y = 1.0; | |
| z = 0.0; | |
| while (cnt > 0) | |
| { | |
| x += 0.01; | |
| y -= 0.01; | |
| z += (*fpow)(x, y); | |
| --cnt; | |
| } | |
| printf ("Rslt: %g, %u ms\n", z, GetTickCount () - tiS); | |
| } | |
| int main (int argc, char **argv) | |
| { | |
| int e; | |
| mingw_test_init (); | |
| e = (argc > 1 ? atoi(argv[1]) : 20000000); | |
| /** | |
| * Test `pow` function in libmingwex. | |
| */ | |
| printf ("Current implementation in libmingwex: "); | |
| test (e); | |
| printf ("pow(-1.0, 2) = %g\n", (*fpow)(-1.0, 2.0)); | |
| printf ("pow(-1.0, 2.2) = %g\n", (*fpow)(-1.0, 2.2)); | |
| printf ("pow(2.0, -1) = %g\n", (*fpow)(2.0,-1.0)); | |
| /** | |
| * Test `pow` function in CRT. | |
| */ | |
| set_pow_crt (); | |
| if (fpow != NULL) { | |
| printf ("Implementation in "CRT_FILENAME": "); | |
| test (e); | |
| printf ("pow(-1.0, 2) = %g\n", (*fpow)(-1.0, 2.0)); | |
| printf ("pow(-1.0, 2.2) = %g\n", (*fpow)(-1.0, 2.2)); | |
| printf ("pow(2.0, -1) = %g\n", (*fpow)(2.0,-1.0)); | |
| } | |
| /** | |
| * Test `pow` implementation using `exp` and `log`. | |
| */ | |
| fpow = pow_by_log_exp; | |
| printf ("Implementation by exp and log: "); | |
| test (e); | |
| printf ("pow(-1.0, 2) = %g\n", (*fpow)(-1.0, 2.0)); | |
| printf ("pow(-1.0, 2.2) = %g\n", (*fpow)(-1.0, 2.2)); | |
| printf ("pow(2.0, -1) = %g\n", (*fpow)(2.0,-1.0)); | |
| return 0; | |
| } |