/* * 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. */ #if defined VWR_OUTER_NAMESPACE namespace VWR_OUTER_NAMESPACE { #endif namespace vwr { namespace implem { template struct AssignWrapped { static void assign (T& dst, const T& src) { dst = src; } }; template struct AssignWrapped { static void assign (T (&dst)[N], const T (&src)[N]) { for (unsigned int z = 0; z < N; ++z) { dst[z] = src[z]; } } }; template typename VectorWrapperInfo::scalar_type& VecGetter::get_at (T& parVec, size_type parIndex) { assert(parIndex < VectorWrapperInfo::dimensions); typedef T vector_type; typedef typename VectorWrapperInfo::scalar_type scalar_type; static_assert(std::is_standard_layout::value, "Can't use this function with this vector_type"); const offsets_array_wrapper oaw((bt::number_range::dimensions>())); return *reinterpret_cast(reinterpret_cast(&parVec) + oaw.offsets[parIndex]); } template auto VecGetter::get_at (T& parVec, size_type parIndex) -> get_at_rettype { assert(parIndex < VectorWrapperInfo::dimensions); return VectorWrapperInfo::get_at(parIndex, parVec); } template inline Vec& assign (Vec& parLeft, const Vec& parRight) { for (size_type z = 0; z < D; ++z) { #if defined(VWR_WITH_UNCASTED_ASSIGNMENT) parLeft[z] = parRight[z]; #else parLeft[z] = static_cast::scalar_type>(parRight[z]); #endif } return parLeft; } template Vec& assign_same_type (Vec& parLeft, const Vec& parRight) { implem::AssignWrapped::assign(parLeft.data(), parRight.data()); return parLeft; } template auto Vec3Demotion::xy() const -> lower_vector_type { auto& this_vec = *static_cast*>(this); return lower_vector_type(this_vec[0], this_vec[1]); } template auto Vec3Demotion::xz() const -> lower_vector_type { auto& this_vec = *static_cast*>(this); return lower_vector_type(this_vec[0], this_vec[2]); } template auto Vec3Demotion::yz() const -> lower_vector_type { auto& this_vec = *static_cast*>(this); return lower_vector_type(this_vec[1], this_vec[2]); } template auto Vec4Demotion::xyz() const -> lower_vector_type { auto& this_vec = *static_cast*>(this); return lower_vector_type(this_vec[0], this_vec[1], this_vec[2]); } template auto Vec4Demotion::xyw() const -> lower_vector_type { auto& this_vec = *static_cast*>(this); return lower_vector_type(this_vec[0], this_vec[1], this_vec[3]); } template auto Vec4Demotion::xzw() const -> lower_vector_type { auto& this_vec = *static_cast*>(this); return lower_vector_type(this_vec[0], this_vec[2], this_vec[3]); } template auto Vec4Demotion::yzw() const -> lower_vector_type { auto& this_vec = *static_cast*>(this); return lower_vector_type(this_vec[1], this_vec[2], this_vec[3]); } template auto Vec1Promotion::xn (const scalar_type& parN) const -> higher_vector_type { auto& this_vec = *static_cast*>(this); return higher_vector_type(this_vec[0], parN); } template auto Vec1Promotion::nx (const scalar_type& parN) const -> higher_vector_type { auto& this_vec = *static_cast*>(this); return higher_vector_type(parN, this_vec[0]); } template auto Vec2Promotion::xyn (const scalar_type& parN) const -> higher_vector_type { auto& this_vec = *static_cast*>(this); return higher_vector_type(this_vec[0], this_vec[1], parN); } template auto Vec3Promotion::xyzw (const scalar_type& parW) const -> higher_vector_type { auto& this_vec = *static_cast*>(this); return higher_vector_type(this_vec[0], this_vec[1], this_vec[2], parW); } template auto VecAccessors::x() -> scalar_type& { auto& this_vec = *static_cast*>(this); return this_vec[0]; } template auto VecAccessors::x() const -> const scalar_type& { const auto& this_vec = *static_cast*>(this); return this_vec[0]; } template auto VecAccessors::x() -> scalar_type& { auto& this_vec = *static_cast*>(this); return this_vec[0]; } template auto VecAccessors::x() const -> const scalar_type& { const auto& this_vec = *static_cast*>(this); return this_vec[0]; } template auto VecAccessors::y() -> scalar_type& { auto& this_vec = *static_cast*>(this); return this_vec[1]; } template auto VecAccessors::y() const -> const scalar_type& { const auto& this_vec = *static_cast*>(this); return this_vec[1]; } template auto VecAccessors::x() -> scalar_type& { auto& this_vec = *static_cast*>(this); return this_vec[0]; } template auto VecAccessors::x() const -> const scalar_type& { const auto& this_vec = *static_cast*>(this); return this_vec[0]; } template auto VecAccessors::y() -> scalar_type& { auto& this_vec = *static_cast*>(this); return this_vec[1]; } template auto VecAccessors::y() const -> const scalar_type& { const auto& this_vec = *static_cast*>(this); return this_vec[1]; } template auto VecAccessors::z() -> scalar_type& { auto& this_vec = *static_cast*>(this); return this_vec[2]; } template auto VecAccessors::z() const -> const scalar_type& { const auto& this_vec = *static_cast*>(this); return this_vec[2]; } template auto VecAccessors::x() -> scalar_type& { auto& this_vec = *static_cast*>(this); return this_vec[0]; } template auto VecAccessors::x() const -> const scalar_type& { const auto& this_vec = *static_cast*>(this); return this_vec[0]; } template auto VecAccessors::y() -> scalar_type& { auto& this_vec = *static_cast*>(this); return this_vec[1]; } template auto VecAccessors::y() const -> const scalar_type& { const auto& this_vec = *static_cast*>(this); return this_vec[1]; } template auto VecAccessors::z() -> scalar_type& { auto& this_vec = *static_cast*>(this); return this_vec[2]; } template auto VecAccessors::z() const -> const scalar_type& { const auto& this_vec = *static_cast*>(this); return this_vec[2]; } template auto VecAccessors::w() -> scalar_type& { auto& this_vec = *static_cast*>(this); return this_vec[3]; } template auto VecAccessors::w() const -> const scalar_type& { const auto& this_vec = *static_cast*>(this); return this_vec[3]; } template template offsets_array_wrapper::offsets_array_wrapper (const bt::number_seq&) : offsets({get_offset_enum_from_index::value...}) { static_assert(sizeof...(I) == S, "Bug?"); } template inline constexpr bool compare (const Vec&, const Vec&, ComposeOp, Op, bt::number_seq) { return LastVal; } template inline bool compare (const Vec& parLeft, const Vec& parRight, ComposeOp parComposeOp, Op parOp, bt::number_seq) { static_assert(I1 < VectorWrapperInfo::dimensions, "Index out of range"); return parComposeOp(parOp(parLeft[I1], parRight[I1]), compare(parLeft, parRight, parComposeOp, parOp, bt::number_seq())); } template inline Vec::type> binary_op (const Vec& parLeft, const Vec& parRight, Op parOp, bt::number_seq) { typedef Vec::type> return_type; return return_type(parOp(parLeft[I], parRight[I])...); } template inline Vec binary_op_scalar_right (const Vec& parLeft, const typename Vec::scalar_type& parRight, Op parOp, bt::number_seq) { typedef Vec return_type; return return_type(parOp(parLeft[I], parRight)...); } template inline Vec binary_op_scalar_left (const typename Vec::scalar_type& parLeft, const Vec& parRight, Op parOp, bt::number_seq) { typedef Vec return_type; return return_type(parOp(parLeft, parRight[I])...); } template inline Vec unary_operator_minus (const Vec& parVec, bt::number_seq) { return Vec(-parVec[I]...); } } //namespace implem template const Vec Vec::unit_x(scalar_type(1)); template const Vec Vec::unit_x(scalar_type(1), scalar_type(0)); template const Vec Vec::unit_y(scalar_type(0), scalar_type(1)); template const Vec Vec::unit_x(scalar_type(1), scalar_type(0), scalar_type(0)); template const Vec Vec::unit_y(scalar_type(0), scalar_type(1), scalar_type(0)); template const Vec Vec::unit_z(scalar_type(0), scalar_type(0), scalar_type(1)); template const Vec Vec::unit_x(scalar_type(1), scalar_type(0), scalar_type(0), scalar_type(0)); template const Vec Vec::unit_y(scalar_type(0), scalar_type(1), scalar_type(0), scalar_type(0)); template const Vec Vec::unit_z(scalar_type(0), scalar_type(0), scalar_type(1), scalar_type(0)); template const Vec Vec::unit_w(scalar_type(0), scalar_type(0), scalar_type(0), scalar_type(1)); template Vec mk_vec (const V& parVec) { return Vec(parVec); } template inline bool operator== (const Vec& parLeft, const Vec& parRight) { static_assert(static_cast(VectorWrapperInfo::dimensions) == static_cast(VectorWrapperInfo::dimensions), "Dimensions mismatch"); typedef typename std::common_type::scalar_type, typename VectorWrapperInfo::scalar_type>::type scalar_type; return implem::compare( parLeft, parRight, std::logical_and(), std::equal_to(), bt::number_range::dimensions>() ); } template inline bool operator!= (const Vec& parLeft, const Vec& parRight) { static_assert(static_cast(VectorWrapperInfo::dimensions) == static_cast(VectorWrapperInfo::dimensions), "Dimensions mismatch"); typedef typename std::common_type::scalar_type, typename VectorWrapperInfo::scalar_type>::type scalar_type; return implem::compare( parLeft, parRight, std::logical_or(), std::not_equal_to(), bt::number_range::dimensions>() ); } template inline bool operator< (const Vec& parLeft, const Vec& parRight) { static_assert(static_cast(VectorWrapperInfo::dimensions) == static_cast(VectorWrapperInfo::dimensions), "Dimensions mismatch"); typedef typename std::common_type::scalar_type, typename VectorWrapperInfo::scalar_type>::type scalar_type; return implem::compare( parLeft, parRight, std::logical_and(), std::less(), bt::number_range::dimensions>() ); } template inline bool operator> (const Vec& parLeft, const Vec& parRight) { static_assert(static_cast(VectorWrapperInfo::dimensions) == static_cast(VectorWrapperInfo::dimensions), "Dimensions mismatch"); typedef typename std::common_type::scalar_type, typename VectorWrapperInfo::scalar_type>::type scalar_type; return implem::compare( parLeft, parRight, std::logical_and(), std::greater(), bt::number_range::dimensions>() ); } template inline bool operator<= (const Vec& parLeft, const Vec& parRight) { static_assert(static_cast(VectorWrapperInfo::dimensions) == static_cast(VectorWrapperInfo::dimensions), "Dimensions mismatch"); typedef typename std::common_type::scalar_type, typename VectorWrapperInfo::scalar_type>::type scalar_type; return implem::compare( parLeft, parRight, std::logical_and(), std::less_equal(), bt::number_range::dimensions>() ); } template inline bool operator>= (const Vec& parLeft, const Vec& parRight) { static_assert(static_cast(VectorWrapperInfo::dimensions) == static_cast(VectorWrapperInfo::dimensions), "Dimensions mismatch"); typedef typename std::common_type::scalar_type, typename VectorWrapperInfo::scalar_type>::type scalar_type; return implem::compare( parLeft, parRight, std::logical_and(), std::greater_equal(), bt::number_range::dimensions>() ); } template inline bool operator== (const Vec& parLeft, const typename VectorWrapperInfo::scalar_type& parRight) { bool retval = true; for (size_type z = 0; z < VectorWrapperInfo::dimensions; ++z) { retval &= (parLeft[z] == parRight); } return retval; } template inline bool operator< ( const Vec& parLeft, const typename VectorWrapperInfo::scalar_type& parRight) { bool retval = true; for (size_type z = 0; z < VectorWrapperInfo::dimensions; ++z) { retval &= (parLeft[z] < parRight); } return retval; } template inline Vec operator- (const Vec& parVec) { return implem::unary_operator_minus(parVec, bt::number_range::dimensions>()); } template inline bool operator> (const Vec& parLeft, const T& parRight) { return not (parLeft < parRight) and not (parLeft == parRight); } template inline bool operator<= (const Vec& parLeft, const T& parRight) { return (parLeft < parRight) or (parLeft == parRight); } template inline bool operator>= (const Vec& parLeft, const T& parRight) { return not (parLeft < parRight); } template inline bool operator!= (const Vec& parLeft, const T& parRight) { return not (parLeft == parRight); } template inline Vec::type> operator+ (const Vec& parLeft, const Vec& parRight) { static_assert(static_cast(VectorWrapperInfo::dimensions) == static_cast(VectorWrapperInfo::dimensions), "Dimensions mismatch"); return implem::binary_op( parLeft, parRight, std::plus::scalar_type, typename VectorWrapperInfo::scalar_type>::type>(), bt::number_range::dimensions>() ); } template inline Vec::type> operator- (const Vec& parLeft, const Vec& parRight) { static_assert(static_cast(VectorWrapperInfo::dimensions) == static_cast(VectorWrapperInfo::dimensions), "Dimensions mismatch"); return implem::binary_op( parLeft, parRight, std::minus::scalar_type, typename VectorWrapperInfo::scalar_type>::type>(), bt::number_range::dimensions>() ); } template inline Vec::type> operator* (const Vec& parLeft, const Vec& parRight) { static_assert(static_cast(VectorWrapperInfo::dimensions) == static_cast(VectorWrapperInfo::dimensions), "Dimensions mismatch"); return implem::binary_op( parLeft, parRight, std::multiplies::scalar_type, typename VectorWrapperInfo::scalar_type>::type>(), bt::number_range::dimensions>() ); } template inline Vec::type> operator/ (const Vec& parLeft, const Vec& parRight) { static_assert(static_cast(VectorWrapperInfo::dimensions) == static_cast(VectorWrapperInfo::dimensions), "Dimensions mismatch"); return implem::binary_op( parLeft, parRight, std::divides::scalar_type, typename VectorWrapperInfo::scalar_type>::type>(), bt::number_range::dimensions>() ); } template inline Vec::type> operator% (const Vec& parLeft, const Vec& parRight) { static_assert(static_cast(VectorWrapperInfo::dimensions) == static_cast(VectorWrapperInfo::dimensions), "Dimensions mismatch"); return implem::binary_op( parLeft, parRight, std::modulus::scalar_type, typename VectorWrapperInfo::scalar_type>::type>(), bt::number_range::dimensions>() ); } template inline Vec operator+ (const Vec& parLeft, const typename Vec::scalar_type& parRight) { return implem::binary_op_scalar_right( parLeft, parRight, std::plus::scalar_type>(), bt::number_range::dimensions>() ); } template inline Vec operator- (const Vec& parLeft, const typename Vec::scalar_type& parRight) { return implem::binary_op_scalar_right( parLeft, parRight, std::minus::scalar_type>(), bt::number_range::dimensions>() ); } template inline Vec operator* (const Vec& parLeft, const typename Vec::scalar_type& parRight) { return implem::binary_op_scalar_right( parLeft, parRight, std::multiplies::scalar_type>(), bt::number_range::dimensions>() ); } template inline Vec operator/ (const Vec& parLeft, const typename Vec::scalar_type& parRight) { return implem::binary_op_scalar_right( parLeft, parRight, std::divides::scalar_type>(), bt::number_range::dimensions>() ); } template inline Vec operator% (const Vec& parLeft, const typename Vec::scalar_type& parRight) { return implem::binary_op_scalar_right( parLeft, parRight, std::modulus::scalar_type>(), bt::number_range::dimensions>() ); } template inline Vec operator+ (const typename Vec::scalar_type& parLeft, const Vec& parRight) { return implem::binary_op_scalar_left( parLeft, parRight, std::plus::scalar_type>(), bt::number_range::dimensions>() ); } template inline Vec operator- (const typename Vec::scalar_type& parLeft, const Vec& parRight) { return implem::binary_op_scalar_left( parLeft, parRight, std::minus::scalar_type>(), bt::number_range::dimensions>() ); } template inline Vec operator* (const typename Vec::scalar_type& parLeft, const Vec& parRight) { return implem::binary_op_scalar_left( parLeft, parRight, std::multiplies::scalar_type>(), bt::number_range::dimensions>() ); } template inline Vec operator/ (const typename Vec::scalar_type& parLeft, const Vec& parRight) { return implem::binary_op_scalar_left( parLeft, parRight, std::divides::scalar_type>(), bt::number_range::dimensions>() ); } template inline Vec operator% (const typename Vec::scalar_type& parLeft, const Vec& parRight) { return implem::binary_op_scalar_left( parLeft, parRight, std::modulus::scalar_type>(), bt::number_range::dimensions>() ); } } //namespace vwr #if defined VWR_OUTER_NAMESPACE } //namespace VWR_OUTER_NAMESPACE #endif