Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

_copysign cannot be used in constant context (MSVC 16 2019) #20

Open
tomreddell opened this issue Jun 25, 2020 · 2 comments
Open

_copysign cannot be used in constant context (MSVC 16 2019) #20

tomreddell opened this issue Jun 25, 2020 · 2 comments

Comments

@tomreddell
Copy link

Building GCEM in a project using Cmake on Windows 10, and with MSVC 16 2019 as the compiler fails, it appears that the implementation of _copysign cannot be used in a constant context. Many errors were thrown of the form:

C:\Users\61405\source\repos\BGNC\extern\gcem\include\gcem_incl/neg_zero.hpp(34,31): message : see usage of '_copysign' [C:\Users\61405\source\repos\BGNC\build\tests\BGNCTestExec.vcxproj]
C:\Users\61405\source\repos\BGNC\tests\coordinates_tests\earth_tests.cpp(129,28): error C2131: expression did not evaluate to a constant [C:\Users\61405\source\repos\BGNC\build\tests\BGNCTestExec.vcxproj]
C:\Users\61405\source\repos\BGNC\extern\gcem\include\gcem_incl/neg_zero.hpp(34,31): message : failure was caused by call of undefined function or one not declared 'constexpr' [C:\Users\61405\source\repos\BGNC\build\tests\BGNCTestExec.vcxproj]

The same code compiled fine when using GCC.

I've confirmed that the errors are removed by manually implementing a version of copysign:

#gcem_options.hpp

template <typename T>
constexpr T HACK_MSVCcopysign(T x, T y)
{
    if ((x < 0 && y > 0) || (x > 0 && y < 0))
    {
        return -x;
    }
    return x;
}

#ifdef _MSC_VER
    #ifndef GCEM_SIGNBIT
        #define GCEM_SIGNBIT(x) _signbit(x)
    #endif
    #ifndef GCEM_COPYSIGN
        // #define GCEM_COPYSIGN(x,y) _copysign(x,y)
        #define GCEM_COPYSIGN(x,y) HACK_MSVCcopysign(x, y)
    #endif
...
@kthohr
Copy link
Owner

kthohr commented Aug 9, 2020

Unfortunately, your approach does not cover signed zeros - try HACK_MSVCcopysign(1.0, -0.0).

If MSVC's _fpclass(x) function is constexpr friendly, then the new gcem::copysign function will provide a workaround.

@lIIIIIIIIl
Copy link

lIIIIIIIIl commented Sep 30, 2020

template <typename T>
constexpr bool signbit(const T x) noexcept
{
#if defined(__clang__) || defined(__GNUC__)
	return __builtin_signbit(x);
#else
	static_assert(sizeof(T) == 4 || sizeof(T) == 8);
	using uint = std::conditional_t<sizeof(T) == 4, std::uint32_t, std::uint64_t>;
	return std::bit_cast<uint>(x) & (uint{ 1 } << (sizeof(T) * 8 - 1));
#endif
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants