libcarla/include/system/boost/qvm/detail/swizzle_traits.hpp
2024-10-18 13:19:59 +08:00

383 lines
11 KiB
C++

#ifndef BOOST_QVM_DETAIL_SWIZZLE_TRAITS_HPP_INCLUDED
#define BOOST_QVM_DETAIL_SWIZZLE_TRAITS_HPP_INCLUDED
// Copyright 2008-2022 Emil Dotchevski and Reverge Studios, Inc.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/qvm/config.hpp>
#include <boost/qvm/deduce_vec.hpp>
#include <boost/qvm/enable_if.hpp>
#include <boost/qvm/assert.hpp>
namespace boost { namespace qvm {
namespace
qvm_detail
{
BOOST_QVM_INLINE_CRITICAL
void const *
get_null()
{
static int const obj=0;
return &obj;
}
template <int A,class Next=void> struct swizzle_idx { static int const value=A; typedef Next next; };
template <class V,int Idx>
struct
const_value
{
static
BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
typename vec_traits<V>::scalar_type
value()
{
BOOST_QVM_ASSERT(0);
return typename vec_traits<V>::scalar_type();
}
};
template <class V>
struct
const_value<V,-1>
{
static
BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
typename vec_traits<V>::scalar_type
value()
{
return scalar_traits<typename vec_traits<V>::scalar_type>::value(0);
}
};
template <class V>
struct
const_value<V,-2>
{
static
BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
typename vec_traits<V>::scalar_type
value()
{
return scalar_traits<typename vec_traits<V>::scalar_type>::value(1);
}
};
template <int Index,bool Neg=(Index<0)>
struct neg_zero;
template <int Index>
struct
neg_zero<Index,true>
{
static int const value=0;
};
template <int Index>
struct
neg_zero<Index,false>
{
static int const value=Index;
};
template <class SwizzleList,int Index,int C=0>
struct
swizzle
{
static int const value=swizzle<typename SwizzleList::next,Index,C+1>::value;
};
template <class SwizzleList,int Match>
struct
swizzle<SwizzleList,Match,Match>
{
static int const value=SwizzleList::value;
};
template <int Index,int C>
struct swizzle<void,Index,C>;
template <class SwizzleList,int C=0>
struct
swizzle_list_length
{
static int const value=swizzle_list_length<typename SwizzleList::next,C+1>::value;
};
template <int C>
struct
swizzle_list_length<void,C>
{
static int const value=C;
};
template <class SwizzleList,int D>
struct
validate_swizzle_list
{
static bool const value =
((SwizzleList::value)<D) && //don't touch extra (), MSVC parsing bug.
validate_swizzle_list<typename SwizzleList::next,D>::value;
};
template <int D>
struct
validate_swizzle_list<void,D>
{
static bool const value=true;
};
template <class OriginalType,class SwizzleList>
class
sw_
{
sw_( sw_ const & );
sw_ & operator=( sw_ const & );
~sw_();
BOOST_QVM_STATIC_ASSERT((validate_swizzle_list<SwizzleList,vec_traits<OriginalType>::dim>::value));
public:
template <class T>
BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
sw_ &
operator=( T const & x )
{
assign(*this,x);
return *this;
}
template <class R
#if __cplusplus >= 201103L
, class = typename enable_if<is_vec<R> >::type
#endif
>
BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
operator R() const
{
R r;
assign(r,*this);
return r;
}
};
template <class OriginalVector,class SwizzleList,bool WriteElementRef=vec_write_element_ref<OriginalVector>::value>
struct sw_write_traits;
template <class OriginalVector,class SwizzleList>
struct
sw_write_traits<OriginalVector,SwizzleList,true>
{
typedef qvm_detail::sw_<OriginalVector,SwizzleList> this_vector;
typedef typename vec_traits<OriginalVector>::scalar_type scalar_type;
static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
template <int I>
static
BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
scalar_type &
write_element( this_vector & x )
{
BOOST_QVM_STATIC_ASSERT(I>=0);
BOOST_QVM_STATIC_ASSERT(I<dim);
int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
BOOST_QVM_STATIC_ASSERT(idx>=0);
BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim);
return vec_traits<OriginalVector>::template write_element<idx>(reinterpret_cast<OriginalVector &>(x));
}
};
template <class OriginalVector,class SwizzleList>
struct
sw_write_traits<OriginalVector,SwizzleList,false>
{
typedef qvm_detail::sw_<OriginalVector,SwizzleList> this_vector;
typedef typename vec_traits<OriginalVector>::scalar_type scalar_type;
static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
template <int I>
static
BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
void
write_element( this_vector & x, scalar_type s )
{
BOOST_QVM_STATIC_ASSERT(I>=0);
BOOST_QVM_STATIC_ASSERT(I<dim);
int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
BOOST_QVM_STATIC_ASSERT(idx>=0);
BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim);
vec_traits<OriginalVector>::template write_element<idx>(reinterpret_cast<OriginalVector &>(x), s);
}
};
template <class SwizzleList>
class
sw01_
{
sw01_( sw01_ const & );
sw01_ & operator=( sw01_ const & );
~sw01_();
public:
template <class R
#if __cplusplus >= 201103L
, class = typename enable_if<is_vec<R> >::type
#endif
>
BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
operator R() const
{
R r;
assign(r,*this);
return r;
}
};
template <class OriginalType,class SwizzleList>
class
sws_
{
sws_( sws_ const & );
sws_ & operator=( sws_ const & );
~sws_();
BOOST_QVM_STATIC_ASSERT((validate_swizzle_list<SwizzleList,1>::value));
public:
template <class R
#if __cplusplus >= 201103L
, class = typename enable_if<is_vec<R> >::type
#endif
>
BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
operator R() const
{
R r;
assign(r,*this);
return r;
}
};
}
template <class OriginalVector,class SwizzleList>
struct
vec_traits<qvm_detail::sw_<OriginalVector,SwizzleList> >:
qvm_detail::sw_write_traits<OriginalVector,SwizzleList>
{
typedef qvm_detail::sw_<OriginalVector,SwizzleList> this_vector;
typedef typename vec_traits<OriginalVector>::scalar_type scalar_type;
static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
template <int I>
static
BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
scalar_type
read_element( this_vector const & x )
{
BOOST_QVM_STATIC_ASSERT(I>=0);
BOOST_QVM_STATIC_ASSERT(I<dim);
int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim);
return idx>=0?
vec_traits<OriginalVector>::template read_element<qvm_detail::neg_zero<idx>::value>(reinterpret_cast<OriginalVector const &>(x)) :
qvm_detail::const_value<this_vector,idx>::value();
}
};
template <class SwizzleList>
struct
vec_traits<qvm_detail::sw01_<SwizzleList> >
{
typedef qvm_detail::sw01_<SwizzleList> this_vector;
typedef int scalar_type;
static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
template <int I>
static
BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
scalar_type
read_element( this_vector const & )
{
BOOST_QVM_STATIC_ASSERT(I>=0);
BOOST_QVM_STATIC_ASSERT(I<dim);
int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
BOOST_QVM_STATIC_ASSERT(idx<0);
return qvm_detail::const_value<this_vector,idx>::value();
}
};
template <class OriginalScalar,class SwizzleList>
struct
vec_traits<qvm_detail::sws_<OriginalScalar,SwizzleList> >
{
typedef qvm_detail::sws_<OriginalScalar,SwizzleList> this_vector;
typedef OriginalScalar scalar_type;
static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
template <int I>
static
BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
scalar_type
read_element( this_vector const & x )
{
BOOST_QVM_STATIC_ASSERT(I>=0);
BOOST_QVM_STATIC_ASSERT(I<dim);
int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
BOOST_QVM_STATIC_ASSERT(idx<1);
return idx==0?
reinterpret_cast<OriginalScalar const &>(x) :
qvm_detail::const_value<this_vector,idx>::value();
}
template <int I>
static
BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
scalar_type &
write_element( this_vector & x )
{
BOOST_QVM_STATIC_ASSERT(I>=0);
BOOST_QVM_STATIC_ASSERT(I<dim);
int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
BOOST_QVM_STATIC_ASSERT(idx==0);
return reinterpret_cast<OriginalScalar &>(x);
}
};
template <class OriginalVector,class SwizzleList,int D>
struct
deduce_vec<qvm_detail::sw_<OriginalVector,SwizzleList>,D>
{
typedef vec<typename vec_traits<OriginalVector>::scalar_type,D> type;
};
template <class OriginalVector,class SwizzleList,int D>
struct
deduce_vec2<qvm_detail::sw_<OriginalVector,SwizzleList>,qvm_detail::sw_<OriginalVector,SwizzleList>,D>
{
typedef vec<typename vec_traits<OriginalVector>::scalar_type,D> type;
};
template <class Scalar,class SwizzleList,int D>
struct
deduce_vec<qvm_detail::sws_<Scalar,SwizzleList>,D>
{
typedef vec<Scalar,D> type;
};
template <class Scalar,class SwizzleList,int D>
struct
deduce_vec2<qvm_detail::sws_<Scalar,SwizzleList>,qvm_detail::sws_<Scalar,SwizzleList>,D>
{
typedef vec<Scalar,D> type;
};
} }
#endif