/* * 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 >::value> struct IsCastIgnoreTrailingPropertiesSet; template struct IsCastIgnoreTrailingPropertiesSet { static const bool value = static_cast(VectorWrapperInfo::cast_ignore_trailing_properties); }; template struct IsCastIgnoreTrailingPropertiesSet { static const bool value = false; }; template template VecBase::VecBase (const T& parInit, typename std::enable_if::value and not std::is_same::value, bool>::type) { for (size_type z = 0; z < VectorWrapperInfo::dimensions; ++z) { VecGetter::get_at(data(), z) = parInit; } } template VecBase::VecBase (const vector_type& parInit) : VecBaseStorage(parInit) { if constexpr (not VecBaseStorage::IsWrappedCopyConstructible) { for (size_type z = 0; z < dimensions; ++z) { (*this)[z] = parInit[z]; } } } template template VecBase::VecBase (scalar_type parX, scalar_type parY, Args... parArgs) { static_assert(2 + sizeof...(Args) == dimensions, "Wrong number of parameters received"); VecGetter::get_at(data(), 0) = parX; VecGetter::get_at(data(), 1) = parY; assign_values(bt::number_range(), std::forward(parArgs)...); } template template void VecBase::assign_values (const bt::number_seq&, Args... parArgs) { static_assert(sizeof...(I) == sizeof...(Args), "Argument count and indices count mismatch"); std::initializer_list t { (VecGetter::get_at(data(), I) = parArgs)... }; static_cast(t); } template template void VecBase::assign_values_op (Op parOp, const bt::number_seq& parSeq, const VecBase& parOther) { this->assign_values(parSeq, parOp((*this)[I], parOther[I])...); } template template void VecBase::assign_values_op_scalar (Op parOp, const bt::number_seq& parSeq, const scalar_type& parOther) { this->assign_values(parSeq, parOp((*this)[I], parOther)...); } template auto VecBase::operator[] (size_type parIndex) -> scalar_type& { return VecGetter::get_at(data(), parIndex); } template auto VecBase::operator[] (size_type parIndex) const -> const scalar_type& { return VecGetter::get_at(const_cast(data()), parIndex); } template template auto VecBase::cast() const -> const typename std::enable_if::value and directly_convertible::value, V2>::type& { static_assert(sizeof(V2) <= sizeof(VecBase) - min_offset::value, "V2 must fit in V starting from the first coordinate"); static_assert(std::is_standard_layout::value, "V2 must be a standard layout type"); static_assert(min_offset::vector_type>::value == 0, "V2 must not have any properties before the first coordinate"); static_assert(have_compat_layout::vector_type>::value, "V is not suitable for casting to V2"); //Assert that V2 won't stomp on part of V's data, unless the user //has explicitly said he doesn't care. static_assert((sizeof(typename VectorWrapperInfo::vector_type>::scalar_type) * VectorWrapperInfo::vector_type>::dimensions == sizeof(V2)) or IsCastIgnoreTrailingPropertiesSet::vector_type>::value, "V2 must not have any properties past the last coordinate"); static_assert(alignof(typename VectorWrapperInfo::scalar_type) == alignof(V2), "Casting to V2 would give you a misaligned variable"); return *reinterpret_cast( reinterpret_cast(this) + VectorWrapperInfo::offset_x ); } template template auto VecBase::cast() -> typename std::enable_if::value and directly_convertible::value, V2>::type& { return const_cast(const_cast*>(this)->cast()); } template template auto VecBase::cast() const -> const typename std::enable_if::value and not directly_convertible::value, V2>::type& { static_assert(std::is_standard_layout::value, "V2 must be a standard layout type"); typedef typename is_vec::vector_type v2_type; static_assert(std::is_base_of::vector_type>, VectorWrapperInfo>::value, "Casting for this type has to be explicitly enabled"); //Assert that V2 won't stomp on part of V's data, unless the user //has explicitly said he doesn't care. static_assert((sizeof(typename VectorWrapperInfo::vector_type>::scalar_type) * VectorWrapperInfo::vector_type>::dimensions == sizeof(V2)) or IsCastIgnoreTrailingPropertiesSet::vector_type>::value, "V2 must not have any properties past the last coordinate"); static_assert(alignof(typename VectorWrapperInfo::scalar_type) == alignof(V2), "Casting to V2 would give you a misaligned variable"); return *reinterpret_cast( reinterpret_cast(&(*this)[0]) ); } template template auto VecBase::cast() -> typename std::enable_if::value and not directly_convertible::value, V2>::type& { return const_cast(const_cast*>(this)->cast()); } template template VecBase& VecBase::operator+= (const VecBase& parOther) { static_assert(static_cast(VectorWrapperInfo::dimensions) == static_cast(VectorWrapperInfo::dimensions), "Dimensions mismatch"); this->assign_values_op(std::plus(), bt::number_range::dimensions>(), parOther); return *this; } template template VecBase& VecBase::operator-= (const VecBase& parOther) { static_assert(static_cast(VectorWrapperInfo::dimensions) == static_cast(VectorWrapperInfo::dimensions), "Dimensions mismatch"); this->assign_values_op(std::minus(), bt::number_range::dimensions>(), parOther); return *this; } template template VecBase& VecBase::operator*= (const VecBase& parOther) { static_assert(static_cast(VectorWrapperInfo::dimensions) == static_cast(VectorWrapperInfo::dimensions), "Dimensions mismatch"); this->assign_values_op(std::multiplies(), bt::number_range::dimensions>(), parOther); return *this; } template template VecBase& VecBase::operator/= (const VecBase& parOther) { static_assert(static_cast(VectorWrapperInfo::dimensions) == static_cast(VectorWrapperInfo::dimensions), "Dimensions mismatch"); this->assign_values_op(std::divides(), bt::number_range::dimensions>(), parOther); return *this; } template VecBase& VecBase::operator+= (const scalar_type& parOther) { this->assign_values_op_scalar(std::plus(), bt::number_range::dimensions>(), parOther); return *this; } template VecBase& VecBase::operator-= (const scalar_type& parOther) { this->assign_values_op_scalar(std::minus(), bt::number_range::dimensions>(), parOther); return *this; } template VecBase& VecBase::operator*= (const scalar_type& parOther) { this->assign_values_op_scalar(std::multiplies(), bt::number_range::dimensions>(), parOther); return *this; } template VecBase& VecBase::operator/= (const scalar_type& parOther) { this->assign_values_op_scalar(std::divides(), bt::number_range::dimensions>(), parOther); return *this; } template inline VecBase::VecBase (const VecBase& parOther) : VecBase(parOther.data()) { } } //namespace implem } //namespace vwr #if defined VWR_OUTER_NAMESPACE } //namespace VWR_OUTER_NAMESPACE #endif