Move VecBase stuff to its own .inl file.
This commit is contained in:
parent
e0e167b658
commit
08378698b8
5 changed files with 304 additions and 271 deletions
|
@ -19,6 +19,8 @@
|
||||||
#include "implem_vec_common.hpp"
|
#include "implem_vec_common.hpp"
|
||||||
#include "sequence_bt.hpp"
|
#include "sequence_bt.hpp"
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#if defined VWR_OUTER_NAMESPACE
|
#if defined VWR_OUTER_NAMESPACE
|
||||||
namespace VWR_OUTER_NAMESPACE {
|
namespace VWR_OUTER_NAMESPACE {
|
||||||
|
@ -107,9 +109,63 @@ namespace vwr {
|
||||||
|
|
||||||
vector_type m_wrapped;
|
vector_type m_wrapped;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename T,
|
||||||
|
typename U,
|
||||||
|
size_type S=(
|
||||||
|
static_cast<int>(VectorWrapperInfo<T>::dimensions) < static_cast<int>(VectorWrapperInfo<U>::dimensions) ?
|
||||||
|
static_cast<int>(VectorWrapperInfo<T>::dimensions)
|
||||||
|
:
|
||||||
|
static_cast<int>(VectorWrapperInfo<U>::dimensions)
|
||||||
|
)
|
||||||
|
> struct have_compat_offsets;
|
||||||
|
template <typename T, typename U> struct have_compat_offsets<T, U, 1> {
|
||||||
|
enum {
|
||||||
|
value = true
|
||||||
|
};
|
||||||
|
};
|
||||||
|
template <typename T, typename U> struct have_compat_offsets<T, U, 2> {
|
||||||
|
enum {
|
||||||
|
value =
|
||||||
|
VectorWrapperInfo<T>::offset_x - min_offset<T>::value == VectorWrapperInfo<U>::offset_x - min_offset<U>::value and
|
||||||
|
VectorWrapperInfo<T>::offset_y - min_offset<T>::value == VectorWrapperInfo<U>::offset_y - min_offset<U>::value
|
||||||
|
};
|
||||||
|
};
|
||||||
|
template <typename T, typename U> struct have_compat_offsets<T, U, 3> {
|
||||||
|
enum {
|
||||||
|
value =
|
||||||
|
VectorWrapperInfo<T>::offset_x - min_offset<T>::value == VectorWrapperInfo<U>::offset_x - min_offset<U>::value and
|
||||||
|
VectorWrapperInfo<T>::offset_y - min_offset<T>::value == VectorWrapperInfo<U>::offset_y - min_offset<U>::value and
|
||||||
|
VectorWrapperInfo<T>::offset_z - min_offset<T>::value == VectorWrapperInfo<U>::offset_z - min_offset<U>::value
|
||||||
|
};
|
||||||
|
};
|
||||||
|
template <typename T, typename U> struct have_compat_offsets<T, U, 4> {
|
||||||
|
enum {
|
||||||
|
value =
|
||||||
|
VectorWrapperInfo<T>::offset_x - min_offset<T>::value == VectorWrapperInfo<U>::offset_x - min_offset<U>::value and
|
||||||
|
VectorWrapperInfo<T>::offset_y - min_offset<T>::value == VectorWrapperInfo<U>::offset_y - min_offset<U>::value and
|
||||||
|
VectorWrapperInfo<T>::offset_z - min_offset<T>::value == VectorWrapperInfo<U>::offset_z - min_offset<U>::value and
|
||||||
|
VectorWrapperInfo<T>::offset_w - min_offset<T>::value == VectorWrapperInfo<U>::offset_w - min_offset<U>::value
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
struct have_compat_layout {
|
||||||
|
enum {
|
||||||
|
value =
|
||||||
|
HasOffsetXEnum<VectorWrapperInfo<T>>::value and
|
||||||
|
HasOffsetXEnum<VectorWrapperInfo<U>>::value and
|
||||||
|
have_compat_offsets<T, U>::value
|
||||||
|
};
|
||||||
|
};
|
||||||
} //namespace implem
|
} //namespace implem
|
||||||
|
|
||||||
|
template <typename V> struct is_castable_to { };
|
||||||
} //namespace vwr
|
} //namespace vwr
|
||||||
|
|
||||||
#if defined VWR_OUTER_NAMESPACE
|
#if defined VWR_OUTER_NAMESPACE
|
||||||
} //namespace VWR_OUTER_NAMESPACE
|
} //namespace VWR_OUTER_NAMESPACE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "implem_vec_base.inl"
|
||||||
|
|
189
include/vectorwrapper/implem_vec_base.inl
Normal file
189
include/vectorwrapper/implem_vec_base.inl
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2015-2017 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 <typename T, bool=HasCastIgnoreTrailingPropertiesEnum<VectorWrapperInfo<T>>::value> struct IsCastIgnoreTrailingPropertiesSet;
|
||||||
|
template <typename T> struct IsCastIgnoreTrailingPropertiesSet<T, true> { static const bool value = static_cast<bool>(VectorWrapperInfo<T>::cast_ignore_trailing_properties); };
|
||||||
|
template <typename T> struct IsCastIgnoreTrailingPropertiesSet<T, false> { static const bool value = false; };
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
template <typename T>
|
||||||
|
VecBase<V>::VecBase (const T& parInit, typename std::enable_if<std::is_same<T, scalar_type>::value and not std::is_same<scalar_type, vector_type>::value, bool>::type) {
|
||||||
|
for (size_type z = 0; z < VectorWrapperInfo<V>::dimensions; ++z) {
|
||||||
|
VecGetter<V>::get_at(m_wrapped, z) = parInit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
VecBase<V>::VecBase (const vector_type& parInit) :
|
||||||
|
m_wrapped(parInit)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
template <typename... Args>
|
||||||
|
VecBase<V>::VecBase (scalar_type parX, scalar_type parY, Args... parArgs) {
|
||||||
|
static_assert(2 + sizeof...(Args) == dimensions, "Wrong number of parameters received");
|
||||||
|
VecGetter<V>::get_at(m_wrapped, 0) = parX;
|
||||||
|
VecGetter<V>::get_at(m_wrapped, 1) = parY;
|
||||||
|
|
||||||
|
assign_values(bt::number_range<size_type, 2, dimensions>(), std::forward<Args>(parArgs)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
template <size_type... I, typename... Args>
|
||||||
|
void VecBase<V>::assign_values (const bt::number_seq<size_type, I...>&, Args... parArgs) {
|
||||||
|
static_assert(sizeof...(I) == sizeof...(Args), "Argument count and indices count mismatch");
|
||||||
|
|
||||||
|
std::initializer_list<scalar_type> t {
|
||||||
|
(VecGetter<V>::get_at(m_wrapped, I) = parArgs)...
|
||||||
|
};
|
||||||
|
static_cast<void>(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
template <typename Op, typename V2, size_type... I>
|
||||||
|
void VecBase<V>::assign_values_op (Op parOp, const bt::number_seq<size_type, I...>& parSeq, const VecBase<V2>& parOther) {
|
||||||
|
this->assign_values(parSeq, parOp((*this)[I], parOther[I])...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
template <typename Op, size_type... I>
|
||||||
|
void VecBase<V>::assign_values_op_scalar (Op parOp, const bt::number_seq<size_type, I...>& parSeq, const scalar_type& parOther) {
|
||||||
|
this->assign_values(parSeq, parOp((*this)[I], parOther)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
auto VecBase<V>::operator[] (size_type parIndex) -> scalar_type& {
|
||||||
|
return VecGetter<V>::get_at(m_wrapped, parIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
auto VecBase<V>::operator[] (size_type parIndex) const -> const scalar_type& {
|
||||||
|
return VecGetter<V>::get_at(const_cast<vector_type&>(m_wrapped), parIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
template <typename V2>
|
||||||
|
auto VecBase<V>::cast() const -> const typename std::enable_if<is_vec<V2>::value and directly_convertible<V, V2>::value, V2>::type& {
|
||||||
|
static_assert(sizeof(V2) <= sizeof(VecBase<V>) - min_offset<V>::value, "V2 must fit in V starting from the first coordinate");
|
||||||
|
static_assert(std::is_standard_layout<V2>::value, "V2 must be a standard layout type");
|
||||||
|
static_assert(min_offset<typename is_vec<V2>::vector_type>::value == 0, "V2 must not have any properties before the first coordinate");
|
||||||
|
static_assert(have_compat_layout<V, typename is_vec<V2>::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<typename is_vec<V2>::vector_type>::scalar_type) * VectorWrapperInfo<typename is_vec<V2>::vector_type>::dimensions == sizeof(V2)) or
|
||||||
|
IsCastIgnoreTrailingPropertiesSet<typename is_vec<V2>::vector_type>::value,
|
||||||
|
"V2 must not have any properties past the last coordinate");
|
||||||
|
static_assert(alignof(typename VectorWrapperInfo<V>::scalar_type) == alignof(V2), "Casting to V2 would give you a misaligned variable");
|
||||||
|
|
||||||
|
return *reinterpret_cast<const V2*>(
|
||||||
|
reinterpret_cast<const char*>(this) + VectorWrapperInfo<V>::offset_x
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
template <typename V2>
|
||||||
|
auto VecBase<V>::cast() -> typename std::enable_if<is_vec<V2>::value and directly_convertible<V, V2>::value, V2>::type& {
|
||||||
|
return const_cast<V2&>(const_cast<const VecBase<V>*>(this)->cast<V2>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
template <typename V2>
|
||||||
|
auto VecBase<V>::cast() const -> const typename std::enable_if<is_vec<V2>::value and not directly_convertible<V, V2>::value, V2>::type& {
|
||||||
|
static_assert(std::is_standard_layout<V2>::value, "V2 must be a standard layout type");
|
||||||
|
typedef typename is_vec<V2>::vector_type v2_type;
|
||||||
|
static_assert(std::is_base_of<is_castable_to<typename VectorWrapperInfo<v2_type>::vector_type>, VectorWrapperInfo<V>>::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<typename is_vec<V2>::vector_type>::scalar_type) * VectorWrapperInfo<typename is_vec<V2>::vector_type>::dimensions == sizeof(V2)) or
|
||||||
|
IsCastIgnoreTrailingPropertiesSet<typename is_vec<V2>::vector_type>::value,
|
||||||
|
"V2 must not have any properties past the last coordinate");
|
||||||
|
static_assert(alignof(typename VectorWrapperInfo<V>::scalar_type) == alignof(V2), "Casting to V2 would give you a misaligned variable");
|
||||||
|
|
||||||
|
return *reinterpret_cast<const V2*>(
|
||||||
|
reinterpret_cast<const char*>(&(*this)[0])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
template <typename V2>
|
||||||
|
auto VecBase<V>::cast() -> typename std::enable_if<is_vec<V2>::value and not directly_convertible<V, V2>::value, V2>::type& {
|
||||||
|
return const_cast<V2&>(const_cast<const VecBase<V>*>(this)->cast<V2>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
template <typename V2>
|
||||||
|
VecBase<V>& VecBase<V>::operator+= (const VecBase<V2>& parOther) {
|
||||||
|
static_assert(static_cast<int>(VectorWrapperInfo<V>::dimensions) == static_cast<int>(VectorWrapperInfo<V2>::dimensions), "Dimensions mismatch");
|
||||||
|
this->assign_values_op(std::plus<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template <typename V>
|
||||||
|
template <typename V2>
|
||||||
|
VecBase<V>& VecBase<V>::operator-= (const VecBase<V2>& parOther) {
|
||||||
|
static_assert(static_cast<int>(VectorWrapperInfo<V>::dimensions) == static_cast<int>(VectorWrapperInfo<V2>::dimensions), "Dimensions mismatch");
|
||||||
|
this->assign_values_op(std::minus<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template <typename V>
|
||||||
|
template <typename V2>
|
||||||
|
VecBase<V>& VecBase<V>::operator*= (const VecBase<V2>& parOther) {
|
||||||
|
static_assert(static_cast<int>(VectorWrapperInfo<V>::dimensions) == static_cast<int>(VectorWrapperInfo<V2>::dimensions), "Dimensions mismatch");
|
||||||
|
this->assign_values_op(std::multiplies<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template <typename V>
|
||||||
|
template <typename V2>
|
||||||
|
VecBase<V>& VecBase<V>::operator/= (const VecBase<V2>& parOther) {
|
||||||
|
static_assert(static_cast<int>(VectorWrapperInfo<V>::dimensions) == static_cast<int>(VectorWrapperInfo<V2>::dimensions), "Dimensions mismatch");
|
||||||
|
this->assign_values_op(std::divides<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
VecBase<V>& VecBase<V>::operator+= (const scalar_type& parOther) {
|
||||||
|
this->assign_values_op_scalar(std::plus<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template <typename V>
|
||||||
|
VecBase<V>& VecBase<V>::operator-= (const scalar_type& parOther) {
|
||||||
|
this->assign_values_op_scalar(std::minus<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template <typename V>
|
||||||
|
VecBase<V>& VecBase<V>::operator*= (const scalar_type& parOther) {
|
||||||
|
this->assign_values_op_scalar(std::multiplies<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template <typename V>
|
||||||
|
VecBase<V>& VecBase<V>::operator/= (const scalar_type& parOther) {
|
||||||
|
this->assign_values_op_scalar(std::divides<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
} //namespace implem
|
||||||
|
} //namespace vwr
|
||||||
|
|
||||||
|
#if defined VWR_OUTER_NAMESPACE
|
||||||
|
} //namespace VWR_OUTER_NAMESPACE
|
||||||
|
#endif
|
|
@ -18,25 +18,75 @@
|
||||||
|
|
||||||
#include "size_type.hpp"
|
#include "size_type.hpp"
|
||||||
#include "has_method.hpp"
|
#include "has_method.hpp"
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#if defined VWR_OUTER_NAMESPACE
|
#if defined VWR_OUTER_NAMESPACE
|
||||||
namespace VWR_OUTER_NAMESPACE {
|
namespace VWR_OUTER_NAMESPACE {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace vwr {
|
namespace vwr {
|
||||||
|
template <typename V>
|
||||||
|
struct VectorWrapperInfo;
|
||||||
|
|
||||||
|
template <typename V, size_type S=VectorWrapperInfo<V>::dimensions>
|
||||||
|
class Vec;
|
||||||
|
|
||||||
namespace implem {
|
namespace implem {
|
||||||
define_has_typedef(lower_vector_type, LowerVec);
|
define_has_typedef(lower_vector_type, LowerVec);
|
||||||
define_has_typedef(higher_vector_type, HigherVec);
|
define_has_typedef(higher_vector_type, HigherVec);
|
||||||
define_has_enum(offset_x, OffsetX);
|
define_has_enum(offset_x, OffsetX);
|
||||||
define_has_method(get_at, GetAt);
|
define_has_method(get_at, GetAt);
|
||||||
define_has_enum(cast_ignore_trailing_properties, CastIgnoreTrailingProperties);
|
define_has_enum(cast_ignore_trailing_properties, CastIgnoreTrailingProperties);
|
||||||
|
|
||||||
|
template <typename T, bool=HasOffsetXEnum<VectorWrapperInfo<T>>::value and std::is_standard_layout<T>::value>
|
||||||
|
struct VecGetter;
|
||||||
|
template <typename T>
|
||||||
|
struct VecGetter<T, true> {
|
||||||
|
static typename VectorWrapperInfo<T>::scalar_type& get_at ( T& parVec, size_type parIndex );
|
||||||
|
};
|
||||||
|
template <typename T>
|
||||||
|
struct VecGetter<T, false> {
|
||||||
|
private:
|
||||||
|
static_assert(HasGetAtMethod<VectorWrapperInfo<T>>::value, "You must provide a get_at() static method for this vector_type");
|
||||||
|
typedef typename VectorWrapperInfo<T>::scalar_type scalar_type;
|
||||||
|
typedef T vector_type;
|
||||||
|
using get_at_func = decltype(&VectorWrapperInfo<T>::get_at)(size_type, vector_type&);
|
||||||
|
using get_at_rettype = typename std::result_of<get_at_func>::type;
|
||||||
|
|
||||||
|
static_assert(not std::is_rvalue_reference<get_at_rettype>::value, "rvalue ref return types not implemented");
|
||||||
|
static_assert(std::is_lvalue_reference<get_at_rettype>::value, "Read-only vectors not implemented");
|
||||||
|
|
||||||
|
public:
|
||||||
|
static get_at_rettype get_at ( T& parVec, size_type parIndex );
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, size_type I> struct get_offset_enum_from_index;
|
||||||
|
template <typename T> struct get_offset_enum_from_index<T, 0> {
|
||||||
|
enum { value = VectorWrapperInfo<T>::offset_x };
|
||||||
|
};
|
||||||
|
template <typename T> struct get_offset_enum_from_index<T, 1> {
|
||||||
|
enum { value = VectorWrapperInfo<T>::offset_y };
|
||||||
|
};
|
||||||
|
template <typename T> struct get_offset_enum_from_index<T, 2> {
|
||||||
|
enum { value = VectorWrapperInfo<T>::offset_z };
|
||||||
|
};
|
||||||
|
template <typename T> struct get_offset_enum_from_index<T, 3> {
|
||||||
|
enum { value = VectorWrapperInfo<T>::offset_w };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, size_type S=VectorWrapperInfo<T>::dimensions> struct min_offset {
|
||||||
|
enum {
|
||||||
|
value = (
|
||||||
|
static_cast<int>(get_offset_enum_from_index<T, S-1>::value) < static_cast<int>(min_offset<T, S-1>::value) ?
|
||||||
|
static_cast<int>(get_offset_enum_from_index<T, S-1>::value) :
|
||||||
|
static_cast<int>(min_offset<T, S-1>::value)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
template <typename T> struct min_offset<T, 1> {
|
||||||
|
enum { value = get_offset_enum_from_index<T, 0>::value };
|
||||||
|
};
|
||||||
} //namespace implem
|
} //namespace implem
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
struct VectorWrapperInfo;
|
|
||||||
|
|
||||||
template <typename V, size_type S=VectorWrapperInfo<V>::dimensions>
|
|
||||||
class Vec;
|
|
||||||
} //namespace vwr
|
} //namespace vwr
|
||||||
|
|
||||||
#if defined VWR_OUTER_NAMESPACE
|
#if defined VWR_OUTER_NAMESPACE
|
||||||
|
|
|
@ -16,14 +16,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "implem_vec_base.hpp"
|
|
||||||
#include "implem_vec_common.hpp"
|
|
||||||
#include "sequence_bt.hpp"
|
#include "sequence_bt.hpp"
|
||||||
#include "size_type.hpp"
|
#include "size_type.hpp"
|
||||||
|
#include "implem_vec_base.hpp"
|
||||||
|
#include "implem_vec_common.hpp"
|
||||||
#include <ciso646>
|
#include <ciso646>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#if defined VWR_OUTER_NAMESPACE
|
#if defined VWR_OUTER_NAMESPACE
|
||||||
namespace VWR_OUTER_NAMESPACE {
|
namespace VWR_OUTER_NAMESPACE {
|
||||||
|
@ -42,83 +43,6 @@ namespace vwr {
|
||||||
Vec<V1>& assign ( Vec<V1, D>& parLeft, const Vec<V2, D>& parRight );
|
Vec<V1>& assign ( Vec<V1, D>& parLeft, const Vec<V2, D>& parRight );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T, size_type I> struct get_offset_enum_from_index;
|
|
||||||
template <typename T> struct get_offset_enum_from_index<T, 0> {
|
|
||||||
enum { value = VectorWrapperInfo<T>::offset_x };
|
|
||||||
};
|
|
||||||
template <typename T> struct get_offset_enum_from_index<T, 1> {
|
|
||||||
enum { value = VectorWrapperInfo<T>::offset_y };
|
|
||||||
};
|
|
||||||
template <typename T> struct get_offset_enum_from_index<T, 2> {
|
|
||||||
enum { value = VectorWrapperInfo<T>::offset_z };
|
|
||||||
};
|
|
||||||
template <typename T> struct get_offset_enum_from_index<T, 3> {
|
|
||||||
enum { value = VectorWrapperInfo<T>::offset_w };
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, size_type S=VectorWrapperInfo<T>::dimensions> struct min_offset {
|
|
||||||
enum {
|
|
||||||
value = (
|
|
||||||
static_cast<int>(get_offset_enum_from_index<T, S-1>::value) < static_cast<int>(min_offset<T, S-1>::value) ?
|
|
||||||
static_cast<int>(get_offset_enum_from_index<T, S-1>::value) :
|
|
||||||
static_cast<int>(min_offset<T, S-1>::value)
|
|
||||||
)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
template <typename T> struct min_offset<T, 1> {
|
|
||||||
enum { value = get_offset_enum_from_index<T, 0>::value };
|
|
||||||
};
|
|
||||||
|
|
||||||
template <
|
|
||||||
typename T,
|
|
||||||
typename U,
|
|
||||||
size_type S=(
|
|
||||||
static_cast<int>(VectorWrapperInfo<T>::dimensions) < static_cast<int>(VectorWrapperInfo<U>::dimensions) ?
|
|
||||||
static_cast<int>(VectorWrapperInfo<T>::dimensions)
|
|
||||||
:
|
|
||||||
static_cast<int>(VectorWrapperInfo<U>::dimensions)
|
|
||||||
)
|
|
||||||
> struct have_compat_offsets;
|
|
||||||
template <typename T, typename U> struct have_compat_offsets<T, U, 1> {
|
|
||||||
enum {
|
|
||||||
value = true
|
|
||||||
};
|
|
||||||
};
|
|
||||||
template <typename T, typename U> struct have_compat_offsets<T, U, 2> {
|
|
||||||
enum {
|
|
||||||
value =
|
|
||||||
VectorWrapperInfo<T>::offset_x - min_offset<T>::value == VectorWrapperInfo<U>::offset_x - min_offset<U>::value and
|
|
||||||
VectorWrapperInfo<T>::offset_y - min_offset<T>::value == VectorWrapperInfo<U>::offset_y - min_offset<U>::value
|
|
||||||
};
|
|
||||||
};
|
|
||||||
template <typename T, typename U> struct have_compat_offsets<T, U, 3> {
|
|
||||||
enum {
|
|
||||||
value =
|
|
||||||
VectorWrapperInfo<T>::offset_x - min_offset<T>::value == VectorWrapperInfo<U>::offset_x - min_offset<U>::value and
|
|
||||||
VectorWrapperInfo<T>::offset_y - min_offset<T>::value == VectorWrapperInfo<U>::offset_y - min_offset<U>::value and
|
|
||||||
VectorWrapperInfo<T>::offset_z - min_offset<T>::value == VectorWrapperInfo<U>::offset_z - min_offset<U>::value
|
|
||||||
};
|
|
||||||
};
|
|
||||||
template <typename T, typename U> struct have_compat_offsets<T, U, 4> {
|
|
||||||
enum {
|
|
||||||
value =
|
|
||||||
VectorWrapperInfo<T>::offset_x - min_offset<T>::value == VectorWrapperInfo<U>::offset_x - min_offset<U>::value and
|
|
||||||
VectorWrapperInfo<T>::offset_y - min_offset<T>::value == VectorWrapperInfo<U>::offset_y - min_offset<U>::value and
|
|
||||||
VectorWrapperInfo<T>::offset_z - min_offset<T>::value == VectorWrapperInfo<U>::offset_z - min_offset<U>::value and
|
|
||||||
VectorWrapperInfo<T>::offset_w - min_offset<T>::value == VectorWrapperInfo<U>::offset_w - min_offset<U>::value
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename U>
|
|
||||||
struct have_compat_layout {
|
|
||||||
enum {
|
|
||||||
value =
|
|
||||||
HasOffsetXEnum<VectorWrapperInfo<T>>::value and
|
|
||||||
HasOffsetXEnum<VectorWrapperInfo<U>>::value and
|
|
||||||
have_compat_offsets<T, U>::value
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, size_type S=VectorWrapperInfo<T>::dimensions>
|
template <typename T, size_type S=VectorWrapperInfo<T>::dimensions>
|
||||||
struct offsets_array_wrapper {
|
struct offsets_array_wrapper {
|
||||||
template <size_type... I>
|
template <size_type... I>
|
||||||
|
@ -127,28 +51,6 @@ namespace vwr {
|
||||||
const std::array<unsigned int, S> offsets;
|
const std::array<unsigned int, S> offsets;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, bool=HasOffsetXEnum<VectorWrapperInfo<T>>::value and std::is_standard_layout<T>::value>
|
|
||||||
struct VecGetter;
|
|
||||||
template <typename T>
|
|
||||||
struct VecGetter<T, true> {
|
|
||||||
static typename VectorWrapperInfo<T>::scalar_type& get_at ( T& parVec, size_type parIndex );
|
|
||||||
};
|
|
||||||
template <typename T>
|
|
||||||
struct VecGetter<T, false> {
|
|
||||||
private:
|
|
||||||
static_assert(HasGetAtMethod<VectorWrapperInfo<T>>::value, "You must provide a get_at() static method for this vector_type");
|
|
||||||
typedef typename VectorWrapperInfo<T>::scalar_type scalar_type;
|
|
||||||
typedef T vector_type;
|
|
||||||
using get_at_func = decltype(&VectorWrapperInfo<T>::get_at)(size_type, vector_type&);
|
|
||||||
using get_at_rettype = typename std::result_of<get_at_func>::type;
|
|
||||||
|
|
||||||
static_assert(not std::is_rvalue_reference<get_at_rettype>::value, "rvalue ref return types not implemented");
|
|
||||||
static_assert(std::is_lvalue_reference<get_at_rettype>::value, "Read-only vectors not implemented");
|
|
||||||
|
|
||||||
public:
|
|
||||||
static get_at_rettype get_at ( T& parVec, size_type parIndex );
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename V, bool Enabled> struct Vec1Promotion;
|
template <typename V, bool Enabled> struct Vec1Promotion;
|
||||||
template <typename V> struct Vec1Promotion<V, false> { };
|
template <typename V> struct Vec1Promotion<V, false> { };
|
||||||
template <typename V> struct Vec1Promotion<V, true> {
|
template <typename V> struct Vec1Promotion<V, true> {
|
||||||
|
@ -265,8 +167,6 @@ namespace vwr {
|
||||||
Vec<typename std::common_type<V1, V2>::type> binary_op ( const Vec<V1>& parLeft, const Vec<V2>& parRight, Op parOp, const Vec<typename std::common_type<V1, V2>::type>& parLastVal, bt::number_seq<size_type, I...> );
|
Vec<typename std::common_type<V1, V2>::type> binary_op ( const Vec<V1>& parLeft, const Vec<V2>& parRight, Op parOp, const Vec<typename std::common_type<V1, V2>::type>& parLastVal, bt::number_seq<size_type, I...> );
|
||||||
} //namespace implem
|
} //namespace implem
|
||||||
|
|
||||||
template <typename V> struct is_castable_to { };
|
|
||||||
|
|
||||||
template <typename V, size_type S>
|
template <typename V, size_type S>
|
||||||
class Vec : public implem::VecBase<V> {
|
class Vec : public implem::VecBase<V> {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -20,168 +20,6 @@ namespace VWR_OUTER_NAMESPACE {
|
||||||
|
|
||||||
namespace vwr {
|
namespace vwr {
|
||||||
namespace implem {
|
namespace implem {
|
||||||
template <typename T, bool=HasCastIgnoreTrailingPropertiesEnum<VectorWrapperInfo<T>>::value> struct IsCastIgnoreTrailingPropertiesSet;
|
|
||||||
template <typename T> struct IsCastIgnoreTrailingPropertiesSet<T, true> { static const bool value = static_cast<bool>(VectorWrapperInfo<T>::cast_ignore_trailing_properties); };
|
|
||||||
template <typename T> struct IsCastIgnoreTrailingPropertiesSet<T, false> { static const bool value = false; };
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
template <typename T>
|
|
||||||
VecBase<V>::VecBase (const T& parInit, typename std::enable_if<std::is_same<T, scalar_type>::value and not std::is_same<scalar_type, vector_type>::value, bool>::type) {
|
|
||||||
for (size_type z = 0; z < VectorWrapperInfo<V>::dimensions; ++z) {
|
|
||||||
VecGetter<V>::get_at(m_wrapped, z) = parInit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
VecBase<V>::VecBase (const vector_type& parInit) :
|
|
||||||
m_wrapped(parInit)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
template <typename... Args>
|
|
||||||
VecBase<V>::VecBase (scalar_type parX, scalar_type parY, Args... parArgs) {
|
|
||||||
static_assert(2 + sizeof...(Args) == dimensions, "Wrong number of parameters received");
|
|
||||||
VecGetter<V>::get_at(m_wrapped, 0) = parX;
|
|
||||||
VecGetter<V>::get_at(m_wrapped, 1) = parY;
|
|
||||||
|
|
||||||
assign_values(bt::number_range<size_type, 2, dimensions>(), std::forward<Args>(parArgs)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
template <size_type... I, typename... Args>
|
|
||||||
void VecBase<V>::assign_values (const bt::number_seq<size_type, I...>&, Args... parArgs) {
|
|
||||||
static_assert(sizeof...(I) == sizeof...(Args), "Argument count and indices count mismatch");
|
|
||||||
|
|
||||||
std::initializer_list<scalar_type> t {
|
|
||||||
(VecGetter<V>::get_at(m_wrapped, I) = parArgs)...
|
|
||||||
};
|
|
||||||
static_cast<void>(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
template <typename Op, typename V2, size_type... I>
|
|
||||||
void VecBase<V>::assign_values_op (Op parOp, const bt::number_seq<size_type, I...>& parSeq, const VecBase<V2>& parOther) {
|
|
||||||
this->assign_values(parSeq, parOp((*this)[I], parOther[I])...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
template <typename Op, size_type... I>
|
|
||||||
void VecBase<V>::assign_values_op_scalar (Op parOp, const bt::number_seq<size_type, I...>& parSeq, const scalar_type& parOther) {
|
|
||||||
this->assign_values(parSeq, parOp((*this)[I], parOther)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
auto VecBase<V>::operator[] (size_type parIndex) -> scalar_type& {
|
|
||||||
return VecGetter<V>::get_at(m_wrapped, parIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
auto VecBase<V>::operator[] (size_type parIndex) const -> const scalar_type& {
|
|
||||||
return VecGetter<V>::get_at(const_cast<vector_type&>(m_wrapped), parIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
template <typename V2>
|
|
||||||
auto VecBase<V>::cast() const -> const typename std::enable_if<is_vec<V2>::value and directly_convertible<V, V2>::value, V2>::type& {
|
|
||||||
static_assert(sizeof(V2) <= sizeof(VecBase<V>) - min_offset<V>::value, "V2 must fit in V starting from the first coordinate");
|
|
||||||
static_assert(std::is_standard_layout<V2>::value, "V2 must be a standard layout type");
|
|
||||||
static_assert(min_offset<typename is_vec<V2>::vector_type>::value == 0, "V2 must not have any properties before the first coordinate");
|
|
||||||
static_assert(have_compat_layout<V, typename is_vec<V2>::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<typename is_vec<V2>::vector_type>::scalar_type) * VectorWrapperInfo<typename is_vec<V2>::vector_type>::dimensions == sizeof(V2)) or
|
|
||||||
IsCastIgnoreTrailingPropertiesSet<typename is_vec<V2>::vector_type>::value,
|
|
||||||
"V2 must not have any properties past the last coordinate");
|
|
||||||
static_assert(alignof(typename VectorWrapperInfo<V>::scalar_type) == alignof(V2), "Casting to V2 would give you a misaligned variable");
|
|
||||||
|
|
||||||
return *reinterpret_cast<const V2*>(
|
|
||||||
reinterpret_cast<const char*>(this) + VectorWrapperInfo<V>::offset_x
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
template <typename V2>
|
|
||||||
auto VecBase<V>::cast() -> typename std::enable_if<is_vec<V2>::value and directly_convertible<V, V2>::value, V2>::type& {
|
|
||||||
return const_cast<V2&>(const_cast<const VecBase<V>*>(this)->cast<V2>());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
template <typename V2>
|
|
||||||
auto VecBase<V>::cast() const -> const typename std::enable_if<is_vec<V2>::value and not directly_convertible<V, V2>::value, V2>::type& {
|
|
||||||
static_assert(std::is_standard_layout<V2>::value, "V2 must be a standard layout type");
|
|
||||||
typedef typename is_vec<V2>::vector_type v2_type;
|
|
||||||
static_assert(std::is_base_of<is_castable_to<typename VectorWrapperInfo<v2_type>::vector_type>, VectorWrapperInfo<V>>::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<typename is_vec<V2>::vector_type>::scalar_type) * VectorWrapperInfo<typename is_vec<V2>::vector_type>::dimensions == sizeof(V2)) or
|
|
||||||
IsCastIgnoreTrailingPropertiesSet<typename is_vec<V2>::vector_type>::value,
|
|
||||||
"V2 must not have any properties past the last coordinate");
|
|
||||||
static_assert(alignof(typename VectorWrapperInfo<V>::scalar_type) == alignof(V2), "Casting to V2 would give you a misaligned variable");
|
|
||||||
|
|
||||||
return *reinterpret_cast<const V2*>(
|
|
||||||
reinterpret_cast<const char*>(&(*this)[0])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
template <typename V2>
|
|
||||||
auto VecBase<V>::cast() -> typename std::enable_if<is_vec<V2>::value and not directly_convertible<V, V2>::value, V2>::type& {
|
|
||||||
return const_cast<V2&>(const_cast<const VecBase<V>*>(this)->cast<V2>());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
template <typename V2>
|
|
||||||
VecBase<V>& VecBase<V>::operator+= (const VecBase<V2>& parOther) {
|
|
||||||
static_assert(static_cast<int>(VectorWrapperInfo<V>::dimensions) == static_cast<int>(VectorWrapperInfo<V2>::dimensions), "Dimensions mismatch");
|
|
||||||
this->assign_values_op(std::plus<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
template <typename V>
|
|
||||||
template <typename V2>
|
|
||||||
VecBase<V>& VecBase<V>::operator-= (const VecBase<V2>& parOther) {
|
|
||||||
static_assert(static_cast<int>(VectorWrapperInfo<V>::dimensions) == static_cast<int>(VectorWrapperInfo<V2>::dimensions), "Dimensions mismatch");
|
|
||||||
this->assign_values_op(std::minus<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
template <typename V>
|
|
||||||
template <typename V2>
|
|
||||||
VecBase<V>& VecBase<V>::operator*= (const VecBase<V2>& parOther) {
|
|
||||||
static_assert(static_cast<int>(VectorWrapperInfo<V>::dimensions) == static_cast<int>(VectorWrapperInfo<V2>::dimensions), "Dimensions mismatch");
|
|
||||||
this->assign_values_op(std::multiplies<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
template <typename V>
|
|
||||||
template <typename V2>
|
|
||||||
VecBase<V>& VecBase<V>::operator/= (const VecBase<V2>& parOther) {
|
|
||||||
static_assert(static_cast<int>(VectorWrapperInfo<V>::dimensions) == static_cast<int>(VectorWrapperInfo<V2>::dimensions), "Dimensions mismatch");
|
|
||||||
this->assign_values_op(std::divides<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
VecBase<V>& VecBase<V>::operator+= (const scalar_type& parOther) {
|
|
||||||
this->assign_values_op_scalar(std::plus<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
template <typename V>
|
|
||||||
VecBase<V>& VecBase<V>::operator-= (const scalar_type& parOther) {
|
|
||||||
this->assign_values_op_scalar(std::minus<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
template <typename V>
|
|
||||||
VecBase<V>& VecBase<V>::operator*= (const scalar_type& parOther) {
|
|
||||||
this->assign_values_op_scalar(std::multiplies<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
template <typename V>
|
|
||||||
VecBase<V>& VecBase<V>::operator/= (const scalar_type& parOther) {
|
|
||||||
this->assign_values_op_scalar(std::divides<scalar_type>(), bt::number_range<size_type, 0, VectorWrapperInfo<V>::dimensions>(), parOther);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename VectorWrapperInfo<T>::scalar_type& VecGetter<T, true>::get_at (T& parVec, size_type parIndex) {
|
typename VectorWrapperInfo<T>::scalar_type& VecGetter<T, true>::get_at (T& parVec, size_type parIndex) {
|
||||||
assert(parIndex < VectorWrapperInfo<T>::dimensions);
|
assert(parIndex < VectorWrapperInfo<T>::dimensions);
|
||||||
|
|
Loading…
Add table
Reference in a new issue