diff --git a/source/simple/support/algorithm.hpp b/source/simple/support/algorithm.hpp
index 2811321ebe922627f0b5c9838a7813ffb5a24b50..76237ab171e7555f572b21d54668baeb9a1f50b2 100644
--- a/source/simple/support/algorithm.hpp
+++ b/source/simple/support/algorithm.hpp
@@ -273,40 +273,107 @@ namespace simple::support
 	template <typename... Numbers>
 	[[nodiscard]] constexpr
 	auto average(Numbers... n)
-	//TODO: noexcept account for return value construction
-	//TODO: cast size to result type of sum instead of int
+	//TODO: noexcept account for return value and default construction
 	noexcept(noexcept((n + ...) / int(sizeof...(n))))
 	{
-		return (n + ...) / int(sizeof...(n));
+		using Sum = decltype((n + ...));
+		return (n + ...) / (Sum{} + sizeof...(n));
+	}
+
+	template <typename Number, typename Ratio>
+	[[nodiscard]] constexpr
+	Number way(Number from, Number to, Ratio ratio)
+	noexcept(noexcept(Number(from + (to - from)*ratio)))
+	{
+		return from + (to - from)*ratio;
+	}
+
+	template <typename Number, typename Ratio>
+	[[nodiscard]] constexpr
+	Number wayback(Number from, Number to, Ratio ratio)
+	noexcept(noexcept(Number(from - (from - to)*ratio)))
+	{
+		return from - (from - to)*ratio;
 	}
 
 	template <typename Number>
 	[[nodiscard]] constexpr
-	Number midpoint(Number a, Number b)
-	noexcept(noexcept(Number(a + (b - a)/2)))
+	Number halfway(Number from, Number to)
+	// TODO: implement in terms of way with rational 1/2
+	noexcept(noexcept(Number(from - (from - to)/2)))
 	{
-		return a + (b - a)/2;
+		return from + (to - from)/2;
+	}
+
+	template <typename Number>
+	[[nodiscard]] constexpr
+	Number halfwayback(Number from, Number to)
+	// TODO: implement in terms of wayback with rational 1/2
+	noexcept(noexcept(Number(from - (from - to)/2)))
+	{
+		return from - (from - to)/2;
+	}
+
+	template <typename Integer,
+		typename Unsigned = std::make_unsigned_t<Integer>>
+	[[nodiscard]] constexpr
+	Integer midpoint(Integer a, Integer b)
+	// noexcept(noexcept(TODO))
+	{
+		using std::numeric_limits;
+		static_assert(
+			numeric_limits<Unsigned>::max() >=
+				Unsigned(numeric_limits<Integer>::max()),
+			"Unsigned includes Integer"
+		);
+		static_assert(
+			numeric_limits<Unsigned>::max()/2 <=
+				numeric_limits<Integer>::max(),
+			"Halfing Unsigned brings it to positive Integer range"
+		);
+		static_assert(std::is_unsigned_v<Integer> ||
+			Unsigned(numeric_limits<Integer>::max()) <=
+				Unsigned(-Unsigned(numeric_limits<Integer>::min())),
+			"Can negate a positive Integer"
+		);
+
+		Unsigned diff = Unsigned(b) - Unsigned(a);
+
+		// 2's complement with carry as sign
+		Unsigned negative_2x = -diff; // neg
+		negative_2x /= 2; // div
+		Integer negative = -Integer(negative_2x); // neg
+
+		Integer positive = diff / 2;
+
+		auto overflew = b < a;
+		return a + (overflew ? negative : positive);
+
+		// TODO: this is for geom::vector
+		// return a + overflew * idiff + !overflew * diff;
+
 	}
 
 	template <typename Unsigned>
 	[[nodiscard]] constexpr
-	Unsigned midpoint_overflow(Unsigned a, Unsigned b)
+	Unsigned umidpoint(Unsigned a, Unsigned b)
 	// noexcept(noexcept(TODO))
 	{
 
 		Unsigned diff{};
-		bool overflew = sub_overflow(diff,b,a);
+		auto overflew = sub_overflow(diff,b,a);
 
 		// manual idiv
 		Unsigned idiff = -diff; // neg
 		idiff /= Unsigned{2}; // div
 		idiff = -idiff; // neg
 		// or... 0 - (0 - diff)/2, this is midpointception! TODO: -_-
+		// can't use halfwayback here cause promotion ToT
 
-		diff /= Unsigned{2};
+		diff /= 2;
 
 		return a + (overflew ? idiff : diff);
-		// return a + overflew * idiff + ~overflew * diff;
+		// return a + overflew * idiff + !overflew * diff;
 
 	}
 
diff --git a/unit_tests/libcpp_midpoint.cpp b/unit_tests/libcpp_midpoint.cpp
index c745d5009c40989cb4e1949134396e6fedbae78c..f0afd460b36683efa2d4328d35fbb9eaa1c304d1 100644
--- a/unit_tests/libcpp_midpoint.cpp
+++ b/unit_tests/libcpp_midpoint.cpp
@@ -10,7 +10,7 @@
 // <numeric>
 
 // template <class _Tp>
-// _Tp midpoint_overflow(_Tp __a, _Tp __b) noexcept
+// _Tp midpoint(_Tp __a, _Tp __b) noexcept
 //
 
 #include <stdint.h>
@@ -30,44 +30,44 @@ void signed_test()
     constexpr T three{3};
     constexpr T four{4};
 
-    // ASSERT_SAME_TYPE(decltype(midpoint_overflow(T(), T())), T);
-    // ASSERT_NOEXCEPT(          midpoint_overflow(T(), T()));
+    static_assert(std::is_same_v<decltype(midpoint(T(), T())), T>);
+    // ASSERT_NOEXCEPT(          midpoint(T(), T()));
     using limits = std::numeric_limits<T>;
 
-    static_assert(midpoint_overflow(one, three) == two, "");
-    static_assert(midpoint_overflow(three, one) == two, "");
-
-    assert(midpoint_overflow(zero, zero) == zero);
-    assert(midpoint_overflow(zero, two)  == one);
-    assert(midpoint_overflow(two, zero)  == one);
-    assert(midpoint_overflow(two, two)   == two);
-
-    assert(midpoint_overflow(one, four)    == two);
-    assert(midpoint_overflow(four, one)    == three);
-    assert(midpoint_overflow(three, four)  == three);
-    assert(midpoint_overflow(four, three)  == four);
-
-    assert(midpoint_overflow(T( 3), T( 4)) == T(3));
-    assert(midpoint_overflow(T( 4), T( 3)) == T(4));
-    assert(midpoint_overflow(T(-3), T( 4)) == T(0));
-    assert(midpoint_overflow(T(-4), T( 3)) == T(-1));
-    assert(midpoint_overflow(T( 3), T(-4)) == T(0));
-    assert(midpoint_overflow(T( 4), T(-3)) == T(1));
-    assert(midpoint_overflow(T(-3), T(-4)) == T(-3));
-    assert(midpoint_overflow(T(-4), T(-3)) == T(-4));
-
-    static_assert(midpoint_overflow(limits::min(), limits::max()) == T(-1), "");
-    static_assert(midpoint_overflow(limits::max(), limits::min()) == T( 0), "");
-
-    static_assert(midpoint_overflow(limits::min(), T(6)) == limits::min()/2 + 3, "");
-    assert(       midpoint_overflow(T(6), limits::min()) == limits::min()/2 + 3);
-    assert(       midpoint_overflow(limits::max(), T(6)) == limits::max()/2 + 4);
-    static_assert(midpoint_overflow(T(6), limits::max()) == limits::max()/2 + 3, "");
-
-    assert(       midpoint_overflow(limits::min(), T(-6)) == limits::min()/2 - 3);
-    static_assert(midpoint_overflow(T(-6), limits::min()) == limits::min()/2 - 3, "");
-    static_assert(midpoint_overflow(limits::max(), T(-6)) == limits::max()/2 - 2, "");
-    assert(       midpoint_overflow(T(-6), limits::max()) == limits::max()/2 - 3);
+    static_assert(midpoint(one, three) == two, "");
+    static_assert(midpoint(three, one) == two, "");
+
+    assert(midpoint(zero, zero) == zero);
+    assert(midpoint(zero, two)  == one);
+    assert(midpoint(two, zero)  == one);
+    assert(midpoint(two, two)   == two);
+
+    assert(midpoint(one, four)    == two);
+    assert(midpoint(four, one)    == three);
+    assert(midpoint(three, four)  == three);
+    assert(midpoint(four, three)  == four);
+
+    assert(midpoint(T( 3), T( 4)) == T(3));
+    assert(midpoint(T( 4), T( 3)) == T(4));
+    assert(midpoint(T(-3), T( 4)) == T(0));
+    assert(midpoint(T(-4), T( 3)) == T(-1));
+    assert(midpoint(T( 3), T(-4)) == T(0));
+    assert(midpoint(T( 4), T(-3)) == T(1));
+    assert(midpoint(T(-3), T(-4)) == T(-3));
+    assert(midpoint(T(-4), T(-3)) == T(-4));
+
+    static_assert(midpoint(limits::min(), limits::max()) == T(-1), "");
+    static_assert(midpoint(limits::max(), limits::min()) == T( 0), "");
+
+    static_assert(midpoint(limits::min(), T(6)) == limits::min()/2 + 3, "");
+    assert(       midpoint(T(6), limits::min()) == limits::min()/2 + 3);
+    assert(       midpoint(limits::max(), T(6)) == limits::max()/2 + 4);
+    static_assert(midpoint(T(6), limits::max()) == limits::max()/2 + 3, "");
+
+    assert(       midpoint(limits::min(), T(-6)) == limits::min()/2 - 3);
+    static_assert(midpoint(T(-6), limits::min()) == limits::min()/2 - 3, "");
+    static_assert(midpoint(limits::max(), T(-6)) == limits::max()/2 - 2, "");
+    assert(       midpoint(T(-6), limits::max()) == limits::max()/2 - 3);
 }
 
 template <typename T>
@@ -79,46 +79,69 @@ void unsigned_test()
     constexpr T three{3};
     constexpr T four{4};
 
-    // ASSERT_SAME_TYPE(decltype(midpoint_overflow(T(), T())), T);
-    // ASSERT_NOEXCEPT(          midpoint_overflow(T(), T()));
+    static_assert(std::is_same_v<decltype(midpoint(T(), T())), T>);
+    // ASSERT_NOEXCEPT(          midpoint(T(), T()));
     using limits = std::numeric_limits<T>;
     const T half_way = (limits::max() - limits::min())/2;
 
-    static_assert(midpoint_overflow(one, three) == two, "");
-    static_assert(midpoint_overflow(three, one) == two, "");
-
-    assert(midpoint_overflow(zero, zero) == zero);
-    assert(midpoint_overflow(zero, two)  == one);
-    assert(midpoint_overflow(two, zero)  == one);
-    assert(midpoint_overflow(two, two)   == two);
-
-    assert(midpoint_overflow(one, four)    == two);
-    assert(midpoint_overflow(four, one)    == three);
-    assert(midpoint_overflow(three, four)  == three);
-    assert(midpoint_overflow(four, three)  == four);
-
-    assert(midpoint_overflow(limits::min(), limits::max()) == T(half_way));
-    assert(midpoint_overflow(limits::max(), limits::min()) == T(half_way + 1));
-
-    static_assert(midpoint_overflow(limits::min(), T(6)) == limits::min()/2 + 3, "");
-    assert(       midpoint_overflow(T(6), limits::min()) == limits::min()/2 + 3);
-    assert(       midpoint_overflow(limits::max(), T(6)) == half_way + 4);
-    static_assert(midpoint_overflow(T(6), limits::max()) == half_way + 3, "");
+    static_assert(midpoint(one, three) == two, "");
+    static_assert(midpoint(three, one) == two, "");
+
+    assert(midpoint(zero, zero) == zero);
+    assert(midpoint(zero, two)  == one);
+    assert(midpoint(two, zero)  == one);
+    assert(midpoint(two, two)   == two);
+
+    assert(midpoint(one, four)    == two);
+    assert(midpoint(four, one)    == three);
+    assert(midpoint(three, four)  == three);
+    assert(midpoint(four, three)  == four);
+
+    assert(midpoint(limits::min(), limits::max()) == T(half_way));
+    assert(midpoint(limits::max(), limits::min()) == T(half_way + 1));
+
+    static_assert(midpoint(limits::min(), T(6)) == limits::min()/2 + 3, "");
+    assert(       midpoint(T(6), limits::min()) == limits::min()/2 + 3);
+    assert(       midpoint(limits::max(), T(6)) == half_way + 4);
+    static_assert(midpoint(T(6), limits::max()) == half_way + 3, "");
+
+    static_assert(std::is_same_v<decltype(umidpoint(T(), T())), T>);
+    // ASSERT_NOEXCEPT(          midpoint(T(), T()));
+    static_assert(umidpoint(one, three) == two, "");
+    static_assert(umidpoint(three, one) == two, "");
+
+    assert(umidpoint(zero, zero) == zero);
+    assert(umidpoint(zero, two)  == one);
+    assert(umidpoint(two, zero)  == one);
+    assert(umidpoint(two, two)   == two);
+
+    assert(umidpoint(one, four)    == two);
+    assert(umidpoint(four, one)    == three);
+    assert(umidpoint(three, four)  == three);
+    assert(umidpoint(four, three)  == four);
+
+    assert(umidpoint(limits::min(), limits::max()) == T(half_way));
+    assert(umidpoint(limits::max(), limits::min()) == T(half_way + 1));
+
+    static_assert(umidpoint(limits::min(), T(6)) == limits::min()/2 + 3, "");
+    assert(       umidpoint(T(6), limits::min()) == limits::min()/2 + 3);
+    assert(       umidpoint(limits::max(), T(6)) == half_way + 4);
+    static_assert(umidpoint(T(6), limits::max()) == half_way + 3, "");
 }
 
 
 int main(int, char**)
 {
-    // signed_test<signed char>();
-    // signed_test<short>();
-    // signed_test<int>();
-    // signed_test<long>();
-    // signed_test<long long>();
-    //
-    // signed_test<int8_t>();
-    // signed_test<int16_t>();
-    // signed_test<int32_t>();
-    // signed_test<int64_t>();
+    signed_test<signed char>();
+    signed_test<short>();
+    signed_test<int>();
+    signed_test<long>();
+    signed_test<long long>();
+
+    signed_test<int8_t>();
+    signed_test<int16_t>();
+    signed_test<int32_t>();
+    signed_test<int64_t>();
 
     unsigned_test<unsigned char>();
     unsigned_test<unsigned short>();
@@ -137,7 +160,7 @@ int main(int, char**)
 #endif
 
 //     int_test<char>();
-    // signed_test<ptrdiff_t>();
+    signed_test<ptrdiff_t>();
     unsigned_test<size_t>();
 
     return 0;
diff --git a/unit_tests/libstdcpp_midpoint.cpp b/unit_tests/libstdcpp_midpoint.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d9a2848b35a8a56e1b05e36c1751bdd92e249f20
--- /dev/null
+++ b/unit_tests/libstdcpp_midpoint.cpp
@@ -0,0 +1,113 @@
+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <climits>
+#include <cassert>
+#include "simple/support/algorithm.hpp"
+
+using simple::support::midpoint;
+
+static_assert(std::is_same_v<decltype(midpoint(0, 1)), int>);
+static_assert(noexcept(midpoint(1, 2)));
+
+struct test_type { };
+template<typename T> decltype(midpoint<T>(T(), T())) try_midpoint(int);
+template<typename T> test_type try_midpoint(...);
+template<typename T> constexpr bool no_midpoint()
+{ return std::is_same_v<decltype(try_midpoint<T>()), test_type>; }
+
+static_assert(no_midpoint<bool>());
+static_assert(no_midpoint<const bool>());
+static_assert(no_midpoint<const int>());
+static_assert(no_midpoint<volatile int>());
+
+static_assert( midpoint(0, 0) == 0 );
+static_assert( midpoint(1, 1) == 1 );
+static_assert( midpoint(0, 1) == 0 );
+static_assert( midpoint(1, 0) == 1 );
+static_assert( midpoint(0, 2) == 1 );
+static_assert( midpoint(3, 2) == 3 );
+static_assert( midpoint(-5, 4) == -1 );
+static_assert( midpoint(5, -4) == 1 );
+static_assert( midpoint(-5, -4) == -5 );
+static_assert( midpoint(-4, -5) == -4 );
+static_assert( midpoint(INT_MIN, INT_MAX) == -1 );
+static_assert( midpoint(INT_MAX, INT_MIN) == 0 );
+static_assert( midpoint(INT_MAX, INT_MAX) == INT_MAX );
+static_assert( midpoint(INT_MAX, INT_MAX-1) == INT_MAX );
+static_assert( midpoint(INT_MAX-1, INT_MAX-1) == INT_MAX-1 );
+static_assert( midpoint(INT_MAX-1, INT_MAX) == INT_MAX-1 );
+static_assert( midpoint(INT_MAX, INT_MAX-2) == INT_MAX-1 );
+
+static_assert( midpoint(0u, 0u) == 0 );
+static_assert( midpoint(0u, 1u) == 0 );
+static_assert( midpoint(1u, 0u) == 1 );
+static_assert( midpoint(0u, 2u) == 1 );
+static_assert( midpoint(3u, 2u) == 3 );
+static_assert( midpoint(0u, UINT_MAX) == UINT_MAX/2 );
+static_assert( midpoint(UINT_MAX, 0u) == (UINT_MAX/2 + 1) );
+static_assert( midpoint(UINT_MAX, UINT_MAX) == UINT_MAX );
+static_assert( midpoint(UINT_MAX, UINT_MAX-1) == UINT_MAX );
+static_assert( midpoint(UINT_MAX-1, UINT_MAX-1) == UINT_MAX-1 );
+static_assert( midpoint(UINT_MAX-1, UINT_MAX) == UINT_MAX-1 );
+static_assert( midpoint(UINT_MAX, UINT_MAX-2) == UINT_MAX-1 );
+
+static_assert( midpoint<short>(0, 0) == 0 );
+static_assert( midpoint<short>(0, 1) == 0 );
+static_assert( midpoint<short>(1, 0) == 1 );
+static_assert( midpoint<short>(0, 2) == 1 );
+static_assert( midpoint<short>(3, 2) == 3 );
+static_assert( midpoint<short>(-5, 4) == -1 );
+static_assert( midpoint<short>(5, -4) == 1 );
+static_assert( midpoint<short>(-5, -4) == -5 );
+static_assert( midpoint<short>(-4, -5) == -4 );
+static_assert( midpoint<short>(SHRT_MIN, SHRT_MAX) == -1 );
+static_assert( midpoint<short>(SHRT_MAX, SHRT_MIN) == 0 );
+static_assert( midpoint<short>(SHRT_MAX, SHRT_MAX) == SHRT_MAX );
+static_assert( midpoint<short>(SHRT_MAX, SHRT_MAX-1) == SHRT_MAX );
+static_assert( midpoint<short>(SHRT_MAX-1, SHRT_MAX-1) == SHRT_MAX-1 );
+static_assert( midpoint<short>(SHRT_MAX-1, SHRT_MAX) == SHRT_MAX-1 );
+static_assert( midpoint<short>(SHRT_MAX, SHRT_MAX-2) == SHRT_MAX-1 );
+
+static_assert( midpoint<signed char>(0, 0) == 0 );
+static_assert( midpoint<signed char>(1, 1) == 1 );
+static_assert( midpoint<signed char>(0, 1) == 0 );
+static_assert( midpoint<signed char>(1, 0) == 1 );
+static_assert( midpoint<signed char>(0, 2) == 1 );
+static_assert( midpoint<signed char>(3, 2) == 3 );
+static_assert( midpoint<signed char>(-5, 4) == -1 );
+static_assert( midpoint<signed char>(5, -4) == 1 );
+static_assert( midpoint<signed char>(-5, -4) == -5 );
+static_assert( midpoint<signed char>(-4, -5) == -4 );
+static_assert( midpoint<signed char>(SCHAR_MIN, SCHAR_MAX) == -1 );
+static_assert( midpoint<signed char>(SCHAR_MAX, SCHAR_MIN) == 0 );
+static_assert( midpoint<signed char>(SCHAR_MAX, SCHAR_MAX) == SCHAR_MAX );
+static_assert( midpoint<signed char>(SCHAR_MAX, SCHAR_MAX-1) == SCHAR_MAX);
+
+void
+test01()
+{
+  // Test every possibility for signed char.
+  for (int a = SCHAR_MIN; a <= SCHAR_MAX; ++a)
+    for (int b = SCHAR_MIN; b <= SCHAR_MAX; ++b)
+      assert( midpoint(a, b) == midpoint<int>(a, b) );
+}
+
+int main()
+{
+  test01();
+}