/* This file is part of the Vc library. {{{ Copyright (C) 2012 Matthias Kretz Vc is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Vc is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Vc. If not, see . }}}*/ #ifndef VC_COMMON_TYPES_H #define VC_COMMON_TYPES_H #ifdef VC_CHECK_ALIGNMENT #include #include #endif /*OUTER_NAMESPACE_BEGIN*/ namespace Vc { // helper type to implement sfloat_v (Vector) struct sfloat {}; template struct DetermineEntryType { typedef T Type; }; template<> struct DetermineEntryType { typedef float Type; }; template struct NegateTypeHelper { typedef T Type; }; template<> struct NegateTypeHelper { typedef char Type; }; template<> struct NegateTypeHelper { typedef short Type; }; template<> struct NegateTypeHelper { typedef int Type; }; namespace VectorSpecialInitializerZero { enum ZEnum { Zero = 0 }; } namespace VectorSpecialInitializerOne { enum OEnum { One = 1 }; } namespace VectorSpecialInitializerIndexesFromZero { enum IEnum { IndexesFromZero }; } template class Memory; #ifdef VC_MSVC # if defined(VC_IMPL_Scalar) namespace Scalar { template class Vector; template class Mask; } #define _Vector Vc::Scalar::Vector # elif defined(VC_IMPL_SSE) namespace SSE { template class Vector; template class Mask; class Float8Mask; } #define _Vector Vc::SSE::Vector # elif defined(VC_IMPL_AVX) namespace AVX { template class Vector; template class Mask; } #define _Vector Vc::AVX::Vector # else # error "Sorry, MSVC is a nasty compiler and needs extra care. Please help." # endif #endif namespace { template struct EnableIf { typedef T Value; }; template struct EnableIf {}; template struct IsSignedInteger { enum { Value = 0 }; }; template<> struct IsSignedInteger { enum { Value = 1 }; }; template<> struct IsSignedInteger { enum { Value = 1 }; }; template<> struct IsSignedInteger { enum { Value = 1 }; }; template<> struct IsSignedInteger { enum { Value = 1 }; }; template<> struct IsSignedInteger { enum { Value = 1 }; }; template struct IsUnsignedInteger { enum { Value = 0 }; }; template<> struct IsUnsignedInteger { enum { Value = 1 }; }; template<> struct IsUnsignedInteger { enum { Value = 1 }; }; template<> struct IsUnsignedInteger { enum { Value = 1 }; }; template<> struct IsUnsignedInteger { enum { Value = 1 }; }; template<> struct IsUnsignedInteger { enum { Value = 1 }; }; template struct IsInteger { enum { Value = IsSignedInteger::Value | IsUnsignedInteger::Value }; }; template struct IsReal { enum { Value = 0 }; }; template<> struct IsReal { enum { Value = 1 }; }; template<> struct IsReal { enum { Value = 1 }; }; template struct IsEqualType { enum { Value = 0 }; }; template struct IsEqualType { enum { Value = 1 }; }; template struct IsInTypelist { enum { Value = false }; }; template struct IsInTypelist { enum { Value = true }; }; template struct IsInTypelist { enum { Value = true }; }; template struct IsInTypelist { enum { Value = true }; }; template struct IsInTypelist { enum { Value = true }; }; template struct IsInTypelist { enum { Value = true }; }; template struct IsInTypelist { enum { Value = true }; }; template struct IsInTypelist { enum { Value = true }; }; template struct IsCombinationOf { enum { Value = false }; }; template struct IsCombinationOf { enum { Value = true }; }; template struct IsCombinationOf { enum { Value = true }; }; namespace { struct yes { char x; }; struct no { yes x, y; }; } // anonymous namespace template struct HasImplicitCast { #ifdef VC_MSVC // MSVC can't compile this code if we pass a type that has large alignment restrictions by // value // clang OTOH warns about this code if we pass a null-reference, thus we ifdef the const-ref // for MSVC only static yes test(const To &) { return yes(); } #else static yes test( To) { return yes(); } #endif static no test(...) { return no(); } enum { #ifdef VC_MSVC // I want to test whether implicit cast works. If it works MSVC thinks it should give a warning. Wrong. Shut up. #pragma warning(suppress : 4257 4267) #endif Value = !!(sizeof(test(*static_cast(0))) == sizeof(yes)) }; }; #if defined(VC_GCC) && VC_GCC < 0x40300 // GCC 4.1 is very noisy because of the float->int and double->int type trait tests. We get // around this noise with a little specialization. template<> struct HasImplicitCast { enum { Value = true }; }; template<> struct HasImplicitCast { enum { Value = true }; }; #endif #ifdef VC_MSVC // MSVC is such a broken compiler :'( // HasImplicitCast breaks if From has an __declspec(align(#)) modifier and has no implicit cast // to To. That's because it'll call test(...) as test(From) and not test(const From &). // This results in C2718. And MSVC is too stupid to see that it should just shut up and // everybody would be happy. // // Because the HasImplicitCast specializations can only be implemented after the Vector class // was declared we have to write some nasty hacks. template struct HasImplicitCast<_Vector, T2> { enum { Value = false }; }; #if defined(VC_IMPL_Scalar) template struct HasImplicitCast, T2> { enum { Value = false }; }; template struct HasImplicitCast, Vc::Scalar::Mask > { enum { Value = true }; }; #elif defined(VC_IMPL_SSE) template struct HasImplicitCast, T2> { enum { Value = false }; }; template struct HasImplicitCast, Vc::SSE::Mask > { enum { Value = true }; }; template struct HasImplicitCast { enum { Value = false }; }; template<> struct HasImplicitCast { enum { Value = true }; }; #elif defined(VC_IMPL_AVX) template struct HasImplicitCast, T2> { enum { Value = false }; }; template struct HasImplicitCast, Vc::AVX::Mask > { enum { Value = true }; }; #endif template struct HasImplicitCast<_Vector, _Vector > { enum { Value = true }; }; //template<> struct HasImplicitCast<_Vector< int>, _Vector< unsigned int>> { enum { Value = true }; }; //template<> struct HasImplicitCast<_Vector< unsigned int>, _Vector< int>> { enum { Value = true }; }; //template<> struct HasImplicitCast<_Vector< short>, _Vector> { enum { Value = true }; }; //template<> struct HasImplicitCast<_Vector, _Vector< short>> { enum { Value = true }; }; template struct HasImplicitCast, T2> { enum { Value = false }; }; template struct HasImplicitCast, Vc::Memory > { enum { Value = true }; }; #undef _Vector #endif template struct CanConvertToInt : public HasImplicitCast {}; template<> struct CanConvertToInt { enum { Value = 0 }; }; //template<> struct CanConvertToInt { enum { Value = 0 }; }; //template<> struct CanConvertToInt { enum { Value = 0 }; }; enum TestEnum {}; VC_STATIC_ASSERT(CanConvertToInt::Value == 1, CanConvertToInt_is_broken); VC_STATIC_ASSERT(CanConvertToInt::Value == 1, CanConvertToInt_is_broken); VC_STATIC_ASSERT(CanConvertToInt::Value == 0, CanConvertToInt_is_broken); VC_STATIC_ASSERT(CanConvertToInt::Value == 1, CanConvertToInt_is_broken); VC_STATIC_ASSERT(CanConvertToInt::Value == 1, CanConvertToInt_is_broken); VC_STATIC_ASSERT(CanConvertToInt::Value == 0, CanConvertToInt_is_broken); VC_STATIC_ASSERT(CanConvertToInt::Value == 1, CanConvertToInt_is_broken); typedef HasImplicitCast HasImplicitCastTest0; typedef HasImplicitCast HasImplicitCastTest1; typedef HasImplicitCast HasImplicitCastTest2; typedef HasImplicitCast HasImplicitCastTest3; typedef HasImplicitCast HasImplicitCastTest4; VC_STATIC_ASSERT(HasImplicitCastTest0::Value == true, HasImplicitCast0_is_broken); VC_STATIC_ASSERT(HasImplicitCastTest1::Value == true, HasImplicitCast1_is_broken); VC_STATIC_ASSERT(HasImplicitCastTest2::Value == true, HasImplicitCast2_is_broken); VC_STATIC_ASSERT(HasImplicitCastTest3::Value == true, HasImplicitCast3_is_broken); VC_STATIC_ASSERT(HasImplicitCastTest4::Value == false, HasImplicitCast4_is_broken); template struct IsLikeInteger { enum { Value = !IsReal::Value && CanConvertToInt::Value }; }; template struct IsLikeSignedInteger { enum { Value = IsLikeInteger::Value && !IsUnsignedInteger::Value }; }; } // anonymous namespace #ifndef VC_CHECK_ALIGNMENT template static Vc_ALWAYS_INLINE void assertCorrectAlignment(const _T *){} #else template static Vc_ALWAYS_INLINE void assertCorrectAlignment(const _T *ptr) { const size_t s = Vc_ALIGNOF(_T); if((reinterpret_cast(ptr) & ((s ^ (s & (s - 1))) - 1)) != 0) { fprintf(stderr, "A vector with incorrect alignment has just been created. Look at the stacktrace to find the guilty object.\n"); abort(); } } #endif } // namespace Vc /*OUTER_NAMESPACE_END*/ #endif // VC_COMMON_TYPES_H