Skip to content
New issue

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

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

Already on GitHub? # 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
}

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

No branches or pull requests

3 participants