Skip to content

Commit a0cccfb

Browse files
authored
Merge pull request #465 from serge-sans-paille/feature/detect-sincos
Implement a more robust detection for sincos / __sincos function family
2 parents 16ef83e + 4d5ee6f commit a0cccfb

File tree

1 file changed

+74
-16
lines changed

1 file changed

+74
-16
lines changed

include/xsimd/types/xsimd_scalar.hpp

Lines changed: 74 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -406,28 +406,86 @@ namespace xsimd
406406
}
407407
#endif
408408

409+
namespace detail
410+
{
411+
#define XSIMD_HASSINCOS_TRAIT(func) \
412+
template<class S> \
413+
struct has##func \
414+
{ \
415+
template<class T> static auto get(T* ptr) -> decltype(func(std::declval<T>(), std::declval<T*>(), std::declval<T*>()), std::true_type{});\
416+
static std::false_type get(...); \
417+
static constexpr bool value = decltype(get((S*)nullptr))::value; \
418+
}
419+
420+
#define XSIMD_HASSINCOS(func, T) has##func<T>::value
421+
422+
XSIMD_HASSINCOS_TRAIT(sincos);
423+
XSIMD_HASSINCOS_TRAIT(sincosf);
424+
XSIMD_HASSINCOS_TRAIT(__sincos);
425+
XSIMD_HASSINCOS_TRAIT(__sincosf);
426+
427+
struct generic_sincosf
428+
{
429+
template<class T>
430+
typename std::enable_if<XSIMD_HASSINCOS(sincosf, T), void>::type
431+
operator()(float val, T &s, T &c)
432+
{
433+
sincosf(val, &s, &c);
434+
}
435+
436+
template<class T>
437+
typename std::enable_if<!XSIMD_HASSINCOS(sincosf, T) && XSIMD_HASSINCOS(__sincosf, T), void>::type
438+
operator()(float val, T &s, T &c)
439+
{
440+
__sincosf(val, &s, &c);
441+
}
442+
443+
template<class T>
444+
typename std::enable_if<!XSIMD_HASSINCOS(sincosf, T) && !XSIMD_HASSINCOS(__sincosf, T), void>::type
445+
operator()(float val, T &s, T &c)
446+
{
447+
s = std::sin(val);
448+
c = std::cos(val);
449+
}
450+
};
451+
452+
struct generic_sincos
453+
{
454+
template<class T>
455+
typename std::enable_if<XSIMD_HASSINCOS(sincos, T), void>::type
456+
operator()(double val, T &s, T &c)
457+
{
458+
sincos(val, &s, &c);
459+
}
460+
461+
template<class T>
462+
typename std::enable_if<!XSIMD_HASSINCOS(sincos, T) && XSIMD_HASSINCOS(__sincos, T), void>::type
463+
operator()(double val, T &s, T &c)
464+
{
465+
__sincos(val, &s, &c);
466+
}
467+
468+
template<class T>
469+
typename std::enable_if<!XSIMD_HASSINCOS(sincos, T) && !XSIMD_HASSINCOS(__sincos, T), void>::type
470+
operator()(double val, T &s, T &c)
471+
{
472+
s = std::sin(val);
473+
c = std::cos(val);
474+
}
475+
};
476+
477+
#undef XSIMD_HASSINCOS_TRAIT
478+
#undef XSIMD_HASSINCOS
479+
}
480+
409481
inline void sincos(float val, float&s, float& c)
410482
{
411-
#if defined(__APPLE__)
412-
__sincosf(val, &s, &c);
413-
#elif defined(_GNU_SOURCE)
414-
::sincosf(val, &s, &c);
415-
#else
416-
s = std::sin(val);
417-
c = std::cos(val);
418-
#endif
483+
detail::generic_sincosf{}(val, s, c);
419484
}
420485

421486
inline void sincos(double val, double&s, double& c)
422487
{
423-
#if defined(__APPLE__)
424-
__sincos(val, &s, &c);
425-
#elif defined(_GNU_SOURCE)
426-
::sincos(val, &s, &c);
427-
#else
428-
s = std::sin(val);
429-
c = std::cos(val);
430-
#endif
488+
detail::generic_sincos{}(val, s, c);
431489
}
432490

433491
template <class T>

0 commit comments

Comments
 (0)