diff --git a/source/simple/support/algorithm.hpp b/source/simple/support/algorithm.hpp
index 2ad32abfe564a36882f7790fe82cbaf689abfe02..fc688597c8701ee5e63a463f7eae554f53d4aec9 100644
--- a/source/simple/support/algorithm.hpp
+++ b/source/simple/support/algorithm.hpp
@@ -187,6 +187,7 @@ namespace simple::support
 
 
 	template <typename Container>
+	[[nodiscard]]
 	constexpr auto make_range(Container& container)
 	{
 		using std::begin;
@@ -198,6 +199,7 @@ namespace simple::support
 	constexpr auto make_range(Container&& container) = delete;
 
 	template <typename Container>
+	[[nodiscard]]
 	constexpr auto reverse_range(Container& container)
 	{
 		using std::rbegin;
@@ -210,12 +212,34 @@ namespace simple::support
 
 
 	template<typename Index = std::size_t, typename Container>
-	constexpr
+	[[nodiscard]] constexpr
 	auto get_iterator_range(Container&& container, const range<Index>& index_range)
+	{
+		return make_range(std::forward<Container>(container)).sub_range(index_range);
+	}
+
+	template<typename It>
+	[[nodiscard]] constexpr
+	auto distance(const range<It>& rng, It origin)
 	{
 		using std::begin;
 		using std::end;
-		return make_range(std::forward<Container>(container)).sub_range(index_range);
+		return range{ begin(rng) - origin, end(rng) - origin };
+	}
+
+	template <typename From, typename To, typename Origin>
+	[[nodiscard]] constexpr
+	auto map_range(const From& from, To&& to, Origin origin)
+	{
+		return get_iterator_range(to, distance(from, origin));
+	}
+
+	template <typename From, typename To>
+	[[nodiscard]] constexpr
+	auto map_range(const From& from, const To& to)
+	{
+		using std::begin;
+		return get_iterator_range(to, distance(from, begin(from)));
 	}
 
 	template <typename Itr, typename BinaryOp>
@@ -317,7 +341,7 @@ namespace simple::support
 	template <typename Integer,
 		typename Unsigned = std::make_unsigned_t<Integer>>
 	[[nodiscard]] constexpr
-	Integer midpoint(Integer a, Integer b)
+	Integer midpoint(Integer a, Integer b) noexcept
 	// noexcept(noexcept(TODO))
 	{
 		using std::numeric_limits;
diff --git a/source/simple/support/range.hpp b/source/simple/support/range.hpp
index 2b4b1cebdfab9857ca6d0c33e2e824d9b60cd0fc..6bc1501f3c3e2824c4acd7091f6dd1098ba2c9fb 100644
--- a/source/simple/support/range.hpp
+++ b/source/simple/support/range.hpp
@@ -47,25 +47,41 @@ namespace simple::support
 			return bounds == other.bounds;
 		}
 
-		template <typename T = Type, std::enable_if_t<range_based_for_loopable<T>{}>...>
-		constexpr Type begin() const { return lower(); }
-		template <typename T = Type, std::enable_if_t<range_based_for_loopable<T>{}>...>
-		constexpr Type end() const { return upper(); }
-
-		template<typename Range>
-		constexpr range sub_range(const Range& other) const
+		template <typename T = Type,
+			std::enable_if_t<range_based_for_loopable<T>{}>...>
+		[[nodiscard]] constexpr Type begin() const { return lower(); }
+		template <typename T = Type,
+			std::enable_if_t<range_based_for_loopable<T>{}>...>
+		[[nodiscard]] constexpr Type end() const { return upper(); }
+
+		template <typename T = Type,
+			std::enable_if_t<range_based_for_loopable<T>{}>...>
+		[[nodiscard]] constexpr auto rbegin() const
+		{ return std::make_reverse_iterator(upper()); }
+		template <typename T = Type,
+			std::enable_if_t<range_based_for_loopable<T>{}>...>
+		[[nodiscard]] constexpr auto rend() const
+		{ return std::make_reverse_iterator(lower()); }
+
+		template<typename OtherType>
+		[[nodiscard]] constexpr
+		range sub_range(range<OtherType> other) const
 		{
-			range result
+			// TODO: use unsigned for other type when it makes sense, to avoid overflow
+			clamp_in_place(other, {
+				OtherType{},
+				static_cast<OtherType>(upper() - lower())
+			});
+			return
 			{
 				lower() + other.lower(),
 				lower() + other.upper()
 			};
-			clamp_in_place(result, {lower(), upper()});
-			return result;
 		}
 
 		constexpr auto validity() const { return lower() <= upper(); }
 		constexpr bool valid() const { return bool(validity()); }
+
 		constexpr range& fix() &
 		{
 			using std::min;
@@ -89,6 +105,12 @@ namespace simple::support
 			return range{*this}.fix();
 		}
 
+		[[nodiscard]]
+		constexpr auto reverse() const
+		{
+			return support::range{rbegin(), rend()};
+		}
+
 		template <typename ValueType = Type, std::common_type_t<ValueType, Type>* = nullptr>
 		constexpr bool contains(const ValueType& value) const
 		{ return lower() < value && value < upper(); }
@@ -168,6 +190,11 @@ namespace simple::support
 	constexpr range<Type> intersection(const range<Type>& one, range<Type> other)
 	{ return one.intersection(other); }
 
+	template <typename Type>
+	[[nodiscard]]
+	constexpr auto reverse(const range<Type>& one)
+	{ return one.reverse(); }
+
 	template <typename Type>
 	constexpr
 	range<Type>& clamp_in_place(range<Type>& v, const range<Type>& hilo)
diff --git a/unit_tests/algorithm.cpp b/unit_tests/algorithm.cpp
index f9290f52693104e4806aea83a7acfcf72c510afc..64ca9398555682c0fb21db66a289bf10ccb4d26d 100644
--- a/unit_tests/algorithm.cpp
+++ b/unit_tests/algorithm.cpp
@@ -116,6 +116,7 @@ void IteratorRange()
 	array<int, 5> sub_array{3, 4, 5, 6, 7};
 	array<int, 5> sub_array_2{5, 6, 7, 8, 9};
 	array<int, 5> sub_array_3{0, 1, 2, 3, 4};
+	array<int, 5> rsub_array_2{9, 8, 7, 6, 5};
 
 	int i = 0;
 	for(auto&& element : get_iterator_range(arr, {3, 8}))
@@ -125,6 +126,16 @@ void IteratorRange()
 	for(auto&& element : get_iterator_range(arr, {5, 800}))
 		assert(sub_array_2[i++] == element);
 
+	i = arr.size();;
+	for(auto&& element : reverse_range(arr))
+		assert(arr[--i] == element);
+
+
+	i = 0;
+	for(auto&& element : reverse(get_iterator_range(arr, {5, 800})))
+		assert(rsub_array_2[i++] == element);
+
+
 	i = 0;
 	for(auto&& element : get_iterator_range<int>(arr, {-105, 5}))
 		assert(sub_array_3[i++] == element);
@@ -164,9 +175,11 @@ void Average()
 constexpr bool Constexprness()
 {
 	range<int> v{};
-	get_iterator_range(v.bounds, v);
-	make_range(v.bounds);
-	reverse_range(v.bounds);
+	range<int*> vitr{};
+	(void)get_iterator_range(v.bounds, v);
+	(void)make_range(v.bounds);
+	(void)reverse_range(v.bounds);
+	(void)reverse(vitr);
 	auto itr = v.bounds.begin();
 	advance_vector(itr,itr,itr);
 	advance_vector(itr,itr,itr,itr);
diff --git a/unit_tests/range.cpp b/unit_tests/range.cpp
index c5d3df3e0108095e002e05509ea986aed4a90d73..3851611044861690eb192d5ac7440159a6c376ba 100644
--- a/unit_tests/range.cpp
+++ b/unit_tests/range.cpp
@@ -127,10 +127,23 @@ void SubRange()
 	range sub_rng_2{5, 9};
 	range sub_rng_3{0, 5};
 
-	assert( sub_rng == rng.sub_range(make_range(3, 8)) );
-	assert( sub_rng_2 == rng.sub_range(make_range(5, 800)) );
-	assert( sub_rng_3 == rng.sub_range(make_range(-105, 5)) );
-	assert( rng == rng.sub_range(make_range(-105, 105)) );
+	assert( sub_rng == rng.sub_range(range{3, 8}) );
+	assert( sub_rng_2 == rng.sub_range(range{5, 800}) );
+	assert( sub_rng_3 == rng.sub_range(range{-105, 5}) );
+	assert( rng == rng.sub_range(range{-105, 105}) );
+
+	auto limit = range<int>::limit();
+	range inc{-1,1};
+
+	assert( inc == inc.sub_range(limit) );
+
+	range near_limit {limit.upper(), limit.upper()};
+	near_limit -= 100;
+	near_limit.upper() += 50;
+	range overflow {25, 125};
+	range sub_near_limit = near_limit;
+	sub_near_limit.lower() += 25;
+	assert( sub_near_limit == near_limit.sub_range(overflow) );
 }
 
 template <typename Larger, typename Smaller>
@@ -256,7 +269,7 @@ constexpr bool Constexprness()
 	v.overlaps(v);
 	v.intersects_lower(i);
 	v.intersects_upper(i);
-	v.sub_range(v);
+	(void)v.sub_range(v);
 	v += 1;
 	v = v+1;
 	v -= 1;