Merge pull request #46 from fastfloat/dlemire/more_tests

Adding more CI tests and adds support for clang under msys2
This commit is contained in:
Daniel Lemire 2020-12-22 16:31:48 -05:00 committed by GitHub
commit 2940ec0458
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 310 additions and 79 deletions

49
.github/workflows/mingw-ci.yml vendored Normal file
View File

@ -0,0 +1,49 @@
name: MinGW32-CI
on: [push, pull_request]
# Important: scoop will either install 32-bit GCC or 64-bit GCC, not both.
# It is important to build static libraries because cmake is not smart enough under Windows/mingw to take care of the path. So
# with a dynamic library, you could get failures due to the fact that the EXE can't find its DLL.
jobs:
ci:
name: windows-gcc
runs-on: windows-2016
env:
CMAKE_GENERATOR: Ninja
CC: gcc
CXX: g++
steps: # To reproduce what is below, start a powershell with administrative rights, using scoop *is* a good idea
- uses: actions/checkout@v2
- uses: actions/cache@v2 # we cache the scoop setup with 32-bit GCC
id: cache
with:
path: |
C:\ProgramData\scoop
key: scoop32 # static key: should be good forever
- name: Setup Windows # This should almost never run if the cache works.
if: steps.cache.outputs.cache-hit != 'true'
shell: powershell
run: |
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
scoop install sudo --global
sudo scoop install git --global
sudo scoop install ninja --global
sudo scoop install cmake --global
sudo scoop install gcc --arch 32bit --global
$env:path
Write-Host 'Everything has been installed, you are good!'
- name: Build and Test 32-bit x86
shell: powershell
run: |
$ENV:PATH="C:\ProgramData\scoop\shims;C:\ProgramData\scoop\apps\gcc\current\bin;C:\ProgramData\scoop\apps\ninja\current;$ENV:PATH"
mkdir build32
cd build32
cmake -DFASTFLOAT_TEST=ON ..
cmake --build . --verbose
ctest -j4 --output-on-failure -R basictest

49
.github/workflows/mingw64-ci.yml vendored Normal file
View File

@ -0,0 +1,49 @@
name: MinGW64-CI
on: [push, pull_request]
# Important: scoop will either install 32-bit GCC or 64-bit GCC, not both.
# It is important to build static libraries because cmake is not smart enough under Windows/mingw to take care of the path. So
# with a dynamic library, you could get failures due to the fact that the EXE can't find its DLL.
jobs:
ci:
name: windows-gcc
runs-on: windows-2016
env:
CMAKE_GENERATOR: Ninja
CC: gcc
CXX: g++
steps: # To reproduce what is below, start a powershell with administrative rights, using scoop *is* a good idea
- uses: actions/checkout@v2
- uses: actions/cache@v2 # we cache the scoop setup with 64-bit GCC
id: cache
with:
path: |
C:\ProgramData\scoop
key: scoop64 # static key: should be good forever
- name: Setup Windows # This should almost never run if the cache works.
if: steps.cache.outputs.cache-hit != 'true'
shell: powershell
run: |
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
scoop install sudo --global
sudo scoop install git --global
sudo scoop install ninja --global
sudo scoop install cmake --global
sudo scoop install gcc --arch 64bit --global
$env:path
Write-Host 'Everything has been installed, you are good!'
- name: Build and Test 64-bit x64
shell: powershell
run: |
$ENV:PATH="C:\ProgramData\scoop\shims;C:\ProgramData\scoop\apps\gcc\current\bin;C:\ProgramData\scoop\apps\ninja\current;$ENV:PATH"
mkdir build64
cd build64
cmake -DFASTFLOAT_TEST=ON ..
cmake --build . --verbose
ctest -j4 --output-on-failure -R basictest

39
.github/workflows/msys2-clang.yml vendored Normal file
View File

@ -0,0 +1,39 @@
name: MSYS2-CLANG-CI
on: [push, pull_request]
jobs:
windows-mingw:
name: ${{ matrix.msystem }}
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
strategy:
fail-fast: false
matrix:
include:
- msystem: "MINGW64"
install: mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-clang
type: Release
- msystem: "MINGW32"
install: mingw-w64-i686-cmake mingw-w64-i686-ninja mingw-w64-i686-clang
type: Release
env:
CMAKE_GENERATOR: Ninja
steps:
- uses: actions/checkout@v2
- uses: msys2/setup-msys2@v2
with:
update: true
msystem: ${{ matrix.msystem }}
install: ${{ matrix.install }}
- name: Prepare build dir
run: mkdir build
- name: Configure
run: cd build && cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DFASTFLOAT_TEST=ON ..
- name: Build
run: cmake --build build
- name: Run basic tests
run: cd build && ctest --output-on-failure -R basictest

View File

@ -18,7 +18,7 @@ jobs:
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@v1.4
with:
cmake-version: '3.9.x'
cmake-version: '3.11.x'
- name: Install older compilers
run: |
sudo -E dpkg --add-architecture i386

View File

@ -17,7 +17,7 @@ jobs:
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@v1.4
with:
cmake-version: '3.9.x'
cmake-version: '3.11.x'
- name: install older compilers
run: |
sudo -E dpkg --add-architecture i386

View File

@ -5,18 +5,18 @@
#include <cstdint>
#include <cassert>
#if (defined(__i386) || defined(__i386__) || defined(_M_IX86) \
|| defined(__arm__) \
|| defined(__MINGW32__))
#define FASTFLOAT_32BIT
#elif (defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) \
#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) \
|| defined(__amd64) || defined(__aarch64__) || defined(_M_ARM64) \
|| defined(__MINGW64__) \
|| defined(__s390x__) \
|| (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)))
#define FASTFLOAT_64BIT
#elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) \
|| defined(__arm__) \
|| defined(__MINGW32__))
#define FASTFLOAT_32BIT
#else
#error Unknown platform
#error Unknown platform (not 32-bit, not 64-bit?)
#endif
#if ((defined(_WIN32) || defined(_WIN64)) && !defined(__clang__))
@ -164,7 +164,7 @@ fastfloat_really_inline value128 full_multiplication(uint64_t a,
// ARM64 has native support for 64-bit multiplications, no need to emulate
answer.high = __umulh(a, b);
answer.low = a * b;
#elif defined(FASTFLOAT_32BIT) || (defined(_WIN64))
#elif defined(FASTFLOAT_32BIT) || (defined(_WIN64) && !defined(__clang__))
answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64
#elif defined(FASTFLOAT_64BIT)
__uint128_t r = ((__uint128_t)a) * b;

View File

@ -30,15 +30,15 @@ void allvalues() {
std::cerr << "parsing error ? " << buffer << std::endl;
abort();
}
if(copysign(1,result_value) != copysign(1,v)) {
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v
<< std::endl;
abort();
} else if (std::isnan(v)) {
if (std::isnan(v)) {
if (!std::isnan(result_value)) {
std::cerr << "not nan" << buffer << std::endl;
abort();
}
} else if(copysign(1,result_value) != copysign(1,v)) {
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v
<< std::endl;
abort();
} else if (result_value != v) {
std::cerr << "no match ? " << buffer << std::endl;
std::cout << "started with " << std::hexfloat << v << std::endl;

View File

@ -20,16 +20,16 @@ bool basic_test_64bit(std::string vals, double val) {
std::cerr << " I could not parse " << vals << std::endl;
return false;
}
if(copysign(1,result_value) != copysign(1,val)) {
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << val
<< std::endl;
return false;
} else if (std::isnan(val)) {
if (std::isnan(val)) {
if (!std::isnan(result_value)) {
std::cerr << vals << std::endl;
std::cerr << "not nan" << result_value << std::endl;
return false;
}
}
} else if(copysign(1,result_value) != copysign(1,val)) {
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << val
<< std::endl;
return false;
} else if (result_value != val) {
std::cerr << vals << std::endl;
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << val

View File

@ -17,7 +17,21 @@ double cygwin_strtod_l(const char* start, char** end) {
ss.imbue(std::locale::classic());
ss << start;
ss >> d;
size_t nread = ss.tellg();
if(ss.fail()) { *end = nullptr; }
if(ss.eof()) { ss.clear(); }
auto nread = ss.tellg();
*end = const_cast<char*>(start) + nread;
return d;
}
float cygwin_strtof_l(const char* start, char** end) {
float d;
std::stringstream ss;
ss.imbue(std::locale::classic());
ss << start;
ss >> d;
if(ss.fail()) { *end = nullptr; }
if(ss.eof()) { ss.clear(); }
auto nread = ss.tellg();
*end = const_cast<char*>(start) + nread;
return d;
}
@ -29,10 +43,10 @@ template <typename T> char *to_string(T d, char *buffer) {
return buffer + written;
}
void strtod_from_string(const char * st, float& d) {
void strtof_from_string(const char * st, float& d) {
char *pr = (char *)st;
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
d = cygwin_strtod_l(st, &pr);
d = cygwin_strtof_l(st, &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
d = _strtof_l(st, &pr, c_locale);
@ -45,7 +59,7 @@ void strtod_from_string(const char * st, float& d) {
}
}
void allvalues() {
bool allvalues() {
char buffer[64];
for (uint64_t w = 0; w <= 0xFFFFFFFF; w++) {
float v;
@ -68,15 +82,24 @@ void allvalues() {
const char *string_end = to_string(midv, buffer);
float str_answer;
strtod_from_string(buffer, str_answer);
strtof_from_string(buffer, str_answer);
float result_value;
auto result = fast_float::from_chars(buffer, string_end, result_value);
if (result.ec != std::errc()) {
std::cerr << "parsing error ? " << buffer << std::endl;
abort();
return false;
}
if(copysign(1,result_value) != copysign(1,v)) {
if (std::isnan(v)) {
if (!std::isnan(result_value)) {
std::cerr << "not nan" << buffer << std::endl;
std::cerr << "v " << std::hexfloat << v << std::endl;
std::cerr << "v2 " << std::hexfloat << v2 << std::endl;
std::cerr << "midv " << std::hexfloat << midv << std::endl;
std::cerr << "expected_midv " << std::hexfloat << expected_midv << std::endl;
return false;
}
} else if(copysign(1,result_value) != copysign(1,v)) {
std::cerr << buffer << std::endl;
std::cerr << "v " << std::hexfloat << v << std::endl;
std::cerr << "v2 " << std::hexfloat << v2 << std::endl;
@ -84,16 +107,7 @@ void allvalues() {
std::cerr << "expected_midv " << std::hexfloat << expected_midv << std::endl;
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v
<< std::endl;
abort();
} else if (std::isnan(v)) {
if (!std::isnan(result_value)) {
std::cerr << "not nan" << buffer << std::endl;
std::cerr << "v " << std::hexfloat << v << std::endl;
std::cerr << "v2 " << std::hexfloat << v2 << std::endl;
std::cerr << "midv " << std::hexfloat << midv << std::endl;
std::cerr << "expected_midv " << std::hexfloat << expected_midv << std::endl;
abort();
}
return false;
} else if (result_value != str_answer) {
std::cerr << "no match ? " << buffer << std::endl;
std::cerr << "v " << std::hexfloat << v << std::endl;
@ -104,18 +118,26 @@ void allvalues() {
std::cout << "round down to " << std::hexfloat << str_answer << std::endl;
std::cout << "got back " << std::hexfloat << result_value << std::endl;
std::cout << std::dec;
abort();
return false;
}
}
}
std::cout << std::endl;
return true;
}
inline void Assert(bool Assertion) {
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
if (!Assertion) { std::cerr << "Omitting hard falure on msys/cygwin/sun systems."; }
#else
if (!Assertion) { throw std::runtime_error("bug"); }
#endif
}
int main() {
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
std::cout << "Warning: msys/cygwin or solaris detected. This particular test is likely to generate false failures due to our reliance on the underlying runtime library." << std::endl;
std::cout << "Warning: msys/cygwin or solaris detected. This particular test is likely to generate false failures due to our reliance on the underlying runtime library as a gold standard." << std::endl;
#endif
allvalues();
Assert(allvalues());
std::cout << std::endl;
std::cout << "all ok" << std::endl;
return EXIT_SUCCESS;

View File

@ -30,16 +30,16 @@ void allvalues() {
std::cerr << "parsing error ? " << buffer << std::endl;
abort();
}
if(copysign(1,result_value) != copysign(1,v)) {
std::cerr << buffer << std::endl;
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v
<< std::endl;
abort();
} else if (std::isnan(v)) {
if (std::isnan(v)) {
if (!std::isnan(result_value)) {
std::cerr << "not nan" << buffer << std::endl;
abort();
}
} else if(copysign(1,result_value) != copysign(1,v)) {
std::cerr << buffer << std::endl;
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v
<< std::endl;
abort();
} else if (result_value != v) {
std::cerr << "no match ? " << buffer << " got " << result_value << " expected " << v << std::endl;
std::cout << "started with " << std::hexfloat << v << std::endl;

View File

@ -60,12 +60,7 @@ void random_values(size_t N) {
abort();
}
}
if(copysign(1,result_value) != copysign(1,v)) {
std::cerr << buffer << std::endl;
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v
<< std::endl;
abort();
} else if (std::isnan(v)) {
if (std::isnan(v)) {
if (!std::isnan(result_value)) {
std::cerr << "not nan" << buffer << std::endl;
errors++;
@ -73,6 +68,11 @@ void random_values(size_t N) {
abort();
}
}
} else if(copysign(1,result_value) != copysign(1,v)) {
std::cerr << buffer << std::endl;
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v
<< std::endl;
abort();
} else if (result_value != v) {
std::cerr << "no match ? '" << buffer << "'" << std::endl;
std::cout << "started with " << std::hexfloat << v << std::endl;

View File

@ -3,8 +3,7 @@
#include <vector>
inline void Assert(bool Assertion) {
if (!Assertion)
throw std::runtime_error("bug");
if (!Assertion) { throw std::runtime_error("bug"); }
}
template <typename T>

View File

@ -19,7 +19,21 @@ double cygwin_strtod_l(const char* start, char** end) {
ss.imbue(std::locale::classic());
ss << start;
ss >> d;
size_t nread = ss.tellg();
if(ss.fail()) { *end = nullptr; }
if(ss.eof()) { ss.clear(); }
auto nread = ss.tellg();
*end = const_cast<char*>(start) + nread;
return d;
}
float cygwin_strtof_l(const char* start, char** end) {
float d;
std::stringstream ss;
ss.imbue(std::locale::classic());
ss << start;
ss >> d;
if(ss.fail()) { *end = nullptr; }
if(ss.eof()) { ss.clear(); }
auto nread = ss.tellg();
*end = const_cast<char*>(start) + nread;
return d;
}
@ -29,7 +43,9 @@ double cygwin_strtod_l(const char* start, char** end) {
std::pair<double, bool> strtod_from_string(const char *st) {
double d;
char *pr;
#ifdef _WIN32
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
d = cygwin_strtod_l(st, &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
d = _strtod_l(st, &pr, c_locale);
#else
@ -47,7 +63,7 @@ std::pair<float, bool> strtof_from_string(char *st) {
float d;
char *pr;
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
d = cygwin_strtod_l(st, &pr);
d = cygwin_strtof_l(st, &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
d = _strtof_l(st, &pr, c_locale);

View File

@ -62,12 +62,7 @@ void random_values(size_t N) {
abort();
}
}
if(copysign(1,result_value) != copysign(1,v)) {
std::cerr << buffer << std::endl;
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v
<< std::endl;
abort();
} else if (std::isnan(v)) {
if (std::isnan(v)) {
if (!std::isnan(result_value)) {
std::cerr << "not nan" << buffer << std::endl;
errors++;
@ -75,6 +70,11 @@ void random_values(size_t N) {
abort();
}
}
} else if(copysign(1,result_value) != copysign(1,v)) {
std::cerr << buffer << std::endl;
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v
<< std::endl;
abort();
} else if (result_value != v) {
std::cerr << "no match ? " << buffer << std::endl;
std::cout << "started with " << std::hexfloat << v << std::endl;

View File

@ -17,7 +17,21 @@ double cygwin_strtod_l(const char* start, char** end) {
ss.imbue(std::locale::classic());
ss << start;
ss >> d;
size_t nread = ss.tellg();
if(ss.fail()) { *end = nullptr; }
if(ss.eof()) { ss.clear(); }
auto nread = ss.tellg();
*end = const_cast<char*>(start) + nread;
return d;
}
float cygwin_strtof_l(const char* start, char** end) {
float d;
std::stringstream ss;
ss.imbue(std::locale::classic());
ss << start;
ss >> d;
if(ss.fail()) { *end = nullptr; }
if(ss.eof()) { ss.clear(); }
auto nread = ss.tellg();
*end = const_cast<char*>(start) + nread;
return d;
}
@ -111,7 +125,9 @@ size_t build_random_string(RandomEngine &rand, char *buffer) {
std::pair<double, bool> strtod_from_string(char *st) {
double d;
char *pr;
#ifdef _WIN32
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
d = cygwin_strtod_l(st, &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
d = _strtod_l(st, &pr, c_locale);
#else
@ -129,7 +145,7 @@ std::pair<float, bool> strtof_from_string(char *st) {
float d;
char *pr;
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
d = cygwin_strtod_l(st, &pr);
d = cygwin_strtof_l(st, &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
d = _strtof_l(st, &pr, c_locale);
@ -205,13 +221,17 @@ bool tester(uint64_t seed, size_t volume) {
}
int main() {
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
std::cout << "Warning: msys/cygwin or solaris detected. This particular test is likely to generate false failures due to our reliance on the underlying runtime library." << std::endl;
#endif
std::cout << "Warning: msys/cygwin or solaris detected." << std::endl;
return EXIT_SUCCESS;
#else
if (tester(1234344, 100000000)) {
std::cout << "All tests ok." << std::endl;
return EXIT_SUCCESS;
}
std::cout << "Failure." << std::endl;
return EXIT_FAILURE;
#endif
}

View File

@ -16,7 +16,21 @@ double cygwin_strtod_l(const char* start, char** end) {
ss.imbue(std::locale::classic());
ss << start;
ss >> d;
size_t nread = ss.tellg();
if(ss.fail()) { *end = nullptr; }
if(ss.eof()) { ss.clear(); }
auto nread = ss.tellg();
*end = const_cast<char*>(start) + nread;
return d;
}
float cygwin_strtof_l(const char* start, char** end) {
float d;
std::stringstream ss;
ss.imbue(std::locale::classic());
ss << start;
ss >> d;
if(ss.fail()) { *end = nullptr; }
if(ss.eof()) { ss.clear(); }
auto nread = ss.tellg();
*end = const_cast<char*>(start) + nread;
return d;
}
@ -106,7 +120,9 @@ size_t build_random_string(RandomEngine &rand, char *buffer) {
std::pair<double, bool> strtod_from_string(char *st) {
double d;
char *pr;
#ifdef _WIN32
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
d = cygwin_strtod_l(st, &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
d = _strtod_l(st, &pr, c_locale);
#else
@ -124,7 +140,7 @@ std::pair<float, bool> strtof_from_string(char *st) {
float d;
char *pr;
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
d = cygwin_strtod_l(st, &pr);
d = cygwin_strtof_l(st, &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
d = _strtof_l(st, &pr, c_locale);
@ -202,11 +218,13 @@ bool tester(uint64_t seed, size_t volume) {
int main() {
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
std::cout << "Warning: msys/cygwin detected. This particular test is likely to generate false failures due to our reliance on the underlying runtime library." << std::endl;
#endif
return EXIT_SUCCESS;
#else
if (tester(1234344, 100000000)) {
std::cout << "All tests ok." << std::endl;
return EXIT_SUCCESS;
}
std::cout << "Failure." << std::endl;
return EXIT_FAILURE;
#endif
}

View File

@ -15,15 +15,32 @@ double cygwin_strtod_l(const char* start, char** end) {
ss.imbue(std::locale::classic());
ss << start;
ss >> d;
size_t nread = ss.tellg();
if(ss.fail()) { *end = nullptr; }
if(ss.eof()) { ss.clear(); }
auto nread = ss.tellg();
*end = const_cast<char*>(start) + nread;
return d;
}
float cygwin_strtof_l(const char* start, char** end) {
float d;
std::stringstream ss;
ss.imbue(std::locale::classic());
ss << start;
ss >> d;
if(ss.fail()) { *end = nullptr; }
if(ss.eof()) { ss.clear(); }
auto nread = ss.tellg();
*end = const_cast<char*>(start) + nread;
return d;
}
#endif
inline void Assert(bool Assertion) {
if (!Assertion)
throw std::runtime_error("bug");
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
if (!Assertion) { std::cerr << "Omitting hard falure on msys/cygwin/sun systems."; }
#else
if (!Assertion) { throw std::runtime_error("bug"); }
#endif
}
template <typename T> std::string to_string(T d) {
@ -70,7 +87,9 @@ void strtod_from_string(const std::string &st, T& d);
template <>
void strtod_from_string(const std::string &st, double& d) {
char *pr = (char *)st.c_str();
#ifdef _WIN32
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
d = cygwin_strtod_l(pr, &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
d = _strtod_l(st.c_str(), &pr, c_locale);
#else
@ -86,7 +105,7 @@ template <>
void strtod_from_string(const std::string &st, float& d) {
char *pr = (char *)st.c_str();
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
d = cygwin_strtod_l(st.c_str(), &pr);
d = cygwin_strtof_l(st.c_str(), &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
d = _strtof_l(st.c_str(), &pr, c_locale);
@ -237,7 +256,7 @@ bool partow_test() {
int main() {
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
std::cout << "Warning: msys/cygwin detected. This particular test is likely to generate false failures due to our reliance on the underlying runtime library." << std::endl;
std::cout << "Warning: msys/cygwin or solaris detected." << std::endl;
#endif
std::cout << "32 bits checks" << std::endl;
Assert(partow_test<float>());