From a142fdb466daa73e30f68d76a919fee05d2ff24f Mon Sep 17 00:00:00 2001
From: Christian Zimmermann <christian.zimmermann@ur.de>
Date: Thu, 6 Oct 2022 18:32:56 +0200
Subject: [PATCH] im com

---
 src/include/ranges/xfor/pos_type.cc.h | 241 +++++++++++---------------
 src/include/ranges/xfor/pos_type.h    | 203 ++++++++--------------
 2 files changed, 166 insertions(+), 278 deletions(-)

diff --git a/src/include/ranges/xfor/pos_type.cc.h b/src/include/ranges/xfor/pos_type.cc.h
index 6d3a562..0a596e6 100644
--- a/src/include/ranges/xfor/pos_type.cc.h
+++ b/src/include/ranges/xfor/pos_type.cc.h
@@ -37,6 +37,13 @@ namespace CNORXZ
 	return SPos<N*N1>();
     }
 
+    template <SizeT N>
+    template <SizeT N1>
+    constexpr auto SPos<N>::operator()(const SPos<N1>& a) const
+    {
+	return SPos<N*N1>();
+    }
+
     template <SizeT N>
     constexpr auto SPos<N>::operator+(const UPos& a) const
     {
@@ -49,9 +56,15 @@ namespace CNORXZ
 	return UPos(N*a.val());
     }
 
+    template <SizeT N>
+    constexpr auto SPos<N>::operator()(const UPos& a) const
+    {
+	return UPos(N*a.val());
+    }
+
     template <SizeT N>
     template <class PosT>
-    constexpr auto SPos<N>::extend(const CPosInterface<PosT>& a) const
+    constexpr auto SPos<N>::extend(const PosT& a) const
     {
 	return MPos<SPos<N>,PosT>(*this,a);
     }
@@ -73,19 +86,25 @@ namespace CNORXZ
     }
     
     template <class PosT>
-    constexpr UPos UPos::operator+(const CPosInterface<PosT>& in) const
+    constexpr UPos UPos::operator+(const PosT& in) const
     {
 	return UPos(mExt + in.val());
     }
     
     template <class PosT>
-    constexpr UPos UPos::operator*(const CPosInterface<PosT>& in) const
+    constexpr UPos UPos::operator*(const PosT& in) const
     {
 	return UPos(mExt * in.val());
     }
 	
     template <class PosT>
-    constexpr auto UPos::extend(const CPosInterface<PosT>& p1) const
+    constexpr UPos UPos::operator()(const PosT& in) const
+    {
+	return UPos(mExt * in.val());
+    }
+	
+    template <class PosT>
+    constexpr auto UPos::extend(const PosT& p1) const
     {
 	return MPos<UPos,PosT>(*this, p1);
     }
@@ -107,19 +126,25 @@ namespace CNORXZ
     }
 	
     template <class PosT1>
-    constexpr UPos FPos::operator+(const CPosInterface<PosT1>& a) const
+    constexpr UPos FPos::operator+(const PosT1& a) const
     {
 	return UPos(mExt + a.val());
     }
 
+    template <class PosT>
+    constexpr FPos UPos::operator*(const PosT& in) const
+    {
+	return FPos(mExt * in.val(), mMap);
+    }
+
     template <class PosT1>
-    constexpr UPos FPos::operator*(const CPosInterface<PosT1>& a) const
+    constexpr UPos FPos::operator()(const PosT1& a) const
     {
 	return UPos(mExt * mMap[a.val()]);
     }
 
     template <class PosT1>
-    constexpr auto FPos::extend(const CPosInterface<PosT1>& a) const
+    constexpr auto FPos::extend(const PosT1& a) const
     {
 	return MPos<FPos,PosT1>(*this,a);
     }
@@ -150,6 +175,13 @@ namespace CNORXZ
     template <SizeT N, SizeT... Ms>
     template <SizeT N1>
     constexpr auto SFPos<N,Ms...>::operator*(const SPos<N1>& a) const
+    {
+	return SFPos<N*N1,Ms...>();
+    }
+
+    template <SizeT N, SizeT... Ms>
+    template <SizeT N1>
+    constexpr auto SFPos<N,Ms...>::operator()(const SPos<N1>& a) const
     {
 	constexpr Arr<SizeT,sizeof...(Ms)> ms({ Ms... });
 	return SPos<N*std::get<a.val()>(ms)>();
@@ -162,7 +194,15 @@ namespace CNORXZ
     }
     
     template <SizeT N, SizeT... Ms>
+    template <SizeT N1>
     constexpr auto SFPos<N,Ms...>::operator*(const UPos& a) const
+    {
+	static const Arr<SizeT,sizeof...(Ms)> ms({ Ms... });
+	return FPos(N * a.val(), &ms[0]);
+    }
+
+    template <SizeT N, SizeT... Ms>
+    constexpr auto SFPos<N,Ms...>::operator()(const UPos& a) const
     {
 	constexpr Arr<SizeT,sizeof...(Ms)> ms({ Ms... });
 	return UPos(N * ms[a.val()]);
@@ -170,171 +210,84 @@ namespace CNORXZ
 
     template <SizeT N, SizeT... Ms>
     template <class PosT>
-    constexpr auto SFPos<N,Ms...>::extend(const CPosInterface<PosT>& a) const
+    constexpr auto SFPos<N,Ms...>::extend(const PosT& a) const
     {
 	return MPos<SFPos<N,Ms...>,PosT>(*this,a);
     }
 
-    
-    /************
-     *   DPos   *
-     ************/
-
-    inline DPos::DPos(Uptr<VPosBase>&& a) :
-	ObjHandle<VPosBase>(std::forward<Uptr<VPosBase>>(a))
-    {}
-
-    template <class PosT>
-    inline DPos::DPos(const CPosInterface<PosT>& a) :
-	ObjHandle<VPosBase>( std::make_unique<VPos<PosT>>(a) )
-    {}
-
-    inline SizeT DPos::size() const
-    {
-	return mC->vsize();
-    }
-    
-    inline SizeT DPos::val() const
-    {
-	return mC->vval();
-    }
-    
-    inline DPosRef DPos::first() const
-    {
-	return DPosRef(mC->vget());
-    } 
-
-    inline DPosRef DPos::next() const
-    {
-	return DPosRef(mC->vnext());
-    } 
-
-    template <class PosT1>
-    inline DPos DPos::operator+(const CPosInterface<PosT1>& a) const
-    {
-	VPosRef<PosT1> r(&a);
-	return DPos(mC->vplus(&r)); // check memory safety!!!
-    }
-    
-    template <class PosT1>
-    inline DPos DPos::operator*(const CPosInterface<PosT1>& a) const
-    {
-	VPosRef<PosT1> r(&a);
-	return DPos(mC->vtimes(&r)); // check memory safety!!!
-    }    
-    
-    template <class PosT1>
-    inline DPos DPos::extend(const CPosInterface<PosT1>& a) const
-    {
-	return DPos(mC->vextend(a));
-    }
-    
-    /***************
-     *   DPosRef   *
-     ***************/
-    
-    inline DPosRef::DPosRef(const VPosBase* c) :
-	mC(c)
-    {}
-    
-    inline SizeT DPosRef::size() const
-    {
-	return mC->vsize();
-    }
-    
-    inline SizeT DPosRef::val() const
-    {
-	return mC->vval();
-    }
-    
-    inline DPosRef DPosRef::first() const
-    {
-	return DPosRef(mC->vget());
-    } 
-
-    inline DPosRef DPosRef::next() const
-    {
-	return DPosRef(mC->vnext());
-    } 
-
-    template <class PosT1>
-    inline DPos DPosRef::operator+(const CPosInterface<PosT1>& a) const
-    {
-	VPosRef<PosT1> r(&a);
-	return DPos(mC->vplus(&r)); // check memory safety!!!
-    }
-    
-    template <class PosT1>
-    inline DPos DPosRef::operator*(const CPosInterface<PosT1>& a) const
-    {
-	VPosRef<PosT1> r(&a);
-	return DPos(mC->vtimes(&r)); // check memory safety!!!
-    }    
-    
-    template <class PosT1>
-    inline DPos DPosRef::extend(const CPosInterface<PosT1>& a) const
-    {
-	return DPos(mC->vextend(a));
-    }
-
-
     /************
      *   MPos   *
      ************/
 
-    template <class PosT1, class PosT2>
-    constexpr MPos<PosT1,PosT2>::MPos(const CPosInterface<PosT1>& first,
-				      const CPosInterface<PosT2>& next) :
-	mFirst(first.THIS()), mNext(next.THIS())
-    {}
-
-    template <class PosT1, class PosT2>
-    constexpr SizeT MPos<PosT1,PosT2>::size() const
+    template <class BPosT, class NPosT>
+    constexpr MPos<BPosT,NPosT>::MPos()
     {
-	return mFirst.size() + mNext.size();
+	static_assert(is_scalar_pos_type<BPosT>::value,
+		      "MPos has to be derived from scalar pos type");
     }
 
-    template <class PosT1, class PosT2>
-    constexpr auto MPos<PosT1,PosT2>::val() const
+    template <class BPosT, class NPosT>
+    template <typename... Args>
+    constexpr MPos<BPosT,NPosT>::MPos(Args&&... args, const NPosT& next) :
+	BPosT(args...), mNext(next)
     {
-	return mFirst.val();
+	static_assert(is_scalar_pos_type<BPosT>::value,
+		      "MPos has to be derived from scalar pos type");
     }
 
-    template <class PosT1, class PosT2>
-    constexpr const PosT1& MPos<PosT1,PosT2>::first() const
+    template <class BPosT, class NPosT>
+    template <typename... Args>
+    constexpr MPos<BPosT,NPosT>::MPos(Args&&... args, NPosT&& next) :
+	BPosT(args...), mNext(next)
     {
-	return mFirst;
+	static_assert(is_scalar_pos_type<BPosT>::value,
+		      "MPos has to be derived from scalar pos type");
     }
 
-    template <class PosT1, class PosT2>
-    constexpr const PosT2& MPos<PosT1,PosT2>::next() const
+    template <class BPosT, class NPosT>
+    constexpr SizeT MPos<BPosT,NPosT>::size() const
+    {
+	return BPosT::size() + mNext.size();
+    }
+
+    template <class BPosT, class NPosT>
+    constexpr const NPos& MPos<BPosT,NPosT>::next() const
     {
 	return mNext;
     }
 
-    template <class PosT1, class PosT2>
-    template <class PosT3, class PosT4>
-    constexpr auto MPos<PosT1,PosT2>::operator+(const MPos<PosT3,PosT4>& a) const
+    template <class BPosT, class NPosT>
+    template <class PosT>
+    constexpr auto MPos<BPosT,NPosT>::operator+(const PosT& a) const
     {
-	typedef decltype(first()+a.first()) PosT5;
-	typedef decltype(next()+a.next()) PosT6;
-	return MPos<PosT5,PosT6>(first()+a.first(), next()+a.next());
+	typedef decltype(BPosT::operator+(a)) OBPosT;
+	typedef decltype(mNext + a.next()) ONPosT;
+	return MPos<OBPosT,ONPosT>( BPosT::operator+(a), mNext + a.next() );
     }
 
-    template <class PosT1, class PosT2>
-    template <class PosT3>
-    constexpr auto MPos<PosT1,PosT2>::operator*(const CPosInterface<PosT3>& a) const
+    template <class BPosT, class NPosT>
+    template <class PosT>
+    constexpr auto MPos<BPosT,NPosT>::operator*(const PosT& a) const
     {
-	typedef decltype(first()*a.THIS()) PosT5;
-	typedef decltype(next()*a.THIS()) PosT6;
-	return MPos<PosT5,PosT6>(first()*a.THIS(), next()*a.THIS());
+	typedef decltype(BPosT::operator*(a)) OBPosT;
+	typedef decltype(mNext * a.next()) ONPosT;
+	return MPos<OBPosT,ONPosT>( BPosT::operator*(a), mNext * a.next() );
     }
 
-    template <class PosT1, class PosT2>
-    template <class PosT3>
-    constexpr auto MPos<PosT1,PosT2>::extend(const CPosInterface<PosT3>& p) const
+    template <class BPosT, class NPosT>
+    template <class PosT>
+    constexpr auto MPos<BPosT,NPosT>::operator()(const PosT& a) const
     {
-	return MPos<MPos<PosT1,PosT2>,PosT3>(*this,p);
+	typedef decltype(BPosT::operator()(a)) OBPosT;
+	typedef decltype(mNext(a.next())) ONPosT;
+	return MPos<OBPosT,ONPosT>( BPosT::operator()(a), mNext(a.next()) );
+    }
+	
+    template <class BPosT, class NPosT>
+    template <class PosT>
+    constexpr auto MPos<BPosT,NPosT>::extend(const PosT& a) const
+    {
+	return mNext.extend(a);
     }
 
 }
diff --git a/src/include/ranges/xfor/pos_type.h b/src/include/ranges/xfor/pos_type.h
index 5365bc6..827c45a 100644
--- a/src/include/ranges/xfor/pos_type.h
+++ b/src/include/ranges/xfor/pos_type.h
@@ -6,68 +6,45 @@
 
 namespace CNORXZ
 {
+    // shift to base.h
+#define CXZ_CVAL_FALSE static constexpr bool value = false
+#define CXZ_CVAL_TRUE static constexpr bool value = true
+    
+    template <class T>
+    struct is_pos_type { CXZ_CVAL_FALSE; };
 
-    template <class PosT>
-    class CPosInterface
-    {
-    public:
-	static constexpr bool MULTI = PosT::MULTI;
-	
-	DEFAULT_MEMBERS(CPosInterface);
-
-	PosT& THIS() { return static_cast<PosT&>(*this); }
-	const PosT& THIS() const { return static_cast<const PosT&>(*this); }
-	
-	inline SizeT size() const { return THIS().size(); }
-	inline auto val() const { return THIS().val(); }
-	// template!!!
-	inline CPosInterface<PosT> operator+(const CPosInterface<PosT>& a) const
-	{ return THIS() + a.THIS(); }
-	// template!!!
-	inline CPosInterface<PosT> operator*(const CPosInterface<PosT>& a) const
-	{ return THIS() * a.THIS(); }
-	// template!!!
-	// inline CPosInterface<PosT> execute(const CPosInterface<PosT>& a,
-	// const CPosInterface<PosT>& b, const CPosInterface<PosT>& c) const
-	// => a+b*c; only this executes also the FPos/SFPos-Map!!! 
-	
-	// for each class implement +/* for each argument type EXPLICITLY (NO templates, except for MPos)
-	// *: only UPos/SPos as Arguments, for DPos only UPos as Args
-	
-	template <class P>
-	inline auto extend(const CPosInterface<P>& a) const { return THIS().extend(a); }
-    };
-
+    template <class T>
+    struct is_scalar_pos_type { CXZ_CVAL_FALSE; };
+    
     template <SizeT N>
-    class SPos : public CPosInterface<SPos<N>>
+    class SPos
     {
     public:
-	static constexpr bool MULTI = false;
-
 	constexpr SPos() = default;
 
 	constexpr SizeT size() const;
 	constexpr SizeT val() const;
-
+	
 	template <SizeT N1>
 	constexpr auto operator+(const SPos<N1>& a) const;
 	template <SizeT N1>
 	constexpr auto operator*(const SPos<N1>& a) const;
+	template <SizeT N1>
+	constexpr auto operator()(const SPos<N1>& a) const;
 
 	constexpr auto operator+(const UPos& a) const;
 	constexpr auto operator*(const UPos& a) const;
-
+	constexpr auto operator()(const UPos& a) const;
+	
 	template <class PosT>
-	constexpr auto extend(const CPosInterface<PosT>& a) const;
+	constexpr auto extend(const PosT& a) const;
     };
-    
-    class UPos : public CPosInterface<UPos>
+
+    class UPos
     {
     private:
         SizeT mExt = 0;
     public:
-	static constexpr bool MULTI = false;
-	
 	DEFAULT_MEMBERS(UPos);
 
 	constexpr UPos(SizeT ext);
@@ -76,25 +53,26 @@ namespace CNORXZ
 	constexpr const SizeT& val() const;
 
 	template <class PosT>
-	constexpr UPos operator+(const CPosInterface<PosT>& a) const;
+	constexpr UPos operator+(const PosT& a) const;
 
         template <class PosT>
-	constexpr UPos operator*(const CPosInterface<PosT>& a) const;
-	
+	constexpr UPos operator*(const PosT& a) const;
+
+	template <class PosT>
+	constexpr UPos operator()(const PosT& a) const;
+
         template <class PosT>
-        constexpr auto extend(const CPosInterface<PosT>& y) const;
+        constexpr auto extend(const PosT& a) const;
 
     };
-    
-    class FPos : public CPosInterface<FPos>
+
+    class FPos
     {
     private:
 	SizeT mExt = 0;
 	const SizeT* mMap = nullptr;
 
     public:
-	static constexpr bool MULTI = false;
-
 	DEFAULT_MEMBERS(FPos);
 
 	inline FPos(SizeT ext, const SizeT* map);
@@ -103,21 +81,22 @@ namespace CNORXZ
 	constexpr const SizeT& val() const;
 	
 	template <class PosT1>
-	constexpr UPos operator+(const CPosInterface<PosT1>& a) const;
+	constexpr UPos operator+(const PosT1& a) const;
 
 	template <class PosT1>
-	constexpr UPos operator*(const CPosInterface<PosT1>& a) const;
+	constexpr FPos operator*(const PosT1& a) const;
+
+	template <class PosT>
+	constexpr UPos operator()(const PosT& a) const;
 
 	template <class PosT1>
-	constexpr auto extend(const CPosInterface<PosT1>& a) const;
+	constexpr auto extend(const PosT1& a) const;
     };
 
     template <SizeT N, SizeT... Ms>
-    class SFPos : public CPosInterface<SFPos<N,Ms...>>
+    class SFPos
     {
     public:
-	static constexpr bool MULTI = false;
-
 	constexpr SFPos() = default;
 
 	constexpr SizeT size() const;
@@ -127,101 +106,57 @@ namespace CNORXZ
 	constexpr auto operator+(const SPos<N1>& a) const;
 	template <SizeT N1>
 	constexpr auto operator*(const SPos<N1>& a) const;
+	template <SizeT N1>
+	constexpr auto operator()(const SPos<N1>& a) const;
 
 	constexpr auto operator+(const UPos& a) const;
 	constexpr auto operator*(const UPos& a) const;
+	constexpr auto operator()(const UPos& a) const;
 
 	template <class PosT>
-	constexpr auto extend(const CPosInterface<PosT>& a) const;
-    };
-    
-    class DPos : public ObjHandle<VPosBase>,
-		 public CPosInterface<DPos>
-    {
-    public:
-	static constexpr bool MULTI = true;
-
-	DEFAULT_MEMBERS(DPos);
-	inline DPos(Uptr<VPosBase>&& a);
-	
-	template <class PosT>
-	inline DPos(const CPosInterface<PosT>& a);
-
-	inline SizeT size() const;
-	inline SizeT val() const;
-	inline DPosRef first() const;
-	inline DPosRef next() const;
-
-	template <class PosT1>
-	inline DPos operator+(const CPosInterface<PosT1>& a) const;
-
-	template <class PosT1>
-	inline DPos operator*(const CPosInterface<PosT1>& a) const;
-
-	template <class PosT1>
-	inline DPos extend(const CPosInterface<PosT1>& a) const;
-	
-    };
-    
-    class DPosRef : public CPosInterface<DPosRef>
-    {
-    private:
-	const VPosBase* mC;
-    public:
-	static constexpr bool MULTI = true;
-
-	DEFAULT_MEMBERS(DPosRef);
-	inline DPosRef(const VPosBase* c);
-
-	inline SizeT size() const;
-	inline SizeT val() const;
-	inline DPosRef first() const;
-	inline DPosRef next() const;
-
-	template <class PosT1>
-	inline DPos operator+(const CPosInterface<PosT1>& a) const;
-
-	template <class PosT1>
-	inline DPos operator*(const CPosInterface<PosT1>& a) const;
-
-	template <class PosT1>
-	inline DPos extend(const CPosInterface<PosT1>& a) const;
+	constexpr auto extend(const PosT& a) const;
     };
 
-    // go to original pattern (-> LINEAR template chain)
-    // first: just cast by constructor
-    template <class PosT1, class PosT2>
-    class MPos : public CPosInterface<MPos<PosT1,PosT2>>
+    template <class BPosT, class NPosT>
+    class MPos : public BPosT // BPos should be a SCALAR PosT (NO MPos!)
     {
-    private:
-
-	PosT1 mFirst;
-	PosT2 mNext;
-	
+    protected:
+	NPosT mNext;
     public:
-	static constexpr bool MULTI = true;
+	constexpr MPos()
 
-	DEFAULT_MEMBERS(MPos);
-	
-	constexpr MPos(const CPosInterface<PosT1>& first,
-		       const CPosInterface<PosT2>& next);
+	template <typename... Args>
+	constexpr MPos(Args&&... args, const NPosT& next);
+
+	template <typename... Args>
+	constexpr MPos(Args&&... args, NPosT&& next);
 
 	constexpr SizeT size() const;
-	constexpr auto val() const;
-	constexpr const PosT1& first() const;
-	constexpr const PosT2& next() const;
+	constexpr const NPos& next() const;
 
-	template <class PosT3, class PosT4>
-	constexpr auto operator+(const MPos<PosT3,PosT4>& a) const;
+	template <class PosT>
+	constexpr auto operator+(const PosT& a) const;
 
-	template <class PosT3>
-	constexpr auto operator*(const CPosInterface<PosT3>& a) const;
+	template <class PosT>
+	constexpr auto operator*(const PosT& a) const;
 
-	template <class PosT3>
-	constexpr auto extend(const CPosInterface<PosT3>& p) const;
+	// same as operator*, except for FPos/SFPos, where map is executed
+	template <class PosT>
+	constexpr auto operator()(const PosT& a) const;
+	
+	template <class PosT>
+	constexpr auto extend(const PosT& a) const;
+    };
 
-    };    
-    
+    template <SizeT N> struct is_pos_type<SPos<N>> { CXZ_CVAL_TRUE; };
+    template <SizeT N> struct is_scalar_pos_type<SPos<N>> { CXZ_CVAL_TRUE; };
+    template <> struct is_pos_type<UPos> { CXZ_CVAL_TRUE; };
+    template <> struct is_scalar_pos_type<UPos> { CXZ_CVAL_TRUE; };
+    template <> struct is_pos_type<FPos> { CXZ_CVAL_TRUE; };
+    template <> struct is_scalar_pos_type<FPos> { CXZ_CVAL_TRUE; };
+    template <SizeT N, SizeT... Ms> struct is_pos_type<SFPos<N,Ms...>> { CXZ_CVAL_TRUE; };
+    template <SizeT N, SizeT... Ms> struct is_scalar_pos_type<SFPos<N,Ms...>> { CXZ_CVAL_TRUE; };
+    template <class BPosT, class NPosT> struct is_pos_type<MPos<BPosT,NPosT>> { CXZ_CVAL_TRUE; };
 
 } // end namespace CNORXZInternal