diff --git a/src/include/ranges/urange.cc.h b/src/include/ranges/urange.cc.h index 4868f63..9fbb02d 100644 --- a/src/include/ranges/urange.cc.h +++ b/src/include/ranges/urange.cc.h @@ -306,11 +306,114 @@ namespace CNORXZ * Range Casts * *******************/ + template + struct URangeCast + { + template + static inline Sptr> transform(const RangePtr& r) + { + if(r->type() == typeid(URange)){ + auto rr = std::dynamic_pointer_cast>(r); + Vector v(rr->size()); + std::transform(rr->begin(), rr->end(), v.begin(), + [](const T& x) { return static_cast(x); } ); + return std::dynamic_pointer_cast> + ( URangeFactory(std::move(v)).create() ); + } + else { + return nullptr; + } + } + + static inline Sptr> cast(const RangePtr& r) + { + static_assert(std::is_fundamental::value, "got non-fundamental type"); + CXZ_ASSERT(r->dim() == 1, "range cast into URange: source range must have dim = 1, got " << r->dim()); + Sptr> o = nullptr; + o = transform(r); if(o) return o; + o = transform(r); if(o) return o; + o = transform(r); if(o) return o; + o = transform(r); if(o) return o; + // else general transform using DType (better than nothing), to be implemented!!! + CXZ_ERROR("no range cast available for input range '" << r->type().name() << "'"); + return nullptr; + } + }; + + template struct is_vector : std::false_type {}; + template struct is_vector> : std::true_type {}; + + template + struct URangeCast> + { + template + static inline Sptr>> transform(const RangePtr& r) + { + if(r->type() == typeid(URange)){ + auto rr = std::dynamic_pointer_cast>(r); + Vector> v(rr->size()); + std::transform(rr->begin(), rr->end(), v.begin(), + [](const T& x) { return Vector { static_cast(x) }; } ); + return std::dynamic_pointer_cast>> + ( URangeFactory>(std::move(v)).create() ); + } + else { + return nullptr; + } + } + + template + static inline Sptr>> atransform(const RangePtr& r) + { + if(r->type() == typeid(URange>)){ + auto rr = std::dynamic_pointer_cast>>(r); + Vector> v(rr->size()); + std::transform(rr->begin(), rr->end(), v.begin(), + [](const Arr& x) { + return iter<0,N>( [&](auto i) { return static_cast(x[i]); }, + [](const auto&... e) { return Vector{ e... }; }); + } ); + return std::dynamic_pointer_cast>> + ( URangeFactory>(std::move(v)).create() ); + } + else { + return nullptr; + } + } + + static inline Sptr>> cast(const RangePtr& r) + { + Sptr>> o = nullptr; + if constexpr(std::is_fundamental::value){ + o = transform(r); if(o) return o; + o = transform(r); if(o) return o; + o = transform(r); if(o) return o; + o = transform(r); if(o) return o; + o = atransform(r); if(o) return o; + o = atransform(r); if(o) return o; + o = atransform(r); if(o) return o; + o = atransform(r); if(o) return o; + o = atransform(r); if(o) return o; + o = atransform(r); if(o) return o; + o = atransform(r); if(o) return o; + o = atransform(r); if(o) return o; + } + // else general transform using DType (better than nothing), to be implemented!!! + CXZ_ERROR("no range cast available for input range '" << r->type().name() << "'"); + } + }; + + template Sptr> RangeCast>::func(const RangePtr& r) { - CXZ_ERROR("to be implemented..."); - return nullptr; + if constexpr(std::is_fundamental::value or is_vector::value){ + return URangeCast::cast(r); + } + else { + CXZ_ERROR("no range cast available for input range '" << r->type().name() << "'"); + return nullptr; + } } }