/* * Copyright 2015-2020 Michele "King_DuckZ" Santullo * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "vectorwrapper/sequence_bt.hpp" #include "vectorwrapper/size_type.hpp" #include "vectorwrapper/implem_vec_base.hpp" #include "vectorwrapper/implem_vec_common.hpp" #include #include #include #include #include #define VWR_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ #define VWR_VERSION_MINOR @PROJECT_VERSION_MINOR@ #define VWR_VERSION_PATCH @PROJECT_VERSION_PATCH@ #if defined VWR_OUTER_NAMESPACE namespace VWR_OUTER_NAMESPACE { #endif namespace vwr { template struct VectorWrapperInfo; template class Vec; namespace implem { #if defined(VWR_WITH_IMPLICIT_CONVERSIONS) template Vec& assign ( Vec& parLeft, const Vec& parRight ); #endif template ::dimensions> struct offsets_array_wrapper { template offsets_array_wrapper ( const bt::number_seq& ); const std::array offsets; }; template struct Vec1Promotion; template struct Vec1Promotion { }; template struct Vec1Promotion { typedef Vec::higher_vector_type> higher_vector_type; typedef typename VectorWrapperInfo::scalar_type scalar_type; static_assert(VectorWrapperInfo::higher_vector_type>::dimensions == 2, "Wrong promoted vector type"); higher_vector_type x1 ( void ) const { return xn(scalar_type(1)); } higher_vector_type x0 ( void ) const { return xn(scalar_type(0)); } higher_vector_type xn ( const scalar_type& parN ) const; higher_vector_type nx ( const scalar_type& parN ) const; }; template struct Vec2Promotion; template struct Vec2Promotion {}; template struct Vec2Promotion { typedef Vec::higher_vector_type> higher_vector_type; typedef typename VectorWrapperInfo::scalar_type scalar_type; static_assert(VectorWrapperInfo::higher_vector_type>::dimensions == 3, "Wrong promoted vector type"); higher_vector_type xy1 ( void ) const { return xyn(scalar_type(1)); } higher_vector_type xy0 ( void ) const { return xyn(scalar_type(0)); } higher_vector_type xyn ( const scalar_type& parZ ) const; }; template struct Vec3Promotion; template struct Vec3Promotion {}; template struct Vec3Promotion { typedef Vec::higher_vector_type> higher_vector_type; typedef typename VectorWrapperInfo::scalar_type scalar_type; static_assert(VectorWrapperInfo::higher_vector_type>::dimensions == 4, "Wrong promoted vector type"); higher_vector_type xyz1 ( void ) const { return xyzw(scalar_type(1)); } higher_vector_type xyz0 ( void ) const { return xyzw(scalar_type(0)); } higher_vector_type xyzw ( const scalar_type& parW ) const; }; template struct Vec3Demotion; template struct Vec3Demotion : Vec3Promotion::value> {}; template struct Vec3Demotion : Vec3Promotion::value> { typedef Vec::lower_vector_type> lower_vector_type; typedef typename VectorWrapperInfo::scalar_type scalar_type; static_assert(VectorWrapperInfo::lower_vector_type>::dimensions == 2, "Wrong demoted vector type"); lower_vector_type xy ( void ) const; lower_vector_type xz ( void ) const; lower_vector_type yz ( void ) const; }; template struct Vec4Demotion; template struct Vec4Demotion {}; template struct Vec4Demotion { typedef Vec::lower_vector_type> lower_vector_type; typedef typename VectorWrapperInfo::scalar_type scalar_type; static_assert(VectorWrapperInfo::lower_vector_type>::dimensions == 3, "Wrong demoted vector type"); lower_vector_type xyz ( void ) const; lower_vector_type xyw ( void ) const; lower_vector_type xzw ( void ) const; lower_vector_type yzw ( void ) const; }; template struct VecAccessors; template struct VecAccessors : Vec4Demotion>::value> { typedef typename VectorWrapperInfo::scalar_type scalar_type; const Vec& xyzw ( void ) const { return *static_cast*>(this); } const scalar_type& x ( void ) const; const scalar_type& y ( void ) const; const scalar_type& z ( void ) const; const scalar_type& w ( void ) const; scalar_type& x ( void ); scalar_type& y ( void ); scalar_type& z ( void ); scalar_type& w ( void ); #if defined(VWR_EXTRA_SETTERS) void set_x (const scalar_type& v) { x() = v; } void set_y (const scalar_type& v) { y() = v; } void set_z (const scalar_type& v) { z() = v; } void set_w (const scalar_type& v) { w() = v; } #endif #if defined(VWR_EXTRA_ACCESSORS) Vec xyz0 ( void ) const { return Vec(x(), y(), z(), scalar_type(0)); } Vec xyz1 ( void ) const { return Vec(x(), y(), z(), scalar_type(1)); } Vec x0zw ( void ) const { return Vec(x(), scalar_type(0), z(), w()); } Vec x1zw ( void ) const { return Vec(x(), scalar_type(1), z(), w()); } Vec _0yzw ( void ) const { return Vec(scalar_type(0), y(), z(), w()); } Vec _1yzw ( void ) const { return Vec(scalar_type(1), y(), z(), w()); } Vec wxyz ( void ) const { return Vec(w(), x(), y(), z()); } #endif }; //Workaround for visual studio - VecAccessors should inherit from //both Vec3Promotion and Vec3Demotion, but when I do that, sizeof(Vec) //is wrong. I had to linearize the inheritance hierarchy so that the //sizeof(Vec) == sizeof(V) condition is verified. template struct VecAccessors : Vec3Demotion>::value> { typedef typename VectorWrapperInfo::scalar_type scalar_type; const Vec& xyz ( void ) const { return *static_cast*>(this); } const scalar_type& x ( void ) const; const scalar_type& y ( void ) const; const scalar_type& z ( void ) const; scalar_type& x ( void ); scalar_type& y ( void ); scalar_type& z ( void ); #if defined(VWR_EXTRA_SETTERS) void set_x (const scalar_type& v) { x() = v; } void set_y (const scalar_type& v) { y() = v; } void set_z (const scalar_type& v) { z() = v; } #endif #if defined(VWR_EXTRA_ACCESSORS) Vec xy0 ( void ) const { return Vec(x(), y(), scalar_type(0)); } Vec xy1 ( void ) const { return Vec(x(), y(), scalar_type(1)); } Vec x0z ( void ) const { return Vec(x(), scalar_type(0), z()); } Vec x1z ( void ) const { return Vec(x(), scalar_type(1), z()); } Vec _0yz ( void ) const { return Vec(scalar_type(0), y(), z()); } Vec _1yz ( void ) const { return Vec(scalar_type(1), y(), z()); } Vec zxy ( void ) const { return Vec(z(), x(), y()); } #endif }; template struct VecAccessors : Vec2Promotion>::value> { typedef typename VectorWrapperInfo::scalar_type scalar_type; const Vec& xy ( void ) const { return *static_cast*>(this); } const scalar_type& x ( void ) const; const scalar_type& y ( void ) const; scalar_type& x ( void ); scalar_type& y ( void ); #if defined(VWR_EXTRA_SETTERS) void set_x (const scalar_type& v) { x() = v; } void set_y (const scalar_type& v) { y() = v; } #endif #if defined(VWR_EXTRA_ACCESSORS) Vec x0 ( void ) const { return Vec(x(), scalar_type(0)); } Vec x1 ( void ) const { return Vec(x(), scalar_type(1)); } Vec yx ( void ) const { return Vec(y(), x()); } Vec _0y ( void ) const { return Vec(scalar_type(0), y()); } Vec _1y ( void ) const { return Vec(scalar_type(1), y()); } #endif }; template struct VecAccessors : Vec1Promotion>::value> { typedef typename VectorWrapperInfo::scalar_type scalar_type; scalar_type& x ( void ); const scalar_type& x ( void ) const; #if defined(VWR_EXTRA_SETTERS) void set_x (const scalar_type& v) { x() = v; } #endif }; template constexpr bool compare ( const Vec& parLeft, const Vec& parRight, Op parComposeOp, Op parOp, bt::number_seq ); template bool compare ( const Vec& parLeft, const Vec& parRight, ComposeOp parComposeOp, Op parOp, bt::number_seq ); template Vec::type> binary_op ( const Vec& parLeft, const Vec& parRight, Op parOp, const Vec::type>& parLastVal, bt::number_seq ); } //namespace implem template class Vec : public implem::VecBase { public: enum { dimensions = S }; }; template class Vec : public implem::VecBase, public implem::VecAccessors { static_assert(std::is_standard_layout>::value, "Base class must be a standard layout type"); public: typedef typename implem::VecBase::vector_type vector_type; typedef typename implem::VecBase::scalar_type scalar_type; enum { dimensions = 1 }; static const Vec unit_x; Vec ( void ) = default; Vec ( const Vec& parOther ) : implem::VecBase(parOther) { } Vec ( const vector_type& parIn ) : implem::VecBase(parIn) { } template explicit Vec ( const typename std::enable_if::value and not std::is_same::value, T>::type& parX ) : implem::VecBase(parX) { } #if defined(VWR_WITH_IMPLICIT_CONVERSIONS) template Vec ( const Vec& parOther ) { implem::assign(*this, parOther); } template Vec& operator= ( const Vec& parOther ) { return implem::assign(*this, parOther); } #endif Vec& operator= ( const Vec& parOther ) { return implem::assign_same_type(*this, parOther); } }; template class Vec : public implem::VecBase, public implem::VecAccessors { static_assert(std::is_standard_layout>::value, "Base class must be a standard layout type"); static_assert(std::is_standard_layout>::value, "Base class must be a standard layout type"); public: typedef typename implem::VecBase::scalar_type scalar_type; typedef typename implem::VecBase::vector_type vector_type; enum { dimensions = 2 }; static const Vec unit_x; static const Vec unit_y; Vec ( void ) = default; Vec ( const Vec& parOther ) : implem::VecBase(parOther) { } Vec ( const vector_type& parIn ) : implem::VecBase(parIn) { } explicit Vec ( const scalar_type parX ) : implem::VecBase(parX) { } Vec ( scalar_type parX, scalar_type parY ) : implem::VecBase(parX, parY) { } #if defined(VWR_WITH_IMPLICIT_CONVERSIONS) template Vec ( const Vec& parOther ) { implem::assign(*this, parOther); } template Vec& operator= ( const Vec& parOther ) { return implem::assign(*this, parOther); } #endif Vec& operator= ( const Vec& parOther ) { return implem::assign_same_type(*this, parOther); } Vec& operator= ( const vector_type& parOther ) { this->data() = parOther; return *this; } }; template class Vec : public implem::VecBase, public implem::VecAccessors { static_assert(std::is_standard_layout>::value, "Base class must be a standard layout type"); static_assert(std::is_standard_layout>::value, "Base class must be a standard layout type"); public: typedef typename implem::VecBase::scalar_type scalar_type; typedef typename implem::VecBase::vector_type vector_type; enum { dimensions = 3 }; static const Vec unit_x; static const Vec unit_y; static const Vec unit_z; Vec ( void ) = default; Vec ( const Vec& parOther ) : implem::VecBase(parOther) { } Vec ( const vector_type& parIn ) : implem::VecBase(parIn) { } explicit Vec ( const scalar_type parX ) : implem::VecBase(parX) { } Vec ( scalar_type parX, scalar_type parY, scalar_type parZ ) : implem::VecBase(parX, parY, parZ) { } #if defined(VWR_WITH_IMPLICIT_CONVERSIONS) template Vec ( const Vec& parOther ) { implem::assign(*this, parOther); } template Vec& operator= ( const Vec& parOther ) { return implem::assign(*this, parOther); } #endif Vec& operator= ( const Vec& parOther ) { return implem::assign_same_type(*this, parOther); } Vec& operator= ( const vector_type& parOther ) { this->data() = parOther; return *this; } }; template class Vec : public implem::VecBase, public implem::VecAccessors { static_assert(std::is_standard_layout>::value, "Base class must be a standard layout type"); static_assert(std::is_standard_layout>::value, "Base class must be a standard layout type"); public: typedef typename implem::VecBase::scalar_type scalar_type; typedef typename implem::VecBase::vector_type vector_type; enum { dimensions = 4 }; static const Vec unit_x; static const Vec unit_y; static const Vec unit_z; static const Vec unit_w; Vec ( void ) = default; Vec ( const Vec& parOther ) : implem::VecBase(parOther) { } Vec ( const vector_type& parIn ) : implem::VecBase(parIn) { } explicit Vec ( const scalar_type parX ) : implem::VecBase(parX) { } Vec ( scalar_type parX, scalar_type parY, scalar_type parZ, scalar_type parW ) : implem::VecBase(parX, parY, parZ, parW) { } #if defined(VWR_WITH_IMPLICIT_CONVERSIONS) template Vec ( const Vec& parOther ) { implem::assign(*this, parOther); } template Vec& operator= ( const Vec& parOther ) { return implem::assign(*this, parOther); } #endif Vec& operator= ( const Vec& parOther ) { return implem::assign_same_type(*this, parOther); } Vec& operator= ( const vector_type& parOther ) { this->data() = parOther; return *this; } }; template Vec mk_vec ( const V& parVec ); template bool operator== ( const Vec& parLeft, const Vec& parRight ); template bool operator!= ( const Vec& parLeft, const Vec& parRight ); template bool operator< ( const Vec& parLeft, const Vec& parRight ); template bool operator> ( const Vec& parLeft, const Vec& parRight ); template bool operator<= ( const Vec& parLeft, const Vec& parRight ); template bool operator>= ( const Vec& parLeft, const Vec& parRight ); template bool operator== ( const Vec& parLeft, const typename VectorWrapperInfo::scalar_type& parRight ); template bool operator< ( const Vec& parLeft, const typename VectorWrapperInfo::scalar_type& parRight ); template Vec operator- ( const Vec& parVec ); template bool operator> ( const Vec& parLeft, const T& parRight ); template bool operator<= ( const Vec& parLeft, const T& parRight ); template bool operator>= ( const Vec& parLeft, const T& parRight ); template bool operator!= ( const Vec& parLeft, const T& parRight ); template Vec::type> operator+ ( const Vec& parLeft, const Vec& parRight ); template Vec::type> operator- ( const Vec& parLeft, const Vec& parRight ); template Vec::type> operator* ( const Vec& parLeft, const Vec& parRight ); template Vec::type> operator/ ( const Vec& parLeft, const Vec& parRight ); template Vec::type> operator% ( const Vec& parLeft, const Vec& parRight ); template Vec operator+ ( const Vec& parLeft, const typename Vec::scalar_type& parRight ); template Vec operator- ( const Vec& parLeft, const typename Vec::scalar_type& parRight ); template Vec operator* ( const Vec& parLeft, const typename Vec::scalar_type& parRight ); template Vec operator/ ( const Vec& parLeft, const typename Vec::scalar_type& parRight ); template Vec operator% ( const Vec& parLeft, const typename Vec::scalar_type& parRight ); template Vec operator+ ( const typename Vec::scalar_type& parLeft, const Vec& parRight ); template Vec operator- ( const typename Vec::scalar_type& parLeft, const Vec& parRight ); template Vec operator* ( const typename Vec::scalar_type& parLeft, const Vec& parRight ); template Vec operator/ ( const typename Vec::scalar_type& parLeft, const Vec& parRight ); template Vec operator% ( const typename Vec::scalar_type& parLeft, const Vec& parRight ); } //namespace vwr #if defined VWR_OUTER_NAMESPACE } //namespace VWR_OUTER_NAMESPACE #endif #include "vectorwrapper/vectorwrapper.inl"