blob: 5606af15a5c5a36456b296b920588833d056c340 [file]
#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;
}