Repository: computationalgeography/lue (language: python)

Issue:
Overload all unary local operation algorithms accepting Element values with versions that accept `Scalar<Element>`



Discussion / hints:

Fix patch:
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/abs.hpp b/source/framework/algorithm/include/lue/framework/algorithm/abs.hpp
index 1ed763759..b06ea64a5 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/abs.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/abs.hpp
@@ -1,12 +1,31 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
+#include <cmath>
 
 
 namespace lue {
+    namespace detail {
 
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> abs(
-        Policies const& policies, PartitionedArray<Element, rank> const& array);
+        template<typename InputElement>
+        class Abs
+        {
+
+            public:
+
+                static_assert(std::is_signed_v<InputElement> || std::is_floating_point_v<InputElement>);
+
+                using OutputElement = InputElement;
+
+                auto operator()(InputElement const input_element) const noexcept -> OutputElement
+                {
+                    return std::abs(input_element);
+                }
+        };
+
+    }  // namespace detail
+
+
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(abs, detail::Abs)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/acos.hpp b/source/framework/algorithm/include/lue/framework/algorithm/acos.hpp
index 4b63eeff6..5c501650f 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/acos.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/acos.hpp
@@ -1,12 +1,32 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
+#include <cmath>
 
 
 namespace lue {
+    namespace detail {
 
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> acos(
-        Policies const& policies, PartitionedArray<Element, rank> const& array);
+        template<typename InputElement>
+        class ACos
+        {
+
+            public:
+
+                static_assert(std::is_floating_point_v<InputElement>);
+
+                using OutputElement = InputElement;
+
+
+                auto operator()(InputElement const& input_element) const noexcept -> OutputElement
+                {
+                    return std::acos(input_element);
+                }
+        };
+
+    }  // namespace detail
+
+
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(acos, detail::ACos)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/add.hpp b/source/framework/algorithm/include/lue/framework/algorithm/add.hpp
index 39dc9667f..cc5ddb537 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/add.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/add.hpp
@@ -15,8 +15,9 @@ namespace lue {
 
                 using OutputElement = OutputElement_;
 
-                constexpr OutputElement operator()(
+                constexpr auto operator()(
                     InputElement const& input_element1, InputElement const& input_element2) const noexcept
+                    -> OutputElement
                 {
                     return input_element1 + input_element2;
                 }
@@ -33,6 +34,6 @@ namespace lue {
     }  // namespace policy::add
 
 
-    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(add, detail::Add)
+    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(add, detail::Add)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/all.hpp b/source/framework/algorithm/include/lue/framework/algorithm/all.hpp
index 446713840..e92510963 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/all.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/all.hpp
@@ -17,34 +17,36 @@ namespace lue {
 
                 using OutputElement = InputElement;
 
-                constexpr OutputElement operator()() const noexcept
+                constexpr auto operator()() const noexcept -> OutputElement
                 {
                     // The result is false if there are not values to aggregate
                     return false;
                 }
 
-                constexpr OutputElement operator()(InputElement const input_element) const noexcept
+                constexpr auto operator()(InputElement const input_element) const noexcept -> OutputElement
                 {
                     // The result is true if the input element is true
                     return input_element;
                 }
 
-                constexpr OutputElement operator()(
+                constexpr auto operator()(
                     InputElement const aggregate_value, InputElement const input_element) const noexcept
+                    -> OutputElement
                 {
                     // The result is true if the value aggregated until now is true
                     // and the input element is true
                     return aggregate_value && input_element;
                 }
 
-                constexpr OutputElement partition(OutputElement const input_element) const noexcept
+                constexpr auto partition(OutputElement const input_element) const noexcept -> OutputElement
                 {
                     // The result is true if the input element is true
                     return input_element;
                 }
 
-                constexpr OutputElement partition(
+                constexpr auto partition(
                     OutputElement const aggregated_value, OutputElement const input_element) const noexcept
+                    -> OutputElement
                 {
                     // The result is true if the value aggregated until now is true
                     // and the input element is true
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/asin.hpp b/source/framework/algorithm/include/lue/framework/algorithm/asin.hpp
index 010ddf067..06dc86f05 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/asin.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/asin.hpp
@@ -1,12 +1,32 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
+#include <cmath>
 
 
 namespace lue {
+    namespace detail {
 
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> asin(
-        Policies const& policies, PartitionedArray<Element, rank> const& array);
+        template<typename InputElement>
+        class ASin
+        {
+
+            public:
+
+                static_assert(std::is_floating_point_v<InputElement>);
+
+                using OutputElement = InputElement;
+
+
+                auto operator()(InputElement const& input_element) const noexcept -> OutputElement
+                {
+                    return std::asin(input_element);
+                }
+        };
+
+    }  // namespace detail
+
+
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(asin, detail::ASin)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/atan.hpp b/source/framework/algorithm/include/lue/framework/algorithm/atan.hpp
index ab47f89fb..13d17ef40 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/atan.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/atan.hpp
@@ -1,12 +1,32 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
+#include <cmath>
 
 
 namespace lue {
+    namespace detail {
 
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> atan(
-        Policies const& policies, PartitionedArray<Element, rank> const& array);
+        template<typename InputElement>
+        class ATan
+        {
+
+            public:
+
+                static_assert(std::is_floating_point_v<InputElement>);
+
+                using OutputElement = InputElement;
+
+
+                auto operator()(InputElement const& input_element) const noexcept -> OutputElement
+                {
+                    return std::atan(input_element);
+                }
+        };
+
+    }  // namespace detail
+
+
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(atan, detail::ATan)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/binary_local_operation.hpp b/source/framework/algorithm/include/lue/framework/algorithm/binary_local_operation.hpp
index 62d30479b..fd1fb3206 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/binary_local_operation.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/binary_local_operation.hpp
@@ -1,327 +1,308 @@
 #pragma once
-#include "lue/framework/algorithm/functor_traits.hpp"
+#include "lue/framework/algorithm/policy/policy_traits.hpp"
 #include "lue/framework/algorithm/scalar.hpp"
 #include "lue/framework/partitioned_array.hpp"
+#include <type_traits>
 
 
 namespace lue {
 
     // local_operation(partition, scalar)
-    template<typename Policies, typename InputElement1, typename InputElement2, Rank rank, typename Functor>
+    template<typename Policies, Rank rank, typename Functor>
     auto binary_local_operation(
         hpx::id_type locality_id,
         Policies const& policies,
-        ArrayPartition<InputElement1, rank> const& input_partition,
-        hpx::shared_future<InputElement2> const& input_scalar,
-        Functor const& functor) -> ArrayPartition<OutputElementT<Functor>, rank>;
+        ArrayPartition<policy::InputElementT<Policies, 0>, rank> const& input_partition,
+        hpx::shared_future<policy::InputElementT<Policies, 1>> const& input_scalar,
+        Functor const& functor) -> ArrayPartition<policy::OutputElementT<Policies, 0>, rank>;
 
     // local_operation(array, array)
-    template<typename Policies, typename InputElement1, typename InputElement2, Rank rank, typename Functor>
+    template<typename Policies, Rank rank, typename Functor>
     auto binary_local_operation(
         Policies const& policies,
-        PartitionedArray<InputElement1, rank> const& input_array1,
-        PartitionedArray<InputElement2, rank> const& input_array2,
-        Functor const& functor) -> PartitionedArray<OutputElementT<Functor>, rank>;
+        PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& input_array1,
+        PartitionedArray<policy::InputElementT<Policies, 1>, rank> const& input_array2,
+        Functor const& functor) -> PartitionedArray<policy::OutputElementT<Policies, 0>, rank>;
 
     // local_operation(array, scalar)
-    template<typename Policies, typename InputElement1, typename InputElement2, Rank rank, typename Functor>
+    template<typename Policies, Rank rank, typename Functor>
     auto binary_local_operation(
         Policies const& policies,
-        PartitionedArray<InputElement1, rank> const& input_array,
-        hpx::shared_future<InputElement2> const& input_scalar,
-        Functor const& functor) -> PartitionedArray<OutputElementT<Functor>, rank>;
+        PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& input_array,
+        hpx::shared_future<policy::InputElementT<Policies, 1>> const& input_scalar,
+        Functor const& functor) -> PartitionedArray<policy::OutputElementT<Policies, 0>, rank>;
 
     // local_operation(scalar, array)
-    template<typename Policies, typename InputElement1, typename InputElement2, Rank rank, typename Functor>
+    template<typename Policies, Rank rank, typename Functor>
     auto binary_local_operation(
         Policies const& policies,
-        hpx::shared_future<InputElement1> const& input_scalar,
-        PartitionedArray<InputElement2, rank> const& input_array,
-        Functor const& functor) -> PartitionedArray<OutputElementT<Functor>, rank>;
+        hpx::shared_future<policy::InputElementT<Policies, 0>> const& input_scalar,
+        PartitionedArray<policy::InputElementT<Policies, 1>, rank> const& input_array,
+        Functor const& functor) -> PartitionedArray<policy::OutputElementT<Policies, 0>, rank>;
 
     // local_operation(scalar, scalar)
-    template<typename Policies, typename InputElement1, typename InputElement2, typename Functor>
+    template<typename Policies, typename Functor>
     auto binary_local_operation(
         Policies const& policies,
-        hpx::shared_future<InputElement1> const& input_scalar1,
-        hpx::shared_future<InputElement2> const& input_scalar2,
-        Functor const& functor) -> hpx::future<OutputElementT<Functor>>;
+        hpx::shared_future<policy::InputElementT<Policies, 0>> const& input_scalar1,
+        hpx::shared_future<policy::InputElementT<Policies, 1>> const& input_scalar2,
+        Functor const& functor) -> hpx::future<policy::OutputElementT<Policies, 0>>;
 
 }  // namespace lue
 
 
 // All overloads *with* a Policies template parameter
-#define LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(name, Functor)                                    \
+#define LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_DIFFERENT_OUTPUT_ELEMENT(name, Functor)           \
                                                                                                              \
     /* f(policies, array, array) */                                                                          \
-    template<typename Policies, typename InputElement, Rank rank>                                            \
+    template<typename Policies, Rank rank>                                                                   \
     auto name(                                                                                               \
         Policies const& policies,                                                                            \
-        PartitionedArray<InputElement, rank> const& array1,                                                  \
-        PartitionedArray<InputElement, rank> const& array2)                                                  \
+        PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& array1,                            \
+        PartitionedArray<policy::InputElementT<Policies, 1>, rank> const& array2)                            \
+        ->PartitionedArray<policy::OutputElementT<Policies, 0>, rank>                                        \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-                                                                                                             \
-        return binary_local_operation(policies, array1, array2, Functor<InputElement, OutputElement>{});     \
+        return binary_local_operation(                                                                       \
+            policies,                                                                                        \
+            array1,                                                                                          \
+            array2,                                                                                          \
+            Functor<policy::InputElementT<Policies, 0>, policy::OutputElementT<Policies, 0>>{});             \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
     /* f(policies, array, scalar) */                                                                         \
-    template<typename Policies, typename OutputElement, typename InputElement, Rank rank>                    \
+    template<typename Policies, Rank rank>                                                                   \
     auto name(                                                                                               \
         Policies const& policies,                                                                            \
-        PartitionedArray<InputElement, rank> const& array,                                                   \
-        Scalar<InputElement> const& scalar)                                                                  \
-        ->PartitionedArray<OutputElement, rank>                                                              \
+        PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& array,                             \
+        Scalar<policy::InputElementT<Policies, 1>> const& scalar)                                            \
+        ->PartitionedArray<policy::OutputElementT<Policies, 0>, rank>                                        \
     {                                                                                                        \
         return binary_local_operation(                                                                       \
-            policies, array, scalar.future(), Functor<InputElement, OutputElement>{});                       \
+            policies,                                                                                        \
+            array,                                                                                           \
+            scalar.future(),                                                                                 \
+            Functor<policy::InputElementT<Policies, 0>, policy::OutputElementT<Policies, 0>>{});             \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(policies, array, value_f) */                                                                        \
-    template<typename Policies, typename OutputElement, typename InputElement, Rank rank>                    \
+    /* f(policies, array, value) */                                                                          \
+    template<typename Policies, Rank rank>                                                                   \
     auto name(                                                                                               \
         Policies const& policies,                                                                            \
-        PartitionedArray<InputElement, rank> const& array,                                                   \
-        hpx::shared_future<InputElement> const& value_f)                                                     \
-        ->PartitionedArray<OutputElement, rank>                                                              \
+        PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& array,                             \
+        policy::InputElementT<Policies, 1> const value)                                                      \
+        ->PartitionedArray<policy::OutputElementT<Policies, 0>, rank>                                        \
     {                                                                                                        \
-        return name<Policies, OutputElement, InputElement, rank>(                                            \
-            policies, array, Scalar<InputElement>{value_f});                                                 \
+        return name(policies, array, Scalar{value});                                                         \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(policies, array, value) */                                                                          \
-    template<typename Policies, typename OutputElement, typename InputElement, Rank rank>                    \
+    /* f(policies, scalar, array) */                                                                         \
+    template<typename Policies, Rank rank>                                                                   \
     auto name(                                                                                               \
         Policies const& policies,                                                                            \
-        PartitionedArray<InputElement, rank> const& array,                                                   \
-        InputElement const& value)                                                                           \
-        ->PartitionedArray<OutputElement, rank>                                                              \
+        Scalar<policy::InputElementT<Policies, 0>> const& scalar,                                            \
+        PartitionedArray<policy::InputElementT<Policies, 1>, rank> const& array)                             \
+        ->PartitionedArray<policy::OutputElementT<Policies, 0>, rank>                                        \
     {                                                                                                        \
-        return name<Policies, OutputElement, InputElement, rank>(                                            \
-            policies, array, Scalar<InputElement>{value});                                                   \
+        return binary_local_operation(                                                                       \
+            policies,                                                                                        \
+            scalar.future(),                                                                                 \
+            array,                                                                                           \
+            Functor<policy::InputElementT<Policies, 0>, policy::OutputElementT<Policies, 0>>{});             \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(policies, array, scalar) */                                                                         \
-    template<typename Policies, typename InputElement, Rank rank>                                            \
+    /* f(policies, value, array) */                                                                          \
+    template<typename Policies, Rank rank>                                                                   \
     auto name(                                                                                               \
         Policies const& policies,                                                                            \
-        PartitionedArray<InputElement, rank> const& array,                                                   \
-        Scalar<InputElement> const& scalar)                                                                  \
+        policy::InputElementT<Policies, 0> const value,                                                      \
+        PartitionedArray<policy::InputElementT<Policies, 1>, rank> const& array)                             \
+        ->PartitionedArray<policy::OutputElementT<Policies, 0>, rank>                                        \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-                                                                                                             \
-        return name<Policies, OutputElement, InputElement, rank>(policies, array, scalar);                   \
+        return name(policies, Scalar{value}, array);                                                         \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(policies, array, value_f) */                                                                        \
-    template<typename Policies, typename InputElement, Rank rank>                                            \
+    /* f(policies, scalar, scalar) */                                                                        \
+    template<typename Policies>                                                                              \
     auto name(                                                                                               \
         Policies const& policies,                                                                            \
-        PartitionedArray<InputElement, rank> const& array,                                                   \
-        hpx::shared_future<InputElement> const& value_f)                                                     \
+        Scalar<policy::InputElementT<Policies, 0>> const& scalar1,                                           \
+        Scalar<policy::InputElementT<Policies, 1>> const& scalar2)                                           \
+        ->Scalar<policy::OutputElementT<Policies, 0>>                                                        \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-                                                                                                             \
-        return name<Policies, OutputElement, InputElement, rank>(                                            \
-            policies, array, Scalar<InputElement>{value_f});                                                 \
+        return binary_local_operation(                                                                       \
+            policies,                                                                                        \
+            scalar1.future(),                                                                                \
+            scalar2.future(),                                                                                \
+            Functor<policy::InputElementT<Policies, 0>, policy::OutputElementT<Policies, 0>>{});             \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(policies, array, value) */                                                                          \
-    template<typename Policies, typename InputElement, Rank rank>                                            \
+    /* f(policies, scalar, value) */                                                                         \
+    template<typename Policies>                                                                              \
     auto name(                                                                                               \
         Policies const& policies,                                                                            \
-        PartitionedArray<InputElement, rank> const& array,                                                   \
-        InputElement const& value)                                                                           \
+        Scalar<policy::InputElementT<Policies, 0>> const& scalar,                                            \
+        policy::InputElementT<Policies, 1> const value)                                                      \
+        ->Scalar<policy::OutputElementT<Policies, 0>>                                                        \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-                                                                                                             \
-        return name<Policies, OutputElement, InputElement, rank>(                                            \
-            policies, array, Scalar<InputElement>{value});                                                   \
+        return name(policies, scalar, Scalar{value});                                                        \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(policies, scalar, array) */                                                                         \
-    template<typename Policies, typename OutputElement, typename InputElement, Rank rank>                    \
+    /* f(policies, value, scalar) */                                                                         \
+    template<typename Policies>                                                                              \
     auto name(                                                                                               \
         Policies const& policies,                                                                            \
-        Scalar<InputElement> const& scalar,                                                                  \
-        PartitionedArray<InputElement, rank> const& array)                                                   \
-        ->PartitionedArray<OutputElement, rank>                                                              \
+        policy::InputElementT<Policies, 0> const value,                                                      \
+        Scalar<policy::InputElementT<Policies, 1>> const& scalar)                                            \
+        ->Scalar<policy::OutputElementT<Policies, 0>>                                                        \
     {                                                                                                        \
-        return binary_local_operation(                                                                       \
-            policies, scalar.future(), array, Functor<InputElement, OutputElement>{});                       \
+        return name(policies, Scalar{value}, scalar);                                                        \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(policies, value_f, array) */                                                                        \
-    template<typename Policies, typename OutputElement, typename InputElement, Rank rank>                    \
+    /* f(policies, value, value) */                                                                          \
+    template<typename Policies>                                                                              \
     auto name(                                                                                               \
         Policies const& policies,                                                                            \
-        hpx::shared_future<InputElement> const& value_f,                                                     \
-        PartitionedArray<InputElement, rank> const& array)                                                   \
-        ->PartitionedArray<OutputElement, rank>                                                              \
+        policy::InputElementT<Policies, 0> const value1,                                                     \
+        policy::InputElementT<Policies, 1> const value2)                                                     \
+        ->Scalar<policy::OutputElementT<Policies, 0>>                                                        \
     {                                                                                                        \
-        return name<Policies, OutputElement, InputElement, rank>(                                            \
-            policies, Scalar<InputElement>{value_f}, array);                                                 \
-    }                                                                                                        \
-                                                                                                             \
+        return name(policies, Scalar{value1}, Scalar{value2});                                               \
+    }
+
+
+// All overloads *with* a Policies template parameter
+#define LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(name, Functor)                \
                                                                                                              \
-    /* f(policies, value, array) */                                                                          \
-    template<typename Policies, typename OutputElement, typename InputElement, Rank rank>                    \
+    /* f(policies, array, array) */                                                                          \
+    template<typename Policies, Rank rank>                                                                   \
     auto name(                                                                                               \
         Policies const& policies,                                                                            \
-        InputElement const& value,                                                                           \
-        PartitionedArray<InputElement, rank> const& array)                                                   \
-        ->PartitionedArray<OutputElement, rank>                                                              \
+        PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& array1,                            \
+        PartitionedArray<policy::InputElementT<Policies, 1>, rank> const& array2)                            \
+        ->PartitionedArray<policy::OutputElementT<Policies, 0>, rank>                                        \
     {                                                                                                        \
-        return name<Policies, OutputElement, InputElement, rank>(                                            \
-            policies, Scalar<InputElement>{value}, array);                                                   \
+        return binary_local_operation(                                                                       \
+            policies, array1, array2, Functor<policy::InputElementT<Policies, 0>>{});                        \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(policies, scalar, array) */                                                                         \
-    template<typename Policies, typename InputElement, Rank rank>                                            \
+    /* f(policies, array, scalar) */                                                                         \
+    template<typename Policies, Rank rank>                                                                   \
     auto name(                                                                                               \
         Policies const& policies,                                                                            \
-        Scalar<InputElement> const& scalar,                                                                  \
-        PartitionedArray<InputElement, rank> const& array)                                                   \
+        PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& array,                             \
+        Scalar<policy::InputElementT<Policies, 1>> const& scalar)                                            \
+        ->PartitionedArray<policy::OutputElementT<Policies, 0>, rank>                                        \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-                                                                                                             \
-        return name<Policies, OutputElement, InputElement, rank>(policies, scalar, array);                   \
+        return binary_local_operation(                                                                       \
+            policies, array, scalar.future(), Functor<policy::InputElementT<Policies, 0>>{});                \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(policies, value_f, array) */                                                                        \
-    template<typename Policies, typename InputElement, Rank rank>                                            \
+    /* f(policies, array, value) */                                                                          \
+    template<typename Policies, Rank rank>                                                                   \
     auto name(                                                                                               \
         Policies const& policies,                                                                            \
-        hpx::shared_future<InputElement> const& value_f,                                                     \
-        PartitionedArray<InputElement, rank> const& array)                                                   \
+        PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& array,                             \
+        policy::InputElementT<Policies, 1> const value)                                                      \
+        ->PartitionedArray<policy::OutputElementT<Policies, 0>, rank>                                        \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-                                                                                                             \
-        return name<Policies, OutputElement, InputElement, rank>(                                            \
-            policies, Scalar<InputElement>{value_f}, array);                                                 \
+        return name(policies, array, Scalar{value});                                                         \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(policies, value, array) */                                                                          \
-    template<typename Policies, typename InputElement, Rank rank>                                            \
+    /* f(policies, scalar, array) */                                                                         \
+    template<typename Policies, Rank rank>                                                                   \
     auto name(                                                                                               \
         Policies const& policies,                                                                            \
-        InputElement const& value,                                                                           \
-        PartitionedArray<InputElement, rank> const& array)                                                   \
+        Scalar<policy::InputElementT<Policies, 0>> const& scalar,                                            \
+        PartitionedArray<policy::InputElementT<Policies, 1>, rank> const& array)                             \
+        ->PartitionedArray<policy::OutputElementT<Policies, 0>, rank>                                        \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-                                                                                                             \
-        return name<Policies, OutputElement, InputElement, rank>(                                            \
-            policies, Scalar<InputElement>{value}, array);                                                   \
+        return binary_local_operation(                                                                       \
+            policies, scalar.future(), array, Functor<policy::InputElementT<Policies, 0>>{});                \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(policies, scalar, scalar) */                                                                        \
-    template<typename Policies, typename OutputElement, typename InputElement>                               \
+    /* f(policies, value, array) */                                                                          \
+    template<typename Policies, Rank rank>                                                                   \
     auto name(                                                                                               \
-        Policies const& policies, Scalar<InputElement> const& scalar1, Scalar<InputElement> const& scalar2)  \
-        ->Scalar<OutputElement>                                                                              \
+        Policies const& policies,                                                                            \
+        policy::InputElementT<Policies, 0> const value,                                                      \
+        PartitionedArray<policy::InputElementT<Policies, 1>, rank> const& array)                             \
+        ->PartitionedArray<policy::OutputElementT<Policies, 0>, rank>                                        \
     {                                                                                                        \
-        return binary_local_operation(                                                                       \
-            policies, scalar1.future(), scalar2.future(), Functor<InputElement, OutputElement>{});           \
+        return name(policies, Scalar{value}, array);                                                         \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
     /* f(policies, scalar, scalar) */                                                                        \
-    template<typename Policies, typename InputElement>                                                       \
+    template<typename Policies>                                                                              \
     auto name(                                                                                               \
-        Policies const& policies, Scalar<InputElement> const& scalar1, Scalar<InputElement> const& scalar2)  \
-    {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-                                                                                                             \
-        return name<Policies, OutputElement, InputElement>(policies, scalar1, scalar2);                      \
-    }                                                                                                        \
-                                                                                                             \
-                                                                                                             \
-    /* f(policies, scalar, value) */                                                                         \
-    template<typename Policies, typename OutputElement, typename InputElement>                               \
-    auto name(Policies const& policies, Scalar<InputElement> const& scalar, InputElement const& value)       \
-        ->Scalar<OutputElement>                                                                              \
+        Policies const& policies,                                                                            \
+        Scalar<policy::InputElementT<Policies, 0>> const& scalar1,                                           \
+        Scalar<policy::InputElementT<Policies, 1>> const& scalar2)                                           \
+        ->Scalar<policy::OutputElementT<Policies, 0>>                                                        \
     {                                                                                                        \
-        return name<Policies, OutputElement, InputElement>(                                                  \
-            policies, scalar.future(), Scalar<InputElement>{value});                                         \
+        return binary_local_operation(                                                                       \
+            policies, scalar1.future(), scalar2.future(), Functor<policy::InputElementT<Policies, 0>>{});    \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
     /* f(policies, scalar, value) */                                                                         \
-    template<typename Policies, typename InputElement>                                                       \
-    auto name(Policies const& policies, Scalar<InputElement> const& scalar, InputElement const& value)       \
-    {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-                                                                                                             \
-        return name<Policies, OutputElement, InputElement>(policies, scalar, Scalar<InputElement>{value});   \
-    }                                                                                                        \
-                                                                                                             \
-                                                                                                             \
-    /* f(policies, value, scalar) */                                                                         \
-    template<typename Policies, typename OutputElement, typename InputElement>                               \
-    auto name(Policies const& policies, InputElement const& value, Scalar<InputElement> const& scalar)       \
-        ->Scalar<OutputElement>                                                                              \
+    template<typename Policies>                                                                              \
+    auto name(                                                                                               \
+        Policies const& policies,                                                                            \
+        Scalar<policy::InputElementT<Policies, 0>> const& scalar,                                            \
+        policy::InputElementT<Policies, 1> const value)                                                      \
+        ->Scalar<policy::OutputElementT<Policies, 0>>                                                        \
     {                                                                                                        \
-        return name<Policies, OutputElement, InputElement>(                                                  \
-            policies, Scalar<InputElement>{value}, scalar.future());                                         \
+        return name(policies, scalar, Scalar{value});                                                        \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
     /* f(policies, value, scalar) */                                                                         \
-    template<typename Policies, typename InputElement>                                                       \
-    auto name(Policies const& policies, InputElement const& value, Scalar<InputElement> const& scalar)       \
-    {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-                                                                                                             \
-        return name<Policies, OutputElement, InputElement>(policies, Scalar<InputElement>{value}, scalar);   \
-    }                                                                                                        \
-                                                                                                             \
-                                                                                                             \
-    /* f(policies, value, value) */                                                                          \
-    template<typename Policies, typename OutputElement, typename InputElement>                               \
-    auto name(Policies const& policies, InputElement const& value1, InputElement const& value2)              \
-        ->Scalar<OutputElement>                                                                              \
+    template<typename Policies>                                                                              \
+    auto name(                                                                                               \
+        Policies const& policies,                                                                            \
+        policy::InputElementT<Policies, 0> const value,                                                      \
+        Scalar<policy::InputElementT<Policies, 1>> const& scalar)                                            \
+        ->Scalar<policy::OutputElementT<Policies, 0>>                                                        \
     {                                                                                                        \
-        return name<Policies, OutputElement, InputElement>(                                                  \
-            policies,                                                                                        \
-            Scalar<InputElement>{value1},                                                                    \
-            Scalar<InputElement>{value2},                                                                    \
-            Functor<InputElement, OutputElement>{});                                                         \
+        return name(policies, Scalar{value}, scalar);                                                        \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
     /* f(policies, value, value) */                                                                          \
-    template<typename Policies, typename InputElement>                                                       \
-    auto name(Policies const& policies, InputElement const& value1, InputElement const& value2)              \
+    template<typename Policies>                                                                              \
+    auto name(                                                                                               \
+        Policies const& policies,                                                                            \
+        policy::InputElementT<Policies, 0> const value1,                                                     \
+        policy::InputElementT<Policies, 1> const value2)                                                     \
+        ->Scalar<policy::OutputElementT<Policies, 0>>                                                        \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-                                                                                                             \
-        return name<Policies, OutputElement, InputElement>(                                                  \
-            policies, Scalar<InputElement>{value1}, Scalar<InputElement>{value2});                           \
+        return name(policies, Scalar{value1}, Scalar{value2});                                               \
     }
 
 
 // All overloads *without* a Policies template parameter
-#define LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(name, Functor, Policies)                       \
+#define LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(name, Policies)       \
                                                                                                              \
     /* f(array, array) */                                                                                    \
-    template<typename InputElement, Rank rank>                                                               \
+    template<typename OutputElement, typename InputElement, Rank rank>                                       \
     auto name(                                                                                               \
         PartitionedArray<InputElement, rank> const& array1,                                                  \
         PartitionedArray<InputElement, rank> const& array2)                                                  \
+        ->PartitionedArray<OutputElement, rank>                                                              \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
         using Policies_ = Policies<OutputElement, InputElement>;                                             \
                                                                                                              \
         return name(Policies_{}, array1, array2);                                                            \
@@ -330,216 +311,185 @@ namespace lue {
                                                                                                              \
     /* f(array, scalar) */                                                                                   \
     template<typename OutputElement, typename InputElement, Rank rank>                                       \
-    PartitionedArray<OutputElement, rank> name(                                                              \
-        PartitionedArray<InputElement, rank> const& array, Scalar<InputElement> const& scalar)               \
+    auto name(PartitionedArray<InputElement, rank> const& array, Scalar<InputElement> const& scalar)         \
+        ->PartitionedArray<OutputElement, rank>                                                              \
     {                                                                                                        \
         using Policies_ = Policies<OutputElement, InputElement>;                                             \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement, rank>(Policies_{}, array, scalar);               \
+        return name(Policies_{}, array, scalar);                                                             \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(array, value_f) */                                                                                  \
+    /* f(array, value) */                                                                                    \
     template<typename OutputElement, typename InputElement, Rank rank>                                       \
-    PartitionedArray<OutputElement, rank> name(                                                              \
-        PartitionedArray<InputElement, rank> const& array, hpx::shared_future<InputElement> const& value_f)  \
+    auto name(PartitionedArray<InputElement, rank> const& array, InputElement const value)                   \
+        ->PartitionedArray<OutputElement, rank>                                                              \
     {                                                                                                        \
         using Policies_ = Policies<OutputElement, InputElement>;                                             \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement, rank>(                                           \
-            Policies_{}, array, Scalar<InputElement>{value_f});                                              \
+        return name(Policies_{}, array, value);                                                              \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(array, value) */                                                                                    \
+    /* f(scalar, array) */                                                                                   \
     template<typename OutputElement, typename InputElement, Rank rank>                                       \
-    PartitionedArray<OutputElement, rank> name(                                                              \
-        PartitionedArray<InputElement, rank> const& array, InputElement const& value)                        \
+    auto name(Scalar<InputElement> const& scalar, PartitionedArray<InputElement, rank> const& array)         \
+        ->PartitionedArray<OutputElement, rank>                                                              \
     {                                                                                                        \
         using Policies_ = Policies<OutputElement, InputElement>;                                             \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement, rank>(                                           \
-            Policies_{}, array, Scalar<InputElement>{value});                                                \
-    }                                                                                                        \
-                                                                                                             \
-                                                                                                             \
-    /* f(array, scalar) */                                                                                   \
-    template<typename InputElement, Rank rank>                                                               \
-    auto name(PartitionedArray<InputElement, rank> const& array, Scalar<InputElement> const& scalar)         \
-    {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-                                                                                                             \
-        return name<OutputElement, InputElement, rank>(array, scalar);                                       \
-    }                                                                                                        \
-                                                                                                             \
-                                                                                                             \
-    /* f(array, value_f) */                                                                                  \
-    template<typename InputElement, Rank rank>                                                               \
-    auto name(                                                                                               \
-        PartitionedArray<InputElement, rank> const& array, hpx::shared_future<InputElement> const& value_f)  \
-    {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-                                                                                                             \
-        return name<OutputElement, InputElement, rank>(array, Scalar<InputElement>{value_f});                \
+        return name(Policies_{}, scalar, array);                                                             \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(array, value) */                                                                                    \
-    template<typename InputElement, Rank rank>                                                               \
-    auto name(PartitionedArray<InputElement, rank> const& array, InputElement const& value)                  \
+    /* f(value, array) */                                                                                    \
+    template<typename OutputElement, typename InputElement, Rank rank>                                       \
+    auto name(InputElement const value, PartitionedArray<InputElement, rank> const& array)                   \
+        ->PartitionedArray<OutputElement, rank>                                                              \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
+        using Policies_ = Policies<OutputElement, InputElement>;                                             \
                                                                                                              \
-        return name<OutputElement, InputElement, rank>(array, Scalar<InputElement>{value});                  \
+        return name(Policies_{}, value, array);                                                              \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(scalar, array) */                                                                                   \
-    template<typename OutputElement, typename InputElement, Rank rank>                                       \
-    PartitionedArray<OutputElement, rank> name(                                                              \
-        Scalar<InputElement> const& scalar, PartitionedArray<InputElement, rank> const& array)               \
+    /* f(scalar, scalar) */                                                                                  \
+    template<typename OutputElement, typename InputElement>                                                  \
+    auto name(Scalar<InputElement> const& scalar1, Scalar<InputElement> const& scalar2)                      \
+        ->Scalar<OutputElement>                                                                              \
     {                                                                                                        \
         using Policies_ = Policies<OutputElement, InputElement>;                                             \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement, rank>(Policies_{}, scalar, array);               \
+        return name(Policies_{}, scalar1, scalar2);                                                          \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(value_f, array) */                                                                                  \
-    template<typename OutputElement, typename InputElement, Rank rank>                                       \
-    PartitionedArray<OutputElement, rank> name(                                                              \
-        hpx::shared_future<InputElement> const& value_f, PartitionedArray<InputElement, rank> const& array)  \
+    /* f(scalar, value) */                                                                                   \
+    template<typename OutputElement, typename InputElement>                                                  \
+    auto name(Scalar<InputElement> const& scalar, InputElement const value)->Scalar<OutputElement>           \
     {                                                                                                        \
         using Policies_ = Policies<OutputElement, InputElement>;                                             \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement, rank>(                                           \
-            Policies_{}, Scalar<InputElement>{value_f}, array);                                              \
+        return name(Policies_{}, scalar, value);                                                             \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(value, array) */                                                                                    \
-    template<typename OutputElement, typename InputElement, Rank rank>                                       \
-    PartitionedArray<OutputElement, rank> name(                                                              \
-        InputElement const& value, PartitionedArray<InputElement, rank> const& array)                        \
+    /* f(value, scalar) */                                                                                   \
+    template<typename OutputElement, typename InputElement>                                                  \
+    auto name(InputElement const value, Scalar<InputElement> const& scalar)->Scalar<OutputElement>           \
     {                                                                                                        \
         using Policies_ = Policies<OutputElement, InputElement>;                                             \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement, rank>(                                           \
-            Policies_{}, Scalar<InputElement>{value}, array);                                                \
+        return name(Policies_{}, value, scalar);                                                             \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(scalar, array) */                                                                                   \
-    template<typename InputElement, Rank rank>                                                               \
-    auto name(Scalar<InputElement> const& scalar, PartitionedArray<InputElement, rank> const& array)         \
+    /* f(value, value) */                                                                                    \
+    template<typename OutputElement, typename InputElement>                                                  \
+    requires std::is_arithmetic_v<OutputElement>&& std::is_arithmetic_v<InputElement> auto name(             \
+        InputElement const value1, InputElement const value2)                                                \
+        ->Scalar<OutputElement>                                                                              \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
         using Policies_ = Policies<OutputElement, InputElement>;                                             \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement, rank>(Policies_{}, scalar, array);               \
-    }                                                                                                        \
-                                                                                                             \
+        return lue::name(Policies_{}, value1, value2);                                                       \
+    }
+
+
+// All overloads *without* a Policies template parameter
+#define LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(name, Policies)            \
                                                                                                              \
-    /* f(value_f, array) */                                                                                  \
-    template<typename InputElement, Rank rank>                                                               \
-    auto name(                                                                                               \
-        hpx::shared_future<InputElement> const& value_f, PartitionedArray<InputElement, rank> const& array)  \
+    /* f(array, array) */                                                                                    \
+    template<typename Element, Rank rank>                                                                    \
+    auto name(PartitionedArray<Element, rank> const& array1, PartitionedArray<Element, rank> const& array2)  \
+        ->PartitionedArray<Element, rank>                                                                    \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-        using Policies_ = Policies<OutputElement, InputElement>;                                             \
+        using Policies_ = Policies<Element>;                                                                 \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement, rank>(                                           \
-            Policies_{}, Scalar<InputElement>{value_f}, array);                                              \
+        return name(Policies_{}, array1, array2);                                                            \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(value, array) */                                                                                    \
-    template<typename InputElement, Rank rank>                                                               \
-    auto name(InputElement const& value, PartitionedArray<InputElement, rank> const& array)                  \
+    /* f(array, scalar) */                                                                                   \
+    template<typename Element, Rank rank>                                                                    \
+    auto name(PartitionedArray<Element, rank> const& array, Scalar<Element> const& scalar)                   \
+        ->PartitionedArray<Element, rank>                                                                    \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-        using Policies_ = Policies<OutputElement, InputElement>;                                             \
+        using Policies_ = Policies<Element>;                                                                 \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement, rank>(                                           \
-            Policies_{}, Scalar<InputElement>{value}, array);                                                \
+        return name(Policies_{}, array, scalar);                                                             \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(scalar, scalar) */                                                                                  \
-    template<typename InputElement>                                                                          \
-    auto name(Scalar<InputElement> const& scalar1, Scalar<InputElement> const& scalar2)                      \
+    /* f(array, value) */                                                                                    \
+    template<typename Element, Rank rank>                                                                    \
+    auto name(PartitionedArray<Element, rank> const& array, Element const value)                             \
+        ->PartitionedArray<Element, rank>                                                                    \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-        using Policies_ = Policies<OutputElement, InputElement>;                                             \
+        using Policies_ = Policies<Element>;                                                                 \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement>(Policies_{}, scalar1, scalar2);                  \
+        return name(Policies_{}, array, value);                                                              \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(scalar, value) */                                                                                   \
-    template<typename OutputElement, typename InputElement>                                                  \
-    auto name(Scalar<InputElement> const& scalar, InputElement const& value)->Scalar<OutputElement>          \
+    /* f(scalar, array) */                                                                                   \
+    template<typename Element, Rank rank>                                                                    \
+    auto name(Scalar<Element> const& scalar, PartitionedArray<Element, rank> const& array)                   \
+        ->PartitionedArray<Element, rank>                                                                    \
     {                                                                                                        \
-        using Policies_ = Policies<OutputElement, InputElement>;                                             \
+        using Policies_ = Policies<Element>;                                                                 \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement>(                                                 \
-            Policies_{}, scalar.future(), Scalar<InputElement>{value});                                      \
+        return name(Policies_{}, scalar, array);                                                             \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(scalar, value) */                                                                                   \
-    template<typename InputElement>                                                                          \
-    auto name(Scalar<InputElement> const& scalar, InputElement const& value)                                 \
+    /* f(value, array) */                                                                                    \
+    template<typename Element, Rank rank>                                                                    \
+    auto name(Element const value, PartitionedArray<Element, rank> const& array)                             \
+        ->PartitionedArray<Element, rank>                                                                    \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-        using Policies_ = Policies<OutputElement, InputElement>;                                             \
+        using Policies_ = Policies<Element>;                                                                 \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement>(                                                 \
-            Policies_{}, scalar, Scalar<InputElement>{value});                                               \
+        return name(Policies_{}, value, array);                                                              \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(value, scalar) */                                                                                   \
-    template<typename OutputElement, typename InputElement>                                                  \
-    auto name(InputElement const& value, Scalar<InputElement> const& scalar)->Scalar<OutputElement>          \
+    /* f(scalar, scalar) */                                                                                  \
+    template<typename Element>                                                                               \
+    auto name(Scalar<Element> const& scalar1, Scalar<Element> const& scalar2)->Scalar<Element>               \
     {                                                                                                        \
-        using Policies_ = Policies<OutputElement, InputElement>;                                             \
+        using Policies_ = Policies<Element>;                                                                 \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement>(                                                 \
-            Policies_{}, Scalar<InputElement>{value}, scalar.future());                                      \
+        return name(Policies_{}, scalar1, scalar2);                                                          \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(value, scalar) */                                                                                   \
-    template<typename InputElement>                                                                          \
-    auto name(InputElement const& value, Scalar<InputElement> const& scalar)                                 \
+    /* f(scalar, value) */                                                                                   \
+    template<typename Element>                                                                               \
+    auto name(Scalar<Element> const& scalar, Element const value)->Scalar<Element>                           \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-        using Policies_ = Policies<OutputElement, InputElement>;                                             \
+        using Policies_ = Policies<Element>;                                                                 \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement>(                                                 \
-            Policies_{}, Scalar<InputElement>{value}, scalar);                                               \
+        return name(Policies_{}, scalar, value);                                                             \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
-    /* f(value, value) */                                                                                    \
-    template<typename OutputElement, typename InputElement>                                                  \
-    auto name(InputElement const& value1, InputElement const& value2)                                        \
+    /* f(value, scalar) */                                                                                   \
+    template<typename Element>                                                                               \
+    auto name(Element const value, Scalar<Element> const& scalar)->Scalar<Element>                           \
     {                                                                                                        \
-        using Policies_ = Policies<OutputElement, InputElement>;                                             \
+        using Policies_ = Policies<Element>;                                                                 \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement>(                                                 \
-            Policies_{}, Scalar<InputElement>{value1}, Scalar<InputElement>{value2});                        \
+        return name(Policies_{}, value, scalar);                                                             \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
     /* f(value, value) */                                                                                    \
-    template<typename InputElement>                                                                          \
-    auto name(InputElement const& value1, InputElement const& value2)                                        \
+    template<typename Element>                                                                               \
+    requires std::is_arithmetic_v<Element> auto name(Element const value1, Element const value2)             \
+        ->Scalar<Element>                                                                                    \
     {                                                                                                        \
-        using OutputElement = OutputElementT<Functor<InputElement>>;                                         \
-        using Policies_ = Policies<OutputElement, InputElement>;                                             \
+        using Policies_ = Policies<Element>;                                                                 \
                                                                                                              \
-        return name<Policies_, OutputElement, InputElement>(                                                 \
-            Policies_{}, Scalar<InputElement>{value1}, Scalar<InputElement>{value2});                        \
+        return lue::name(Policies_{}, value1, value2);                                                       \
     }
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/cast.hpp b/source/framework/algorithm/include/lue/framework/algorithm/cast.hpp
index 0be70bfb4..2d2f22f4d 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/cast.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/cast.hpp
@@ -1,12 +1,32 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
 
 
 namespace lue {
+    namespace detail {
 
-    template<typename OutputElement, typename Policies, typename InputElement, Rank rank>
-    PartitionedArray<OutputElement, rank> cast(
-        Policies const& policies, PartitionedArray<InputElement, rank> const& array);
+        template<typename InputElement, typename OutputElement_>
+        class Cast
+        {
+
+            public:
+
+                using OutputElement = OutputElement_;
+
+                static_assert(std::is_arithmetic_v<InputElement>);
+                static_assert(std::is_arithmetic_v<OutputElement>);
+
+
+                constexpr auto operator()(InputElement const& input_element) const noexcept -> OutputElement
+                {
+                    return static_cast<OutputElement>(input_element);
+                }
+        };
+
+    }  // namespace detail
+
+
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_DIFFERENT_OUTPUT_ELEMENT(cast, detail::Cast)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/ceil.hpp b/source/framework/algorithm/include/lue/framework/algorithm/ceil.hpp
index 296e272a3..dc2bea834 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/ceil.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/ceil.hpp
@@ -1,12 +1,32 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
+#include <cmath>
 
 
 namespace lue {
+    namespace detail {
 
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> ceil(
-        Policies const& policies, PartitionedArray<Element, rank> const& array);
+        template<typename InputElement>
+        class Ceil
+        {
+
+            public:
+
+                static_assert(std::is_floating_point_v<InputElement>);
+
+                using OutputElement = InputElement;
+
+
+                auto operator()(InputElement const& input_element) const noexcept -> OutputElement
+                {
+                    return std::ceil(input_element);
+                }
+        };
+
+    }  // namespace detail
+
+
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(ceil, detail::Ceil)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/close_to.hpp b/source/framework/algorithm/include/lue/framework/algorithm/close_to.hpp
index b0c7d1698..b8574b41c 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/close_to.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/close_to.hpp
@@ -31,8 +31,9 @@ namespace lue {
                 }
 
 
-                constexpr OutputElement operator()(
+                constexpr auto operator()(
                     InputElement const& input_element1, InputElement const& input_element2) const noexcept
+                    -> OutputElement
                 {
                     return std::abs(input_element1 - input_element2) <=
                            (_absolute_difference + _relative_difference * std::abs(input_element2));
@@ -59,6 +60,6 @@ namespace lue {
     }  // namespace detail
 
 
-    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(close_to, detail::CloseTo)
+    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_DIFFERENT_OUTPUT_ELEMENT(close_to, detail::CloseTo)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/cos.hpp b/source/framework/algorithm/include/lue/framework/algorithm/cos.hpp
index d7ee7f444..8de1f6997 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/cos.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/cos.hpp
@@ -1,12 +1,32 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
+#include <cmath>
 
 
 namespace lue {
+    namespace detail {
 
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> cos(
-        Policies const& policies, PartitionedArray<Element, rank> const& array);
+        template<typename InputElement>
+        class Cos
+        {
+
+            public:
+
+                static_assert(std::is_floating_point_v<InputElement>);
+
+                using OutputElement = InputElement;
+
+
+                auto operator()(InputElement const& input_element) const noexcept -> OutputElement
+                {
+                    return std::cos(input_element);
+                }
+        };
+
+    }  // namespace detail
+
+
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(cos, detail::Cos)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/abs.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/abs.hpp
index 7cff79327..47e053b3a 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/abs.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/abs.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        auto abs(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::abs::DefaultPolicies<Element>;
-
-            return abs(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            abs, policy::abs::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/acos.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/acos.hpp
index 581f50bbf..10daafa0a 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/acos.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/acos.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        auto acos(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::acos::DefaultPolicies<Element>;
-
-            return acos(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            acos, policy::acos::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/add.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/add.hpp
index 978f72bf8..fc7cc9d30 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/add.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/add.hpp
@@ -6,18 +6,17 @@
 namespace lue {
     namespace policy::add {
 
-        template<typename OutputElement, typename InputElement>
-        using DefaultPolicies = policy::DefaultPolicies<
-            DomainPolicy<InputElement>,
-            OutputElements<OutputElement>,
-            InputElements<InputElement, InputElement>>;
+        template<typename Element>
+        using DefaultPolicies = policy::
+            DefaultPolicies<DomainPolicy<Element>, OutputElements<Element>, InputElements<Element, Element>>;
 
     }  // namespace policy::add
 
 
     namespace default_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(add, detail::Add, policy::add::DefaultPolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            add, policy::add::DefaultPolicies)
         LUE_BINARY_ARITHMETIC_OPERATOR(+, add)
 
     }  // namespace default_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/asin.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/asin.hpp
index c87054e5d..0feb698ef 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/asin.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/asin.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        auto asin(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::asin::DefaultPolicies<Element>;
-
-            return asin(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            asin, policy::asin::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/atan.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/atan.hpp
index 00d7bfa1a..514f02ec8 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/atan.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/atan.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        auto atan(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::atan::DefaultPolicies<Element>;
-
-            return atan(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            atan, policy::atan::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/cast.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/cast.hpp
index e8e46cb02..7ead041d1 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/cast.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/cast.hpp
@@ -16,13 +16,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename OutputElement, typename InputElement, Rank rank>
-        PartitionedArray<OutputElement, rank> cast(PartitionedArray<InputElement, rank> const& array)
-        {
-            using Policies = policy::cast::DefaultPolicies<OutputElement, InputElement>;
-
-            return lue::cast<OutputElement>(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            cast, policy::cast::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/ceil.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/ceil.hpp
index e6d5d9dd8..5103431f5 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/ceil.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/ceil.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        auto ceil(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::ceil::DefaultPolicies<Element>;
-
-            return ceil(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            ceil, policy::ceil::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/close_to.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/close_to.hpp
index e4522f171..61a4e529e 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/close_to.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/close_to.hpp
@@ -1,6 +1,5 @@
 #pragma once
 #include "lue/framework/algorithm/close_to.hpp"
-#include "lue/framework/algorithm/pow.hpp"
 
 
 namespace lue {
@@ -17,9 +16,8 @@ namespace lue {
 
     namespace default_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            close_to, detail::CloseTo, policy::close_to::DefaultPolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            close_to, policy::close_to::DefaultPolicies)
 
     }  // namespace default_policies
-
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/cos.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/cos.hpp
index 0320a8f6d..3bc79af8d 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/cos.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/cos.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        auto cos(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::cos::DefaultPolicies<Element>;
-
-            return cos(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            cos, policy::cos::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/divide.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/divide.hpp
index 5388bdc3b..acb3fb0b1 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/divide.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/divide.hpp
@@ -5,19 +5,17 @@
 namespace lue {
     namespace policy::divide {
 
-        template<typename OutputElement, typename InputElement>
-        using DefaultPolicies = policy::DefaultPolicies<
-            DomainPolicy<InputElement>,
-            OutputElements<OutputElement>,
-            InputElements<InputElement, InputElement>>;
+        template<typename Element>
+        using DefaultPolicies = policy::
+            DefaultPolicies<DomainPolicy<Element>, OutputElements<Element>, InputElements<Element, Element>>;
 
     }  // namespace policy::divide
 
 
     namespace default_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            divide, detail::Divide, policy::divide::DefaultPolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            divide, policy::divide::DefaultPolicies)
         LUE_BINARY_ARITHMETIC_OPERATOR(/, divide)
 
     }  // namespace default_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/equal_to.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/equal_to.hpp
index ae07b8ea3..6d30e9df5 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/equal_to.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/equal_to.hpp
@@ -19,10 +19,10 @@ namespace lue {
 
         // partition == scalar_f
         template<typename InputElement, typename OutputElement = std::uint8_t, Rank rank>
-        ArrayPartition<OutputElement, rank> equal_to(
+        auto equal_to(
             hpx::id_type const locality_id,
             ArrayPartition<InputElement, rank> const& partition,
-            hpx::shared_future<InputElement> const& scalar)
+            hpx::shared_future<InputElement> const& scalar) -> ArrayPartition<OutputElement, rank>
         {
             using Policies = policy::equal_to::DefaultPolicies<OutputElement, InputElement>;
 
@@ -33,18 +33,18 @@ namespace lue {
 
         // partition == scalar
         template<typename InputElement, typename OutputElement = std::uint8_t, Rank rank>
-        ArrayPartition<OutputElement, rank> equal_to(
+        auto equal_to(
             hpx::id_type const locality_id,
             ArrayPartition<InputElement, rank> const& partition,
-            InputElement const& scalar)
+            InputElement const& scalar) -> ArrayPartition<OutputElement, rank>
         {
             return equal_to<InputElement, OutputElement, rank>(
                 locality_id, partition, hpx::make_ready_future<InputElement>(scalar).share());
         }
 
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            equal_to, detail::EqualTo, policy::equal_to::DefaultPolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            equal_to, policy::equal_to::DefaultPolicies)
         LUE_BINARY_COMPARISON_OPERATOR(==, equal_to)
 
     }  // namespace default_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/exp.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/exp.hpp
index e038fc13f..d26c1cca4 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/exp.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/exp.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        auto exp(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::exp::DefaultPolicies<Element>;
-
-            return exp(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            exp, policy::exp::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/floor.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/floor.hpp
index 1fb0a3fdd..110ca8d89 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/floor.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/floor.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        auto floor(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::floor::DefaultPolicies<Element>;
-
-            return floor(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            floor, policy::floor::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/greater_than.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/greater_than.hpp
index 40adba019..4c61e7aa6 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/greater_than.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/greater_than.hpp
@@ -16,8 +16,8 @@ namespace lue {
 
     namespace default_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            greater_than, detail::GreaterThan, policy::greater_than::DefaultPolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            greater_than, policy::greater_than::DefaultPolicies)
         LUE_BINARY_COMPARISON_OPERATOR(>, greater_than)
 
     }  // namespace default_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/greater_than_equal_to.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/greater_than_equal_to.hpp
index a6087c96e..a3534aa03 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/greater_than_equal_to.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/greater_than_equal_to.hpp
@@ -16,8 +16,8 @@ namespace lue {
 
     namespace default_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            greater_than_equal_to, detail::GreaterThanEqualTo, policy::greater_than_equal_to::DefaultPolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            greater_than_equal_to, policy::greater_than_equal_to::DefaultPolicies)
         LUE_BINARY_COMPARISON_OPERATOR(>=, greater_than_equal_to)
 
     }  // namespace default_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/less_than.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/less_than.hpp
index e55c8b315..98b7d8d8a 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/less_than.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/less_than.hpp
@@ -16,8 +16,8 @@ namespace lue {
 
     namespace default_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            less_than, detail::LessThan, policy::less_than::DefaultPolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            less_than, policy::less_than::DefaultPolicies)
         LUE_BINARY_COMPARISON_OPERATOR(<, less_than)
 
     }  // namespace default_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/less_than_equal_to.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/less_than_equal_to.hpp
index 57b93ba8f..227f29d59 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/less_than_equal_to.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/less_than_equal_to.hpp
@@ -16,8 +16,8 @@ namespace lue {
 
     namespace default_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            less_than_equal_to, detail::LessThanEqualTo, policy::less_than_equal_to::DefaultPolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            less_than_equal_to, policy::less_than_equal_to::DefaultPolicies)
         LUE_BINARY_COMPARISON_OPERATOR(<=, less_than_equal_to)
 
     }  // namespace default_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/log.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/log.hpp
index 53782aa0e..92d22e88d 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/log.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/log.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        auto log(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::log::DefaultPolicies<Element>;
-
-            return log(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            log, policy::log::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/log10.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/log10.hpp
index 66eb3e2cc..6b58b7a0c 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/log10.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/log10.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        auto log10(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::log10::DefaultPolicies<Element>;
-
-            return log10(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            log10, policy::log10::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_and.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_and.hpp
index 47d915fde..4ccbb54ce 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_and.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_and.hpp
@@ -17,8 +17,8 @@ namespace lue {
 
     namespace default_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            logical_and, detail::LogicalAnd, policy::logical_and::DefaultPolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            logical_and, policy::logical_and::DefaultPolicies)
         LUE_BINARY_LOGICAL_OPERATOR(&&, logical_and)
 
     }  // namespace default_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_exclusive_or.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_exclusive_or.hpp
index 60e88a3aa..d5dfaf4d8 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_exclusive_or.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_exclusive_or.hpp
@@ -17,8 +17,8 @@ namespace lue {
 
     namespace default_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            logical_exclusive_or, detail::LogicalExclusiveOr, policy::logical_exclusive_or::DefaultPolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            logical_exclusive_or, policy::logical_exclusive_or::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_inclusive_or.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_inclusive_or.hpp
index c08c6287d..0cc58edca 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_inclusive_or.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_inclusive_or.hpp
@@ -17,8 +17,8 @@ namespace lue {
 
     namespace default_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            logical_inclusive_or, detail::LogicalInclusiveOr, policy::logical_inclusive_or::DefaultPolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            logical_inclusive_or, policy::logical_inclusive_or::DefaultPolicies)
         LUE_BINARY_LOGICAL_OPERATOR(||, logical_inclusive_or)
 
     }  // namespace default_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_not.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_not.hpp
index efd41de3f..e83448089 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_not.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/logical_not.hpp
@@ -17,14 +17,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        PartitionedArray<std::uint8_t, rank> logical_not(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::logical_not::DefaultPolicies<std::uint8_t, Element>;
-
-            return logical_not(Policies{}, array);
-        }
-
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            logical_not, policy::logical_not::DefaultPolicies)
 
         LUE_UNARY_LOGICAL_OPERATOR(!, logical_not)
 
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/multiply.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/multiply.hpp
index 2fd114a90..0f7fec0d3 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/multiply.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/multiply.hpp
@@ -5,19 +5,19 @@
 namespace lue {
     namespace policy::multiply {
 
-        template<typename OutputElement, typename InputElement>
+        template<typename Element>
         using DefaultPolicies = policy::DefaultPolicies<
-            AllValuesWithinDomain<InputElement, InputElement>,
-            OutputElements<OutputElement>,
-            InputElements<InputElement, InputElement>>;
+            AllValuesWithinDomain<Element, Element>,
+            OutputElements<Element>,
+            InputElements<Element, Element>>;
 
     }  // namespace policy::multiply
 
 
     namespace default_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            multiply, detail::Multiply, policy::multiply::DefaultPolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            multiply, policy::multiply::DefaultPolicies)
         LUE_BINARY_ARITHMETIC_OPERATOR(*, multiply)
 
     }  // namespace default_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/negate.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/negate.hpp
index 6095b183b..4e312204f 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/negate.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/negate.hpp
@@ -15,13 +15,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        auto negate(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::negate::DefaultPolicies<Element>;
-
-            return negate(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            negate, policy::negate::DefaultPolicies)
 
         LUE_UNARY_LOGICAL_OPERATOR(-, negate)
 
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/not_equal_to.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/not_equal_to.hpp
index 9ab5dffe7..df2877694 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/not_equal_to.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/not_equal_to.hpp
@@ -16,8 +16,8 @@ namespace lue {
 
     namespace default_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            not_equal_to, detail::NotEqualTo, policy::not_equal_to::DefaultPolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            not_equal_to, policy::not_equal_to::DefaultPolicies)
         LUE_BINARY_COMPARISON_OPERATOR(!=, not_equal_to)
 
     }  // namespace default_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/pow.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/pow.hpp
new file mode 100644
index 000000000..c8d5d029d
--- /dev/null
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/pow.hpp
@@ -0,0 +1,22 @@
+#pragma once
+#include "lue/framework/algorithm/pow.hpp"
+
+
+namespace lue {
+    namespace policy::pow {
+
+        template<typename Element>
+        using DefaultPolicies = policy::
+            DefaultPolicies<DomainPolicy<Element>, OutputElements<Element>, InputElements<Element, Element>>;
+
+    }  // namespace policy::pow
+
+
+    namespace default_policies {
+
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            pow, policy::pow::DefaultPolicies)
+
+    }  // namespace default_policies
+
+}  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/round.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/round.hpp
index 352f7d0e1..80f6a1faa 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/round.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/round.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        auto round(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::round::DefaultPolicies<Element>;
-
-            return round(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            round, policy::round::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/sin.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/sin.hpp
index 3060731df..2e15c49f3 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/sin.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/sin.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        auto sin(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::sin::DefaultPolicies<Element>;
-
-            return sin(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            sin, policy::sin::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/sqrt.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/sqrt.hpp
index d8f7b7c6b..3edc273d4 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/sqrt.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/sqrt.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        auto sqrt(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::sqrt::DefaultPolicies<Element>;
-
-            return sqrt(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            sqrt, policy::sqrt::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/subtract.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/subtract.hpp
index 76975bfe5..8dd4727a6 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/subtract.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/subtract.hpp
@@ -5,19 +5,19 @@
 namespace lue {
     namespace policy::subtract {
 
-        template<typename OutputElement, typename InputElement>
+        template<typename Element>
         using DefaultPolicies = policy::DefaultPolicies<
-            AllValuesWithinDomain<InputElement, InputElement>,
-            OutputElements<OutputElement>,
-            InputElements<InputElement, InputElement>>;
+            AllValuesWithinDomain<Element, Element>,
+            OutputElements<Element>,
+            InputElements<Element, Element>>;
 
     }  // namespace policy::subtract
 
 
     namespace default_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            subtract, detail::Subtract, policy::subtract::DefaultPolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            subtract, policy::subtract::DefaultPolicies)
         LUE_BINARY_ARITHMETIC_OPERATOR(-, subtract)
 
     }  // namespace default_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/tan.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/tan.hpp
index acf0cc067..b2f2f9c3e 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/tan.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/tan.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename Element, Rank rank>
-        auto tan(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::tan::DefaultPolicies<Element>;
-
-            return tan(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            tan, policy::tan::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/valid.hpp b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/valid.hpp
index 222dd7dbf..bf4bf4ef8 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/default_policies/valid.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/default_policies/valid.hpp
@@ -18,23 +18,8 @@ namespace lue {
 
     namespace default_policies {
 
-        template<typename BooleanElement, typename ExpressionElement, Rank rank>
-        auto valid(PartitionedArray<ExpressionElement, rank> const& array)
-            -> PartitionedArray<BooleanElement, rank>
-        {
-            using Policies = policy::valid::DefaultPolicies<BooleanElement, ExpressionElement>;
-
-            return valid<BooleanElement>(Policies{}, array);
-        }
-
-
-        template<typename BooleanElement, typename ExpressionElement>
-        auto valid(Scalar<ExpressionElement> const& scalar) -> Scalar<BooleanElement>
-        {
-            using Policies = policy::valid::DefaultPolicies<BooleanElement, ExpressionElement>;
-
-            return valid<BooleanElement>(Policies{}, scalar);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            valid, policy::valid::DefaultPolicies)
 
     }  // namespace default_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/abs.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/abs.hpp
index e837e5624..94c58aae2 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/abs.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/abs.hpp
@@ -1,49 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/abs.hpp"
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
-#include "lue/macro.hpp"
-#include <cmath>
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class Abs
-        {
-
-            public:
-
-                static_assert(std::is_signed_v<InputElement> || std::is_floating_point_v<InputElement>);
-
-                using OutputElement = InputElement;
-
-                OutputElement operator()(InputElement const& input_element) const noexcept
-                {
-                    return std::abs(input_element);
-                }
-        };
-
-    }  // namespace detail
-
-
-    /*!
-        @brief      Return an array with the absolute value of each element in the array passed in
-        @ingroup    local_operation
-    */
-    template<typename Policies, typename Element, Rank rank>
-    auto abs(Policies const& policies, PartitionedArray<Element, rank> const& array)
-        -> PartitionedArray<Element, rank>
-    {
-        return unary_local_operation(policies, array, detail::Abs<Element>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_ABS(Policies, Element, rank)                                                         \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<Element, rank>                                      \
-    abs<ArgumentType<void(Policies)>, Element, rank>(                                                        \
-        ArgumentType<void(Policies)> const&, PartitionedArray<Element, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/acos.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/acos.hpp
index 60b961a3e..a2c19f581 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/acos.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/acos.hpp
@@ -1,46 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/acos.hpp"
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
-#include "lue/macro.hpp"
-#include <cmath>
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class ACos
-        {
-
-            public:
-
-                static_assert(std::is_floating_point_v<InputElement>);
-
-                using OutputElement = InputElement;
-
-
-                OutputElement operator()(InputElement const& input_element) const noexcept
-                {
-                    return std::acos(input_element);
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> acos(
-        Policies const& policies, PartitionedArray<Element, rank> const& array)
-    {
-        return unary_local_operation(policies, array, detail::ACos<Element>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_ACOS(Policies, Element, rank)                                                        \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<Element, rank>                                      \
-    acos<ArgumentType<void(Policies)>, Element, rank>(                                                       \
-        ArgumentType<void(Policies)> const&, PartitionedArray<Element, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/asin.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/asin.hpp
index 42487f86f..01de6ede6 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/asin.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/asin.hpp
@@ -1,46 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/asin.hpp"
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
-#include "lue/macro.hpp"
-#include <cmath>
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class ASin
-        {
-
-            public:
-
-                static_assert(std::is_floating_point_v<InputElement>);
-
-                using OutputElement = InputElement;
-
-
-                OutputElement operator()(InputElement const& input_element) const noexcept
-                {
-                    return std::asin(input_element);
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> asin(
-        Policies const& policies, PartitionedArray<Element, rank> const& array)
-    {
-        return unary_local_operation(policies, array, detail::ASin<Element>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_ASIN(Policies, Element, rank)                                                        \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<Element, rank>                                      \
-    asin<ArgumentType<void(Policies)>, Element, rank>(                                                       \
-        ArgumentType<void(Policies)> const&, PartitionedArray<Element, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/atan.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/atan.hpp
index 7f9619c8e..3e9a7c377 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/atan.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/atan.hpp
@@ -1,46 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/atan.hpp"
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
-#include "lue/macro.hpp"
-#include <cmath>
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class ATan
-        {
-
-            public:
-
-                static_assert(std::is_floating_point_v<InputElement>);
-
-                using OutputElement = InputElement;
-
-
-                OutputElement operator()(InputElement const& input_element) const noexcept
-                {
-                    return std::atan(input_element);
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> atan(
-        Policies const& policies, PartitionedArray<Element, rank> const& array)
-    {
-        return unary_local_operation(policies, array, detail::ATan<Element>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_ATAN(Policies, Element, rank)                                                        \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<Element, rank>                                      \
-    atan<ArgumentType<void(Policies)>, Element, rank>(                                                       \
-        ArgumentType<void(Policies)> const&, PartitionedArray<Element, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/binary_local_operation.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/binary_local_operation.hpp
index a688ead2e..c8d0ec426 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/binary_local_operation.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/binary_local_operation.hpp
@@ -42,11 +42,11 @@ namespace lue {
 
                 public:
 
-                    static OutputPartition binary_local_operation_partition_ready(
+                    static auto binary_local_operation_partition_ready(
                         Policies const& policies,
                         InputPartition1 const& input_partition1,
                         InputPartition2 const& input_partition2,
-                        Functor const& functor)
+                        Functor const& functor) -> OutputPartition
                     {
                         using Offset = OffsetT<InputPartition1>;
 
@@ -124,11 +124,11 @@ namespace lue {
                     }
 
 
-                    static OutputPartition binary_local_operation_partition(
+                    static auto binary_local_operation_partition(
                         Policies const& policies,
                         InputPartition1 const& input_partition1,
                         InputPartition2 const& input_partition2,
-                        Functor const& functor)
+                        Functor const& functor) -> OutputPartition
                     {
                         return hpx::dataflow(
                             hpx::launch::async,
@@ -174,11 +174,11 @@ namespace lue {
 
                 public:
 
-                    static OutputPartition binary_local_operation_partition_ready(
+                    static auto binary_local_operation_partition_ready(
                         Policies const& policies,
                         InputPartition const& input_partition,
                         InputElement const input_scalar,
-                        Functor const& functor)
+                        Functor const& functor) -> OutputPartition
                     {
                         using Offset = OffsetT<InputPartition>;
                         using InputData = DataT<InputPartition>;
@@ -255,11 +255,11 @@ namespace lue {
                     }
 
 
-                    static OutputPartition binary_local_operation_partition(
+                    static auto binary_local_operation_partition(
                         Policies const& policies,
                         InputPartition const& input_partition,
                         hpx::shared_future<InputElement> const& input_scalar,
-                        Functor const& functor)
+                        Functor const& functor) -> OutputPartition
                     {
                         return hpx::dataflow(
                             hpx::launch::async,
@@ -305,11 +305,11 @@ namespace lue {
 
                 public:
 
-                    static OutputPartition binary_local_operation_partition_ready(
+                    static auto binary_local_operation_partition_ready(
                         Policies const& policies,
                         InputElement const input_scalar,
                         InputPartition const& input_partition,
-                        Functor const& functor)
+                        Functor const& functor) -> OutputPartition
                     {
                         using Offset = OffsetT<InputPartition>;
                         using InputData = DataT<InputPartition>;
@@ -386,11 +386,11 @@ namespace lue {
                     }
 
 
-                    static OutputPartition binary_local_operation_partition(
+                    static auto binary_local_operation_partition(
                         Policies const& policies,
                         hpx::shared_future<InputElement> const& input_scalar,
                         InputPartition const& input_partition,
-                        Functor const& functor)
+                        Functor const& functor) -> OutputPartition
                     {
                         return hpx::dataflow(
                             hpx::launch::async,
@@ -427,16 +427,16 @@ namespace lue {
 
 
     // local_operation(partition, scalar)
-    template<typename Policies, typename InputElement1, typename InputElement2, Rank rank, typename Functor>
-    ArrayPartition<OutputElementT<Functor>, rank> binary_local_operation(
+    template<typename Policies, Rank rank, typename Functor>
+    auto binary_local_operation(
         hpx::id_type const locality_id,
         Policies const& policies,
-        ArrayPartition<InputElement1, rank> const& input_partition,
-        hpx::shared_future<InputElement2> const& input_scalar,
-        Functor const& functor)
+        ArrayPartition<policy::InputElementT<Policies, 0>, rank> const& input_partition,
+        hpx::shared_future<policy::InputElementT<Policies, 1>> const& input_scalar,
+        Functor const& functor) -> ArrayPartition<policy::OutputElementT<Policies, 0>, rank>
     {
-        using InputPartition = ArrayPartition<InputElement1, rank>;
-        using OutputPartition = ArrayPartition<OutputElementT<Functor>, rank>;
+        using InputPartition = ArrayPartition<policy::InputElementT<Policies, 0>, rank>;
+        using OutputPartition = ArrayPartition<policy::OutputElementT<Policies, 0>, rank>;
 
         lue_hpx_assert(input_partition.valid());
         lue_hpx_assert(input_scalar.valid());
@@ -444,7 +444,7 @@ namespace lue {
         detail::BinaryLocalOperationPartitionAction<
             Policies,
             InputPartition,
-            InputElement2,
+            policy::InputElementT<Policies, 1>,
             OutputPartition,
             Functor>
             action;
@@ -460,22 +460,22 @@ namespace lue {
 
 
     // local_operation(array, array)
-    template<typename Policies, typename InputElement1, typename InputElement2, Rank rank, typename Functor>
-    PartitionedArray<OutputElementT<Functor>, rank> binary_local_operation(
+    template<typename Policies, Rank rank, typename Functor>
+    auto binary_local_operation(
         Policies const& policies,
-        PartitionedArray<InputElement1, rank> const& input_array1,
-        PartitionedArray<InputElement2, rank> const& input_array2,
-        Functor const& functor)
+        PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& input_array1,
+        PartitionedArray<policy::InputElementT<Policies, 1>, rank> const& input_array2,
+        Functor const& functor) -> PartitionedArray<policy::OutputElementT<Policies, 0>, rank>
     {
-        using InputArray1 = PartitionedArray<InputElement1, rank>;
+        using InputArray1 = PartitionedArray<policy::InputElementT<Policies, 0>, rank>;
         using InputPartitions1 = PartitionsT<InputArray1>;
         using InputPartition1 = PartitionT<InputArray1>;
 
-        using InputArray2 = PartitionedArray<InputElement2, rank>;
+        using InputArray2 = PartitionedArray<policy::InputElementT<Policies, 1>, rank>;
         using InputPartitions2 = PartitionsT<InputArray2>;
         using InputPartition2 = PartitionT<InputArray2>;
 
-        using OutputElement = OutputElementT<Functor>;
+        using OutputElement = policy::OutputElementT<Policies, 0>;
         using OutputArray = PartitionedArray<OutputElement, rank>;
         using OutputPartitions = PartitionsT<OutputArray>;
         using OutputPartition = PartitionT<OutputArray>;
@@ -520,18 +520,18 @@ namespace lue {
 
 
     // local_operation(array, scalar)
-    template<typename Policies, typename InputElement1, typename InputElement2, Rank rank, typename Functor>
-    PartitionedArray<OutputElementT<Functor>, rank> binary_local_operation(
+    template<typename Policies, Rank rank, typename Functor>
+    auto binary_local_operation(
         Policies const& policies,
-        PartitionedArray<InputElement1, rank> const& input_array,
-        hpx::shared_future<InputElement2> const& input_scalar,
-        Functor const& functor)
+        PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& input_array,
+        hpx::shared_future<policy::InputElementT<Policies, 1>> const& input_scalar,
+        Functor const& functor) -> PartitionedArray<policy::OutputElementT<Policies, 0>, rank>
     {
-        using InputArray = PartitionedArray<InputElement1, rank>;
+        using InputArray = PartitionedArray<policy::InputElementT<Policies, 0>, rank>;
         using InputPartitions = PartitionsT<InputArray>;
         using InputPartition = PartitionT<InputArray>;
 
-        using OutputArray = PartitionedArray<OutputElementT<Functor>, rank>;
+        using OutputArray = PartitionedArray<policy::OutputElementT<Policies, 0>, rank>;
         using OutputPartitions = PartitionsT<OutputArray>;
         using OutputPartition = PartitionT<OutputArray>;
 
@@ -543,7 +543,7 @@ namespace lue {
         detail::BinaryLocalOperationPartitionAction<
             Policies,
             InputPartition,
-            InputElement2,
+            policy::InputElementT<Policies, 1>,
             OutputPartition,
             Functor>
             action;
@@ -572,18 +572,18 @@ namespace lue {
 
 
     // local_operation(scalar, array)
-    template<typename Policies, typename InputElement1, typename InputElement2, Rank rank, typename Functor>
-    PartitionedArray<OutputElementT<Functor>, rank> binary_local_operation(
+    template<typename Policies, Rank rank, typename Functor>
+    auto binary_local_operation(
         Policies const& policies,
-        hpx::shared_future<InputElement1> const& input_scalar,
-        PartitionedArray<InputElement2, rank> const& input_array,
-        Functor const& functor)
+        hpx::shared_future<policy::InputElementT<Policies, 0>> const& input_scalar,
+        PartitionedArray<policy::InputElementT<Policies, 1>, rank> const& input_array,
+        Functor const& functor) -> PartitionedArray<policy::OutputElementT<Policies, 0>, rank>
     {
-        using InputArray = PartitionedArray<InputElement2, rank>;
+        using InputArray = PartitionedArray<policy::InputElementT<Policies, 1>, rank>;
         using InputPartitions = PartitionsT<InputArray>;
         using InputPartition = PartitionT<InputArray>;
 
-        using OutputArray = PartitionedArray<OutputElementT<Functor>, rank>;
+        using OutputArray = PartitionedArray<policy::OutputElementT<Policies, 0>, rank>;
         using OutputPartitions = PartitionsT<OutputArray>;
         using OutputPartition = PartitionT<OutputArray>;
 
@@ -594,7 +594,7 @@ namespace lue {
 
         detail::BinaryLocalOperationPartitionAction<
             Policies,
-            InputElement1,
+            policy::InputElementT<Policies, 0>,
             InputPartition,
             OutputPartition,
             Functor>
@@ -624,14 +624,14 @@ namespace lue {
 
 
     // local_operation(scalar, scalar)
-    template<typename Policies, typename InputElement1, typename InputElement2, typename Functor>
+    template<typename Policies, typename Functor>
     auto binary_local_operation(
         Policies const& policies,
-        hpx::shared_future<InputElement1> const& input_scalar1,
-        hpx::shared_future<InputElement2> const& input_scalar2,
-        Functor const& functor) -> hpx::future<OutputElementT<Functor>>
+        hpx::shared_future<policy::InputElementT<Policies, 0>> const& input_scalar1,
+        hpx::shared_future<policy::InputElementT<Policies, 1>> const& input_scalar2,
+        Functor const& functor) -> hpx::future<policy::OutputElementT<Policies, 0>>
     {
-        using OutputElement = OutputElementT<Functor>;
+        using OutputElement = policy::OutputElementT<Policies, 0>;
 
         return hpx::dataflow(
             hpx::launch::async,
@@ -670,64 +670,47 @@ namespace lue {
 }  // namespace lue
 
 
-#define LUE_INSTANTIATE_BINARY_LOCAL_OPERATION_PARTITION(                                                    \
-    Policies, OutputElement, InputElement1, InputElement2, rank, Functor)                                    \
+#define LUE_INSTANTIATE_BINARY_LOCAL_OPERATION_PARTITION(Policies, rank, Functor)                            \
                                                                                                              \
-    template LUE_LOCAL_OPERATION_EXPORT ArrayPartition<OutputElement, rank> binary_local_operation<          \
-        ArgumentType<void(Policies)>,                                                                        \
-        InputElement1,                                                                                       \
-        InputElement2,                                                                                       \
-        rank,                                                                                                \
-        ArgumentType<void(Functor)>>(                                                                        \
+    template LUE_LOCAL_OPERATION_EXPORT auto                                                                 \
+    binary_local_operation<ArgumentType<void(Policies)>, rank, ArgumentType<void(Functor)>>(                 \
         hpx::id_type const locality_id,                                                                      \
         ArgumentType<void(Policies)> const&,                                                                 \
-        ArrayPartition<InputElement1, rank> const&,                                                          \
-        hpx::shared_future<InputElement2> const& input_scalar,                                               \
-        ArgumentType<void(Functor)> const&);
+        ArrayPartition<policy::InputElementT<ArgumentType<void(Policies)>, 0>, rank> const&,                 \
+        hpx::shared_future<policy::InputElementT<ArgumentType<void(Policies)>, 1>> const& input_scalar,      \
+        ArgumentType<void(Functor)> const&)                                                                  \
+        ->ArrayPartition<policy::OutputElementT<ArgumentType<void(Policies)>, 0>, rank>;
 
-#define LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(                                                              \
-    Policies, OutputElement, InputElement1, InputElement2, rank, Functor)                                    \
+#define LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(Policies, rank, Functor)                                      \
                                                                                                              \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<OutputElement, rank> binary_local_operation<        \
-        ArgumentType<void(Policies)>,                                                                        \
-        InputElement1,                                                                                       \
-        InputElement2,                                                                                       \
-        rank,                                                                                                \
-        ArgumentType<void(Functor)>>(                                                                        \
+    template LUE_LOCAL_OPERATION_EXPORT auto                                                                 \
+    binary_local_operation<ArgumentType<void(Policies)>, rank, ArgumentType<void(Functor)>>(                 \
         ArgumentType<void(Policies)> const&,                                                                 \
-        hpx::shared_future<InputElement1> const&,                                                            \
-        PartitionedArray<InputElement2, rank> const&,                                                        \
-        ArgumentType<void(Functor)> const&);                                                                 \
+        hpx::shared_future<policy::InputElementT<ArgumentType<void(Policies)>, 0>> const&,                   \
+        PartitionedArray<policy::InputElementT<ArgumentType<void(Policies)>, 1>, rank> const&,               \
+        ArgumentType<void(Functor)> const&)                                                                  \
+        ->PartitionedArray<policy::OutputElementT<ArgumentType<void(Policies)>, 0>, rank>;                   \
                                                                                                              \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<OutputElement, rank> binary_local_operation<        \
-        ArgumentType<void(Policies)>,                                                                        \
-        InputElement1,                                                                                       \
-        InputElement2,                                                                                       \
-        rank,                                                                                                \
-        ArgumentType<void(Functor)>>(                                                                        \
+    template LUE_LOCAL_OPERATION_EXPORT auto                                                                 \
+    binary_local_operation<ArgumentType<void(Policies)>, rank, ArgumentType<void(Functor)>>(                 \
         ArgumentType<void(Policies)> const&,                                                                 \
-        PartitionedArray<InputElement1, rank> const&,                                                        \
-        hpx::shared_future<InputElement2> const&,                                                            \
-        ArgumentType<void(Functor)> const&);                                                                 \
+        PartitionedArray<policy::InputElementT<ArgumentType<void(Policies)>, 0>, rank> const&,               \
+        hpx::shared_future<policy::InputElementT<ArgumentType<void(Policies)>, 1>> const&,                   \
+        ArgumentType<void(Functor)> const&)                                                                  \
+        ->PartitionedArray<policy::OutputElementT<ArgumentType<void(Policies)>, 0>, rank>;                   \
                                                                                                              \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<OutputElement, rank> binary_local_operation<        \
-        ArgumentType<void(Policies)>,                                                                        \
-        InputElement1,                                                                                       \
-        InputElement2,                                                                                       \
-        rank,                                                                                                \
-        ArgumentType<void(Functor)>>(                                                                        \
+    template LUE_LOCAL_OPERATION_EXPORT auto                                                                 \
+    binary_local_operation<ArgumentType<void(Policies)>, rank, ArgumentType<void(Functor)>>(                 \
         ArgumentType<void(Policies)> const&,                                                                 \
-        PartitionedArray<InputElement1, rank> const&,                                                        \
-        PartitionedArray<InputElement2, rank> const&,                                                        \
-        ArgumentType<void(Functor)> const&);                                                                 \
+        PartitionedArray<policy::InputElementT<ArgumentType<void(Policies)>, 0>, rank> const&,               \
+        PartitionedArray<policy::InputElementT<ArgumentType<void(Policies)>, 1>, rank> const&,               \
+        ArgumentType<void(Functor)> const&)                                                                  \
+        ->PartitionedArray<policy::OutputElementT<ArgumentType<void(Policies)>, 0>, rank>;                   \
                                                                                                              \
-    template LUE_LOCAL_OPERATION_EXPORT auto binary_local_operation<                                         \
-        ArgumentType<void(Policies)>,                                                                        \
-        InputElement1,                                                                                       \
-        InputElement2,                                                                                       \
-        ArgumentType<void(Functor)>>(                                                                        \
+    template LUE_LOCAL_OPERATION_EXPORT auto                                                                 \
+    binary_local_operation<ArgumentType<void(Policies)>, ArgumentType<void(Functor)>>(                       \
         ArgumentType<void(Policies)> const&,                                                                 \
-        hpx::shared_future<InputElement1> const&,                                                            \
-        hpx::shared_future<InputElement2> const&,                                                            \
+        hpx::shared_future<policy::InputElementT<ArgumentType<void(Policies)>, 0>> const&,                   \
+        hpx::shared_future<policy::InputElementT<ArgumentType<void(Policies)>, 1>> const&,                   \
         ArgumentType<void(Functor)> const&)                                                                  \
-        ->hpx::future<OutputElement>;
+        ->hpx::future<policy::OutputElementT<ArgumentType<void(Policies)>, 0>>;
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/cast.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/cast.hpp
index d224e9ac0..c9497000d 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/cast.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/cast.hpp
@@ -1,47 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/cast.hpp"
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
-#include "lue/macro.hpp"
-#include <type_traits>
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement, typename OutputElement_>
-        class Cast
-        {
-
-            public:
-
-                using OutputElement = OutputElement_;
-
-                static_assert(std::is_arithmetic_v<InputElement>);
-                static_assert(std::is_arithmetic_v<OutputElement>);
-
-
-                constexpr auto operator()(InputElement const& input_element) const noexcept -> OutputElement
-                {
-                    return static_cast<OutputElement>(input_element);
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename OutputElement, typename Policies, typename InputElement, Rank rank>
-    auto cast(Policies const& policies, PartitionedArray<InputElement, rank> const& array)
-        -> PartitionedArray<OutputElement, rank>
-    {
-        return unary_local_operation(policies, array, detail::Cast<InputElement, OutputElement>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_CAST(Policies, OutputElement, InputElement, rank)                                    \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<OutputElement, rank>                                \
-    cast<OutputElement, ArgumentType<void(Policies)>, InputElement, rank>(                                   \
-        ArgumentType<void(Policies)> const&, PartitionedArray<InputElement, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/ceil.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/ceil.hpp
index cd2530522..6bb322389 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/ceil.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/ceil.hpp
@@ -1,46 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/ceil.hpp"
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
-#include "lue/macro.hpp"
-#include <cmath>
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class Ceil
-        {
-
-            public:
-
-                static_assert(std::is_floating_point_v<InputElement>);
-
-                using OutputElement = InputElement;
-
-
-                OutputElement operator()(InputElement const& input_element) const noexcept
-                {
-                    return std::ceil(input_element);
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> ceil(
-        Policies const& policies, PartitionedArray<Element, rank> const& array)
-    {
-        return unary_local_operation(policies, array, detail::Ceil<Element>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_CEIL(Policies, Element, rank)                                                        \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<Element, rank>                                      \
-    ceil<ArgumentType<void(Policies)>, Element, rank>(                                                       \
-        ArgumentType<void(Policies)> const&, PartitionedArray<Element, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/cos.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/cos.hpp
index a77754abd..9d72260e1 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/cos.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/cos.hpp
@@ -1,46 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/cos.hpp"
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
-#include "lue/macro.hpp"
-#include <cmath>
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class Cos
-        {
-
-            public:
-
-                static_assert(std::is_floating_point_v<InputElement>);
-
-                using OutputElement = InputElement;
-
-
-                OutputElement operator()(InputElement const& input_element) const noexcept
-                {
-                    return std::cos(input_element);
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> cos(
-        Policies const& policies, PartitionedArray<Element, rank> const& array)
-    {
-        return unary_local_operation(policies, array, detail::Cos<Element>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_COS(Policies, Element, rank)                                                         \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<Element, rank>                                      \
-    cos<ArgumentType<void(Policies)>, Element, rank>(                                                        \
-        ArgumentType<void(Policies)> const&, PartitionedArray<Element, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/exp.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/exp.hpp
index 3c7140921..35462d107 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/exp.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/exp.hpp
@@ -1,45 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
 #include "lue/framework/algorithm/exp.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
-#include "lue/macro.hpp"
-#include <cmath>
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class Exp
-        {
-
-            public:
-
-                static_assert(std::is_floating_point_v<InputElement>);
-
-                using OutputElement = InputElement;
-
-                OutputElement operator()(InputElement const& input_element) const noexcept
-                {
-                    return std::exp(input_element);
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> exp(
-        Policies const& policies, PartitionedArray<Element, rank> const& array)
-    {
-        return unary_local_operation(policies, array, detail::Exp<Element>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_EXP(Policies, Element, rank)                                                         \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<Element, rank>                                      \
-    exp<ArgumentType<void(Policies)>, Element, rank>(                                                        \
-        ArgumentType<void(Policies)> const&, PartitionedArray<Element, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/floor.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/floor.hpp
index 4e9eca132..624eadf04 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/floor.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/floor.hpp
@@ -1,46 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
 #include "lue/framework/algorithm/floor.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
-#include "lue/macro.hpp"
-#include <cmath>
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class Floor
-        {
-
-            public:
-
-                static_assert(std::is_floating_point_v<InputElement>);
-
-                using OutputElement = InputElement;
-
-
-                OutputElement operator()(InputElement const& input_element) const noexcept
-                {
-                    return std::floor(input_element);
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> floor(
-        Policies const& policies, PartitionedArray<Element, rank> const& array)
-    {
-        return unary_local_operation(policies, array, detail::Floor<Element>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_FLOOR(Policies, Element, rank)                                                       \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<Element, rank>                                      \
-    floor<ArgumentType<void(Policies)>, Element, rank>(                                                      \
-        ArgumentType<void(Policies)> const&, PartitionedArray<Element, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/log.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/log.hpp
index 8307b10fe..58360617b 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/log.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/log.hpp
@@ -1,46 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
 #include "lue/framework/algorithm/log.hpp"
-#include "lue/macro.hpp"
-#include <cmath>
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class Log
-        {
-
-            public:
-
-                static_assert(std::is_floating_point_v<InputElement>);
-
-                using OutputElement = InputElement;
-
-
-                OutputElement operator()(InputElement const& input_element) const noexcept
-                {
-                    return std::log(input_element);
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> log(
-        Policies const& policies, PartitionedArray<Element, rank> const& array)
-    {
-        return unary_local_operation(policies, array, detail::Log<Element>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_LOG(Policies, Element, rank)                                                         \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<Element, rank>                                      \
-    log<ArgumentType<void(Policies)>, Element, rank>(                                                        \
-        ArgumentType<void(Policies)> const&, PartitionedArray<Element, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/log10.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/log10.hpp
index 588f5be57..f11d2313d 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/log10.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/log10.hpp
@@ -1,46 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
 #include "lue/framework/algorithm/log10.hpp"
-#include "lue/macro.hpp"
-#include <cmath>
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class Log10
-        {
-
-            public:
-
-                static_assert(std::is_floating_point_v<InputElement>);
-
-                using OutputElement = InputElement;
-
-
-                OutputElement operator()(InputElement const& input_element) const noexcept
-                {
-                    return std::log10(input_element);
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> log10(
-        Policies const& policies, PartitionedArray<Element, rank> const& array)
-    {
-        return unary_local_operation(policies, array, detail::Log10<Element>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_LOG10(Policies, Element, rank)                                                       \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<Element, rank>                                      \
-    log10<ArgumentType<void(Policies)>, Element, rank>(                                                      \
-        ArgumentType<void(Policies)> const&, PartitionedArray<Element, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/logical_not.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/logical_not.hpp
index cfee52808..f63e851b0 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/logical_not.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/logical_not.hpp
@@ -1,45 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
 #include "lue/framework/algorithm/logical_not.hpp"
-#include "lue/macro.hpp"
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class LogicalNot
-        {
-
-            public:
-
-                static_assert(std::is_integral_v<InputElement>);
-
-                using OutputElement = std::uint8_t;
-
-
-                constexpr OutputElement operator()(InputElement const& input_element) const noexcept
-                {
-                    return !input_element;
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename Policies, typename InputElement, Rank rank>
-    PartitionedArray<std::uint8_t, rank> logical_not(
-        Policies const& policies, PartitionedArray<InputElement, rank> const& array)
-    {
-        return unary_local_operation(policies, array, detail::LogicalNot<InputElement>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_LOGICAL_NOT(Policies, Element, rank)                                                 \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<std::uint8_t, rank>                                 \
-    logical_not<ArgumentType<void(Policies)>, Element, rank>(                                                \
-        ArgumentType<void(Policies)> const&, PartitionedArray<Element, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/negate.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/negate.hpp
index 17355bed3..fd2493426 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/negate.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/negate.hpp
@@ -1,46 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
 #include "lue/framework/algorithm/negate.hpp"
-#include "lue/macro.hpp"
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class Negate
-        {
-
-            public:
-
-                static_assert(std::is_signed_v<InputElement> || std::is_floating_point_v<InputElement>);
-
-                using OutputElement = InputElement;
-
-                auto operator()(InputElement const& input_element) const noexcept -> OutputElement
-                {
-                    return -input_element;
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename Policies, Rank rank>
-    auto negate(
-        Policies const& policies, PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& array)
-        -> PartitionedArray<policy::OutputElementT<Policies, 0>, rank>
-    {
-        return unary_local_operation(policies, array, detail::Negate<policy::InputElementT<Policies, 0>>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_NEGATE(Policies, rank)                                                               \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<policy::OutputElementT<Policies, 0>, rank>          \
-    negate<ArgumentType<void(Policies)>, rank>(                                                              \
-        ArgumentType<void(Policies)> const&,                                                                 \
-        PartitionedArray<policy::InputElementT<Policies, 0>, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/round.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/round.hpp
index f5035a00b..4238c583f 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/round.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/round.hpp
@@ -1,46 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
 #include "lue/framework/algorithm/round.hpp"
-#include "lue/macro.hpp"
-#include <cmath>
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class Round
-        {
-
-            public:
-
-                static_assert(std::is_floating_point_v<InputElement>);
-
-                using OutputElement = InputElement;
-
-
-                OutputElement operator()(InputElement const& input_element) const noexcept
-                {
-                    return std::round(input_element);
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> round(
-        Policies const& policies, PartitionedArray<Element, rank> const& array)
-    {
-        return unary_local_operation(policies, array, detail::Round<Element>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_ROUND(Policies, Element, rank)                                                       \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<Element, rank>                                      \
-    round<ArgumentType<void(Policies)>, Element, rank>(                                                      \
-        ArgumentType<void(Policies)> const&, PartitionedArray<Element, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/sin.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/sin.hpp
index a2dc1bd87..728349bdd 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/sin.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/sin.hpp
@@ -1,46 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
 #include "lue/framework/algorithm/sin.hpp"
-#include "lue/macro.hpp"
-#include <cmath>
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class Sin
-        {
-
-            public:
-
-                static_assert(std::is_floating_point_v<InputElement>);
-
-                using OutputElement = InputElement;
-
-
-                OutputElement operator()(InputElement const& input_element) const noexcept
-                {
-                    return std::sin(input_element);
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> sin(
-        Policies const& policies, PartitionedArray<Element, rank> const& array)
-    {
-        return unary_local_operation(policies, array, detail::Sin<Element>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_SIN(Policies, Element, rank)                                                         \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<Element, rank>                                      \
-    sin<ArgumentType<void(Policies)>, Element, rank>(                                                        \
-        ArgumentType<void(Policies)> const&, PartitionedArray<Element, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/sqrt.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/sqrt.hpp
index 5b05ddbf6..9b1f1b12a 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/sqrt.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/sqrt.hpp
@@ -1,45 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
 #include "lue/framework/algorithm/sqrt.hpp"
-#include "lue/macro.hpp"
-#include <cmath>
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class Sqrt
-        {
-
-            public:
-
-                static_assert(std::is_floating_point_v<InputElement>);
-
-                using OutputElement = InputElement;
-
-                OutputElement operator()(InputElement const& input_element) const noexcept
-                {
-                    return std::sqrt(input_element);
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> sqrt(
-        Policies const& policies, PartitionedArray<Element, rank> const& array)
-    {
-        return unary_local_operation(policies, array, detail::Sqrt<Element>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_SQRT(Policies, Element, rank)                                                        \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<Element, rank>                                      \
-    sqrt<ArgumentType<void(Policies)>, Element, rank>(                                                       \
-        ArgumentType<void(Policies)> const&, PartitionedArray<Element, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/tan.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/tan.hpp
index 4c090b3ad..e80ee7905 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/tan.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/tan.hpp
@@ -1,46 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
 #include "lue/framework/algorithm/tan.hpp"
-#include "lue/macro.hpp"
-#include <cmath>
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement>
-        class Tan
-        {
-
-            public:
-
-                static_assert(std::is_floating_point_v<InputElement>);
-
-                using OutputElement = InputElement;
-
-
-                OutputElement operator()(InputElement const& input_element) const noexcept
-                {
-                    return std::tan(input_element);
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> tan(
-        Policies const& policies, PartitionedArray<Element, rank> const& array)
-    {
-        return unary_local_operation(policies, array, detail::Tan<Element>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_TAN(Policies, Element, rank)                                                         \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT PartitionedArray<Element, rank>                                      \
-    tan<ArgumentType<void(Policies)>, Element, rank>(                                                        \
-        ArgumentType<void(Policies)> const&, PartitionedArray<Element, rank> const&);
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/unary_local_operation.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/unary_local_operation.hpp
index 7ac25f76b..0fc91bf58 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/unary_local_operation.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/unary_local_operation.hpp
@@ -1,17 +1,18 @@
 #pragma once
-#include "lue/framework/algorithm/functor_traits.hpp"
-#include "lue/framework/algorithm/scalar.hpp"
+#include "lue/framework/algorithm/local_operation_export.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
 #include "lue/framework/core/annotate.hpp"
 #include "lue/framework/core/component.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/macro.hpp"
 
 
 namespace lue {
     namespace detail {
 
         template<typename Policies, typename InputPartition, typename OutputPartition, typename Functor>
-        OutputPartition unary_local_operation_partition(
+        auto unary_local_operation_partition(
             Policies const& policies, InputPartition const& input_partition, Functor const& functor)
+            -> OutputPartition
         {
             using Offset = OffsetT<InputPartition>;
             using InputData = DataT<InputPartition>;
@@ -39,23 +40,26 @@ namespace lue {
 
                         Count const nr_elements{lue::nr_elements(input_partition_data)};
 
-                        for (Index i = 0; i < nr_elements; ++i)
+                        for (Index element_idx = 0; element_idx < nr_elements; ++element_idx)
                         {
-                            if (indp.is_no_data(input_partition_data, i))
+                            if (indp.is_no_data(input_partition_data, element_idx))
                             {
-                                ondp.mark_no_data(output_partition_data, i);
+                                ondp.mark_no_data(output_partition_data, element_idx);
                             }
-                            else if (!dp.within_domain(input_partition_data[i]))
+                            else if (!dp.within_domain(input_partition_data[element_idx]))
                             {
-                                ondp.mark_no_data(output_partition_data, i);
+                                ondp.mark_no_data(output_partition_data, element_idx);
                             }
                             else
                             {
-                                output_partition_data[i] = functor(input_partition_data[i]);
+                                output_partition_data[element_idx] =
+                                    functor(input_partition_data[element_idx]);
 
-                                if (!rp.within_range(input_partition_data[i], output_partition_data[i]))
+                                if (!rp.within_range(
+                                        input_partition_data[element_idx],
+                                        output_partition_data[element_idx]))
                                 {
-                                    ondp.mark_no_data(output_partition_data, i);
+                                    ondp.mark_no_data(output_partition_data, element_idx);
                                 }
                             }
                         }
@@ -85,17 +89,21 @@ namespace lue {
     }  // namespace detail
 
 
-    template<typename Policies, typename InputElement, Rank rank, typename Functor>
-    PartitionedArray<OutputElementT<Functor>, rank> unary_local_operation(
+    // unary_local_operation(array)
+    template<typename Policies, Rank rank, typename Functor>
+    auto unary_local_operation(
         Policies const& policies,
-        PartitionedArray<InputElement, rank> const& input_array,
-        Functor const& functor)
+        PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& input_array,
+        Functor const& functor) -> PartitionedArray<policy::OutputElementT<Policies, 0>, rank>
     {
+        using InputElement = policy::InputElementT<Policies, 0>;
+        using OutputElement = policy::OutputElementT<Policies, 0>;
+
         using InputArray = PartitionedArray<InputElement, rank>;
         using InputPartitions = PartitionsT<InputArray>;
         using InputPartition = PartitionT<InputArray>;
 
-        using OutputArray = PartitionedArray<OutputElementT<Functor>, rank>;
+        using OutputArray = PartitionedArray<OutputElement, rank>;
         using OutputPartitions = PartitionsT<OutputArray>;
         using OutputPartition = PartitionT<OutputArray>;
 
@@ -107,12 +115,12 @@ namespace lue {
         InputPartitions const& input_partitions{input_array.partitions()};
         OutputPartitions output_partitions{shape_in_partitions(input_array)};
 
-        for (Index p = 0; p < nr_partitions(input_array); ++p)
+        for (Index partition_idx = 0; partition_idx < nr_partitions(input_array); ++partition_idx)
         {
-            output_partitions[p] = hpx::dataflow(
+            output_partitions[partition_idx] = hpx::dataflow(
                 hpx::launch::async,
 
-                [locality_id = localities[p], action, policies, functor](
+                [locality_id = localities[partition_idx], action, policies, functor](
                     InputPartition const& input_partition)
                 {
                     AnnotateFunction annotation{"unary_local_operation"};
@@ -120,19 +128,21 @@ namespace lue {
                     return action(locality_id, policies, input_partition, functor);
                 },
 
-                input_partitions[p]);
+                input_partitions[partition_idx]);
         }
 
         return OutputArray{shape(input_array), localities, std::move(output_partitions)};
     }
 
 
-    template<typename Policies, typename InputElement, typename Functor>
+    // unary_local_operation(scalar)
+    template<typename Policies, typename Functor>
     auto unary_local_operation(
-        Policies const& policies, Scalar<InputElement> const& input_scalar, Functor const& functor)
-        -> Scalar<OutputElementT<Functor>>
+        Policies const& policies,
+        Scalar<policy::InputElementT<Policies, 0>> const& input_scalar,
+        Functor const& functor) -> Scalar<policy::OutputElementT<Policies, 0>>
     {
-        using OutputElement = OutputElementT<Functor>;
+        using OutputElement = policy::OutputElementT<Policies, 0>;
 
         return hpx::dataflow(
             hpx::launch::async,
@@ -166,3 +176,20 @@ namespace lue {
     }
 
 }  // namespace lue
+
+
+#define LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(Policies, rank, Functor)                                       \
+                                                                                                             \
+    template LUE_LOCAL_OPERATION_EXPORT auto                                                                 \
+    unary_local_operation<ArgumentType<void(Policies)>, rank, ArgumentType<void(Functor)>>(                  \
+        ArgumentType<void(Policies)> const&,                                                                 \
+        PartitionedArray<policy::InputElementT<ArgumentType<void(Policies)>>, rank> const&,                  \
+        ArgumentType<void(Functor)> const&)                                                                  \
+        ->PartitionedArray<policy::OutputElementT<ArgumentType<void(Policies)>>, rank>;                      \
+                                                                                                             \
+    template LUE_LOCAL_OPERATION_EXPORT auto                                                                 \
+    unary_local_operation<ArgumentType<void(Policies)>, ArgumentType<void(Functor)>>(                        \
+        ArgumentType<void(Policies)> const&,                                                                 \
+        Scalar<policy::InputElementT<ArgumentType<void(Policies)>>> const&,                                  \
+        ArgumentType<void(Functor)> const&)                                                                  \
+        ->Scalar<policy::OutputElementT<ArgumentType<void(Policies)>>>;
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/definition/valid.hpp b/source/framework/algorithm/include/lue/framework/algorithm/definition/valid.hpp
index c9841a2db..c6586d757 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/definition/valid.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/definition/valid.hpp
@@ -1,57 +1,3 @@
 #pragma once
 #include "lue/framework/algorithm/definition/unary_local_operation.hpp"
-#include "lue/framework/algorithm/local_operation_export.hpp"
 #include "lue/framework/algorithm/valid.hpp"
-#include "lue/macro.hpp"
-
-
-namespace lue {
-    namespace detail {
-
-        template<typename InputElement, typename OutputElement_ = std::uint8_t>
-        class Valid
-        {
-
-            public:
-
-                using OutputElement = OutputElement_;
-
-
-                constexpr auto operator()([[maybe_unused]] InputElement const& input_element) const noexcept
-                    -> OutputElement
-                {
-                    return 1;
-                }
-        };
-
-    }  // namespace detail
-
-
-    template<typename BooleanElement, typename Policies, typename ExpressionElement, Rank rank>
-    auto valid(Policies const& policies, PartitionedArray<ExpressionElement, rank> const& array)
-        -> PartitionedArray<BooleanElement, rank>
-    {
-        return unary_local_operation(policies, array, detail::Valid<ExpressionElement>{});
-    }
-
-
-    template<typename BooleanElement, typename Policies, typename ExpressionElement>
-    auto valid(Policies const& policies, Scalar<ExpressionElement> const& scalar) -> Scalar<BooleanElement>
-    {
-        return unary_local_operation(policies, scalar, detail::Valid<ExpressionElement>{});
-    }
-
-}  // namespace lue
-
-
-#define LUE_INSTANTIATE_VALID(Policies, BooleanElement, ExpressionElement, rank)                             \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT auto                                                                 \
-    valid<BooleanElement, ArgumentType<void(Policies)>, ExpressionElement, rank>(                            \
-        ArgumentType<void(Policies)> const&, PartitionedArray<ExpressionElement, rank> const&)               \
-        ->PartitionedArray<BooleanElement, rank>;                                                            \
-                                                                                                             \
-    template LUE_LOCAL_OPERATION_EXPORT auto                                                                 \
-    valid<BooleanElement, ArgumentType<void(Policies)>, ExpressionElement>(                                  \
-        ArgumentType<void(Policies)> const&, Scalar<ExpressionElement> const&)                               \
-        ->Scalar<BooleanElement>;
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/divide.hpp b/source/framework/algorithm/include/lue/framework/algorithm/divide.hpp
index a41f64fb4..30cfd5734 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/divide.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/divide.hpp
@@ -18,8 +18,9 @@ namespace lue {
                 using OutputElement = OutputElement_;
 
 
-                constexpr OutputElement operator()(
+                constexpr auto operator()(
                     InputElement const& input_element1, InputElement const& input_element2) const noexcept
+                    -> OutputElement
                 {
                     return input_element1 / input_element2;
                 }
@@ -36,8 +37,8 @@ namespace lue {
 
             public:
 
-                static constexpr bool within_domain(
-                    [[maybe_unused]] Element const numerator, Element const denominator) noexcept
+                static constexpr auto within_domain(
+                    [[maybe_unused]] Element const numerator, Element const denominator) noexcept -> bool
                 {
                     return denominator != 0;
                 }
@@ -46,6 +47,6 @@ namespace lue {
     }  // namespace policy::divide
 
 
-    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(divide, detail::Divide)
+    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(divide, detail::Divide)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/equal_to.hpp b/source/framework/algorithm/include/lue/framework/algorithm/equal_to.hpp
index 86a5b7bca..2c92f4ba5 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/equal_to.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/equal_to.hpp
@@ -15,8 +15,9 @@ namespace lue {
 
                 using OutputElement = OutputElement_;
 
-                constexpr OutputElement operator()(
+                constexpr auto operator()(
                     InputElement const& input_element1, InputElement const& input_element2) const noexcept
+                    -> OutputElement
                 {
                     return input_element1 == input_element2;
                 }
@@ -25,6 +26,6 @@ namespace lue {
     }  // namespace detail
 
 
-    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(equal_to, detail::EqualTo)
+    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_DIFFERENT_OUTPUT_ELEMENT(equal_to, detail::EqualTo)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/exp.hpp b/source/framework/algorithm/include/lue/framework/algorithm/exp.hpp
index 7ca8185e3..1eecb2ea9 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/exp.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/exp.hpp
@@ -1,12 +1,31 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
+#include <cmath>
 
 
 namespace lue {
+    namespace detail {
 
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> exp(
-        Policies const& policies, PartitionedArray<Element, rank> const& array);
+        template<typename InputElement>
+        class Exp
+        {
+
+            public:
+
+                static_assert(std::is_floating_point_v<InputElement>);
+
+                using OutputElement = InputElement;
+
+                auto operator()(InputElement const& input_element) const noexcept -> OutputElement
+                {
+                    return std::exp(input_element);
+                }
+        };
+
+    }  // namespace detail
+
+
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(exp, detail::Exp)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/floor.hpp b/source/framework/algorithm/include/lue/framework/algorithm/floor.hpp
index 7a52d1e25..eda35e766 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/floor.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/floor.hpp
@@ -1,12 +1,32 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
+#include <cmath>
 
 
 namespace lue {
+    namespace detail {
 
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> floor(
-        Policies const& policies, PartitionedArray<Element, rank> const& array);
+        template<typename InputElement>
+        class Floor
+        {
+
+            public:
+
+                static_assert(std::is_floating_point_v<InputElement>);
+
+                using OutputElement = InputElement;
+
+
+                auto operator()(InputElement const& input_element) const noexcept -> OutputElement
+                {
+                    return std::floor(input_element);
+                }
+        };
+
+    }  // namespace detail
+
+
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(floor, detail::Floor)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/greater_than.hpp b/source/framework/algorithm/include/lue/framework/algorithm/greater_than.hpp
index 3e34f178f..79a352aa6 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/greater_than.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/greater_than.hpp
@@ -15,8 +15,9 @@ namespace lue {
 
                 using OutputElement = OutputElement_;
 
-                constexpr OutputElement operator()(
+                constexpr auto operator()(
                     InputElement const& input_element1, InputElement const& input_element2) const noexcept
+                    -> OutputElement
                 {
                     return input_element1 > input_element2;
                 }
@@ -25,6 +26,7 @@ namespace lue {
     }  // namespace detail
 
 
-    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(greater_than, detail::GreaterThan)
+    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+        greater_than, detail::GreaterThan)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/greater_than_equal_to.hpp b/source/framework/algorithm/include/lue/framework/algorithm/greater_than_equal_to.hpp
index f21d0b546..d28c9ef45 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/greater_than_equal_to.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/greater_than_equal_to.hpp
@@ -15,8 +15,9 @@ namespace lue {
 
                 using OutputElement = OutputElement_;
 
-                constexpr OutputElement operator()(
+                constexpr auto operator()(
                     InputElement const& input_element1, InputElement const& input_element2) const noexcept
+                    -> OutputElement
                 {
                     return input_element1 >= input_element2;
                 }
@@ -25,6 +26,7 @@ namespace lue {
     }  // namespace detail
 
 
-    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(greater_than_equal_to, detail::GreaterThanEqualTo)
+    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+        greater_than_equal_to, detail::GreaterThanEqualTo)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/less_than.hpp b/source/framework/algorithm/include/lue/framework/algorithm/less_than.hpp
index 21c87000a..278c102b9 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/less_than.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/less_than.hpp
@@ -16,8 +16,9 @@ namespace lue {
                 using OutputElement = OutputElement_;
 
 
-                constexpr OutputElement operator()(
+                constexpr auto operator()(
                     InputElement const& input_element1, InputElement const& input_element2) const noexcept
+                    -> OutputElement
                 {
                     return input_element1 < input_element2;
                 }
@@ -26,6 +27,6 @@ namespace lue {
     }  // namespace detail
 
 
-    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(less_than, detail::LessThan)
+    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_DIFFERENT_OUTPUT_ELEMENT(less_than, detail::LessThan)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/less_than_equal_to.hpp b/source/framework/algorithm/include/lue/framework/algorithm/less_than_equal_to.hpp
index 58d050c96..deb28fbfe 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/less_than_equal_to.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/less_than_equal_to.hpp
@@ -15,8 +15,9 @@ namespace lue {
 
                 using OutputElement = OutputElement_;
 
-                constexpr OutputElement operator()(
+                constexpr auto operator()(
                     InputElement const& input_element1, InputElement const& input_element2) const noexcept
+                    -> OutputElement
                 {
                     return input_element1 <= input_element2;
                 }
@@ -25,6 +26,7 @@ namespace lue {
     }  // namespace detail
 
 
-    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(less_than_equal_to, detail::LessThanEqualTo)
+    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+        less_than_equal_to, detail::LessThanEqualTo)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/log.hpp b/source/framework/algorithm/include/lue/framework/algorithm/log.hpp
index eb0679671..c46a89489 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/log.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/log.hpp
@@ -1,9 +1,32 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
+#include <cmath>
 
 
 namespace lue {
+    namespace detail {
+
+        template<typename InputElement>
+        class Log
+        {
+
+            public:
+
+                static_assert(std::is_floating_point_v<InputElement>);
+
+                using OutputElement = InputElement;
+
+
+                auto operator()(InputElement const& input_element) const noexcept -> OutputElement
+                {
+                    return std::log(input_element);
+                }
+        };
+
+    }  // namespace detail
+
+
     namespace policy::log {
 
         template<typename Element>
@@ -12,7 +35,7 @@ namespace lue {
 
             public:
 
-                static constexpr bool within_domain(Element const element) noexcept
+                static constexpr auto within_domain(Element const element) noexcept -> bool
                 {
                     return element >= 0;
                 }
@@ -21,8 +44,6 @@ namespace lue {
     }  // namespace policy::log
 
 
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> log(
-        Policies const& policies, PartitionedArray<Element, rank> const& array);
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(log, detail::Log)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/log10.hpp b/source/framework/algorithm/include/lue/framework/algorithm/log10.hpp
index 1280b69b1..5d8f797a9 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/log10.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/log10.hpp
@@ -1,9 +1,32 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
+#include <cmath>
 
 
 namespace lue {
+    namespace detail {
+
+        template<typename InputElement>
+        class Log10
+        {
+
+            public:
+
+                static_assert(std::is_floating_point_v<InputElement>);
+
+                using OutputElement = InputElement;
+
+
+                auto operator()(InputElement const& input_element) const noexcept -> OutputElement
+                {
+                    return std::log10(input_element);
+                }
+        };
+
+    }  // namespace detail
+
+
     namespace policy::log10 {
 
         template<typename Element>
@@ -12,7 +35,7 @@ namespace lue {
 
             public:
 
-                static constexpr bool within_domain(Element const element) noexcept
+                static constexpr auto within_domain(Element const element) noexcept -> bool
                 {
                     return element >= 0;
                 }
@@ -21,8 +44,6 @@ namespace lue {
     }  // namespace policy::log10
 
 
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> log10(
-        Policies const& policies, PartitionedArray<Element, rank> const& array);
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(log10, detail::Log10)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/logical_and.hpp b/source/framework/algorithm/include/lue/framework/algorithm/logical_and.hpp
index e175bebc9..96e8046a2 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/logical_and.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/logical_and.hpp
@@ -17,8 +17,9 @@ namespace lue {
                 using OutputElement = OutputElement_;
 
 
-                constexpr OutputElement operator()(
+                constexpr auto operator()(
                     InputElement const& input_element1, InputElement const& input_element2) const noexcept
+                    -> OutputElement
                 {
                     return input_element1 && input_element2;
                 }
@@ -27,6 +28,7 @@ namespace lue {
     }  // namespace detail
 
 
-    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(logical_and, detail::LogicalAnd)
+    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+        logical_and, detail::LogicalAnd)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/logical_exclusive_or.hpp b/source/framework/algorithm/include/lue/framework/algorithm/logical_exclusive_or.hpp
index d30165dd9..053b7cef1 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/logical_exclusive_or.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/logical_exclusive_or.hpp
@@ -17,8 +17,9 @@ namespace lue {
                 using OutputElement = OutputElement_;
 
 
-                constexpr OutputElement operator()(
+                constexpr auto operator()(
                     InputElement const& input_element1, InputElement const& input_element2) const noexcept
+                    -> OutputElement
                 {
                     return bool(input_element1) != bool(input_element2);
                 }
@@ -27,6 +28,7 @@ namespace lue {
     }  // namespace detail
 
 
-    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(logical_exclusive_or, detail::LogicalExclusiveOr)
+    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+        logical_exclusive_or, detail::LogicalExclusiveOr)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/logical_inclusive_or.hpp b/source/framework/algorithm/include/lue/framework/algorithm/logical_inclusive_or.hpp
index 1cfefd4b9..ddcf496bc 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/logical_inclusive_or.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/logical_inclusive_or.hpp
@@ -17,8 +17,9 @@ namespace lue {
                 using OutputElement = OutputElement_;
 
 
-                constexpr OutputElement operator()(
+                constexpr auto operator()(
                     InputElement const& input_element1, InputElement const& input_element2) const noexcept
+                    -> OutputElement
                 {
                     return input_element1 || input_element2;
                 }
@@ -27,6 +28,7 @@ namespace lue {
     }  // namespace detail
 
 
-    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(logical_inclusive_or, detail::LogicalInclusiveOr)
+    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+        logical_inclusive_or, detail::LogicalInclusiveOr)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/logical_not.hpp b/source/framework/algorithm/include/lue/framework/algorithm/logical_not.hpp
index b38016578..010942090 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/logical_not.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/logical_not.hpp
@@ -1,12 +1,33 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
 
 
 namespace lue {
+    namespace detail {
 
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<std::uint8_t, rank> logical_not(
-        Policies const& policies, PartitionedArray<Element, rank> const& array);
+        template<typename InputElement, typename OutputElement_ = std::uint8_t>
+        class LogicalNot
+        {
+
+            public:
+
+                static_assert(std::is_integral_v<InputElement>);
+
+                using OutputElement = OutputElement_;
+
+
+                constexpr auto operator()([[maybe_unused]] InputElement const& input_element) const noexcept
+                    -> OutputElement
+                {
+                    return !input_element;
+                }
+        };
+
+    }  // namespace detail
+
+
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+        logical_not, detail::LogicalNot)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/multiply.hpp b/source/framework/algorithm/include/lue/framework/algorithm/multiply.hpp
index ef639006c..e65d11575 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/multiply.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/multiply.hpp
@@ -16,8 +16,9 @@ namespace lue {
                 using OutputElement = OutputElement_;
 
 
-                constexpr OutputElement operator()(
+                constexpr auto operator()(
                     InputElement const& input_element1, InputElement const& input_element2) const noexcept
+                    -> OutputElement
                 {
                     return input_element1 * input_element2;
                 }
@@ -26,6 +27,6 @@ namespace lue {
     }  // namespace detail
 
 
-    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(multiply, detail::Multiply)
+    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(multiply, detail::Multiply)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/negate.hpp b/source/framework/algorithm/include/lue/framework/algorithm/negate.hpp
index b554eeeb0..a69ff7684 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/negate.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/negate.hpp
@@ -1,13 +1,30 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
 
 
 namespace lue {
+    namespace detail {
 
-    template<typename Policies, Rank rank>
-    auto negate(
-        Policies const& policies, PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& array)
-        -> PartitionedArray<policy::OutputElementT<Policies, 0>, rank>;
+        template<typename InputElement>
+        class Negate
+        {
+
+            public:
+
+                static_assert(std::is_signed_v<InputElement> || std::is_floating_point_v<InputElement>);
+
+                using OutputElement = InputElement;
+
+                auto operator()(InputElement const& input_element) const noexcept -> OutputElement
+                {
+                    return -input_element;
+                }
+        };
+
+    }  // namespace detail
+
+
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(negate, detail::Negate)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/not_equal_to.hpp b/source/framework/algorithm/include/lue/framework/algorithm/not_equal_to.hpp
index a87166c02..f6fcd1d68 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/not_equal_to.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/not_equal_to.hpp
@@ -16,8 +16,9 @@ namespace lue {
                 using OutputElement = OutputElement_;
 
 
-                constexpr OutputElement operator()(
+                constexpr auto operator()(
                     InputElement const& input_element1, InputElement const& input_element2) const noexcept
+                    -> OutputElement
                 {
                     return input_element1 != input_element2;
                 }
@@ -26,6 +27,7 @@ namespace lue {
     }  // namespace detail
 
 
-    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(not_equal_to, detail::NotEqualTo)
+    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+        not_equal_to, detail::NotEqualTo)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/operator.hpp b/source/framework/algorithm/include/lue/framework/algorithm/operator.hpp
index 7db54c8f7..e4bd26506 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/operator.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/operator.hpp
@@ -5,8 +5,9 @@
                                                                                                              \
     /* array + array */                                                                                      \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<Element, rank> operator symbol(                                                         \
+    auto operator symbol(                                                                                    \
         PartitionedArray<Element, rank> const& lhs, PartitionedArray<Element, rank> const& rhs)              \
+        ->PartitionedArray<Element, rank>                                                                    \
     {                                                                                                        \
         return name(lhs, rhs);                                                                               \
     }                                                                                                        \
@@ -14,8 +15,8 @@
                                                                                                              \
     /* array + scalar */                                                                                     \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<Element, rank> operator symbol(                                                         \
-        PartitionedArray<Element, rank> const& lhs, Scalar<Element> const& rhs)                              \
+    auto operator symbol(PartitionedArray<Element, rank> const& lhs, Scalar<Element> const& rhs)             \
+        ->PartitionedArray<Element, rank>                                                                    \
     {                                                                                                        \
         return name(lhs, rhs);                                                                               \
     }                                                                                                        \
@@ -23,8 +24,8 @@
                                                                                                              \
     /* array + value */                                                                                      \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<Element, rank> operator symbol(                                                         \
-        PartitionedArray<Element, rank> const& lhs, Element const& rhs)                                      \
+    auto operator symbol(PartitionedArray<Element, rank> const& lhs, Element const& rhs)                     \
+        ->PartitionedArray<Element, rank>                                                                    \
     {                                                                                                        \
         return name(lhs, rhs);                                                                               \
     }                                                                                                        \
@@ -32,8 +33,8 @@
                                                                                                              \
     /* scalar + array */                                                                                     \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<Element, rank> operator symbol(                                                         \
-        Scalar<Element> const& lhs, PartitionedArray<Element, rank> const& rhs)                              \
+    auto operator symbol(Scalar<Element> const& lhs, PartitionedArray<Element, rank> const& rhs)             \
+        ->PartitionedArray<Element, rank>                                                                    \
     {                                                                                                        \
         return name(lhs, rhs);                                                                               \
     }                                                                                                        \
@@ -41,8 +42,8 @@
                                                                                                              \
     /* value + array */                                                                                      \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<Element, rank> operator symbol(                                                         \
-        Element const& lhs, PartitionedArray<Element, rank> const& rhs)                                      \
+    auto operator symbol(Element const& lhs, PartitionedArray<Element, rank> const& rhs)                     \
+        ->PartitionedArray<Element, rank>                                                                    \
     {                                                                                                        \
         return name(lhs, rhs);                                                                               \
     }                                                                                                        \
@@ -76,103 +77,118 @@
                                                                                                              \
     /* array == array */                                                                                     \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<std::uint8_t, rank> operator symbol(                                                    \
+    auto operator symbol(                                                                                    \
         PartitionedArray<Element, rank> const& lhs, PartitionedArray<Element, rank> const& rhs)              \
+        ->PartitionedArray<std::uint8_t, rank>                                                               \
     {                                                                                                        \
-        return name(lhs, rhs);                                                                               \
+        return name<std::uint8_t>(lhs, rhs);                                                                 \
     }                                                                                                        \
                                                                                                              \
     /* array == scalar */                                                                                    \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<std::uint8_t, rank> operator symbol(                                                    \
-        PartitionedArray<Element, rank> const& lhs, Scalar<Element> const& rhs)                              \
+    auto operator symbol(PartitionedArray<Element, rank> const& lhs, Scalar<Element> const& rhs)             \
+        ->PartitionedArray<std::uint8_t, rank>                                                               \
     {                                                                                                        \
-        return name(lhs, rhs);                                                                               \
+        return name<std::uint8_t>(lhs, rhs);                                                                 \
     }                                                                                                        \
                                                                                                              \
     /* scalar == array */                                                                                    \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<std::uint8_t, rank> operator symbol(                                                    \
-        Scalar<Element> const& lhs, PartitionedArray<Element, rank> const& rhs)                              \
+    auto operator symbol(Scalar<Element> const& lhs, PartitionedArray<Element, rank> const& rhs)             \
+        ->PartitionedArray<std::uint8_t, rank>                                                               \
     {                                                                                                        \
-        return name(lhs, rhs);                                                                               \
+        return name<std::uint8_t>(lhs, rhs);                                                                 \
     }                                                                                                        \
                                                                                                              \
     /* array == value */                                                                                     \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<std::uint8_t, rank> operator symbol(                                                    \
-        PartitionedArray<Element, rank> const& lhs, Element const rhs)                                       \
+    auto operator symbol(PartitionedArray<Element, rank> const& lhs, Element const rhs)                      \
+        ->PartitionedArray<std::uint8_t, rank>                                                               \
     {                                                                                                        \
-        return name(lhs, rhs);                                                                               \
+        return name<std::uint8_t>(lhs, rhs);                                                                 \
     }                                                                                                        \
                                                                                                              \
     /* value == array */                                                                                     \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<std::uint8_t, rank> operator symbol(                                                    \
-        Element const lhs, PartitionedArray<Element, rank> const& rhs)                                       \
+    auto operator symbol(Element const lhs, PartitionedArray<Element, rank> const& rhs)                      \
+        ->PartitionedArray<std::uint8_t, rank>                                                               \
     {                                                                                                        \
-        return name(lhs, rhs);                                                                               \
+        return name<std::uint8_t>(lhs, rhs);                                                                 \
+    }                                                                                                        \
+                                                                                                             \
+    /* scalar == scalar */                                                                                   \
+    template<typename Element>                                                                               \
+    auto operator symbol(Scalar<Element> const& lhs, Scalar<Element> const& rhs)->Scalar<std::uint8_t>       \
+    {                                                                                                        \
+        return name<std::uint8_t>(lhs, rhs);                                                                 \
     }                                                                                                        \
                                                                                                              \
     /* scalar == value */                                                                                    \
     template<typename Element>                                                                               \
     auto operator symbol(Scalar<Element> const& lhs, Element const rhs)->Scalar<std::uint8_t>                \
     {                                                                                                        \
-        return name(lhs, rhs);                                                                               \
+        return name<std::uint8_t>(lhs, rhs);                                                                 \
     }                                                                                                        \
                                                                                                              \
     /* value == scalar */                                                                                    \
     template<typename Element>                                                                               \
     auto operator symbol(Element const lhs, Scalar<Element> const& rhs)->Scalar<std::uint8_t>                \
     {                                                                                                        \
-        return name(lhs, rhs);                                                                               \
+        return name<std::uint8_t>(lhs, rhs);                                                                 \
     }
 
 
 #define LUE_UNARY_LOGICAL_OPERATOR(symbol, name)                                                             \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<std::uint8_t, rank> operator symbol(PartitionedArray<Element, rank> const& array)       \
+    auto operator symbol(PartitionedArray<Element, rank> const& array)->PartitionedArray<std::uint8_t, rank> \
+    {                                                                                                        \
+        return name<std::uint8_t>(array);                                                                    \
+    }                                                                                                        \
+                                                                                                             \
+    template<typename Element>                                                                               \
+    auto operator symbol(Scalar<Element> const& scalar)->Scalar<std::uint8_t>                                \
     {                                                                                                        \
-        return name(array);                                                                                  \
+        return name<std::uint8_t>(scalar);                                                                   \
     }
 
 
 #define LUE_BINARY_LOGICAL_OPERATOR(symbol, name)                                                            \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<std::uint8_t, rank> operator symbol(                                                    \
+    auto operator symbol(                                                                                    \
         PartitionedArray<Element, rank> const& lhs, PartitionedArray<Element, rank> const& rhs)              \
+        ->PartitionedArray<std::uint8_t, rank>                                                               \
     {                                                                                                        \
-        return name(lhs, rhs);                                                                               \
+        return name<std::uint8_t>(lhs, rhs);                                                                 \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<std::uint8_t, rank> operator symbol(                                                    \
-        PartitionedArray<Element, rank> const& lhs, hpx::shared_future<Element> const& rhs)                  \
+    auto operator symbol(PartitionedArray<Element, rank> const& lhs, hpx::shared_future<Element> const& rhs) \
+        ->PartitionedArray<std::uint8_t, rank>                                                               \
     {                                                                                                        \
-        return name(lhs, rhs);                                                                               \
+        return name<std::uint8_t>(lhs, rhs);                                                                 \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<std::uint8_t, rank> operator symbol(                                                    \
-        hpx::shared_future<Element> const& lhs, PartitionedArray<Element, rank> const& rhs)                  \
+    auto operator symbol(hpx::shared_future<Element> const& lhs, PartitionedArray<Element, rank> const& rhs) \
+        ->PartitionedArray<std::uint8_t, rank>                                                               \
     {                                                                                                        \
-        return name(lhs, rhs);                                                                               \
+        return name<std::uint8_t>(lhs, rhs);                                                                 \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<std::uint8_t, rank> operator symbol(                                                    \
-        PartitionedArray<Element, rank> const& lhs, Element const rhs)                                       \
+    auto operator symbol(PartitionedArray<Element, rank> const& lhs, Element const rhs)                      \
+        ->PartitionedArray<std::uint8_t, rank>                                                               \
     {                                                                                                        \
-        return name(lhs, rhs);                                                                               \
+        return name<std::uint8_t>(lhs, rhs);                                                                 \
     }                                                                                                        \
                                                                                                              \
                                                                                                              \
     template<typename Element, Rank rank>                                                                    \
-    PartitionedArray<std::uint8_t, rank> operator symbol(                                                    \
-        Element const lhs, PartitionedArray<Element, rank> const& rhs)                                       \
+    auto operator symbol(Element const lhs, PartitionedArray<Element, rank> const& rhs)                      \
+        ->PartitionedArray<std::uint8_t, rank>                                                               \
     {                                                                                                        \
-        return name(lhs, rhs);                                                                               \
+        return name<std::uint8_t>(lhs, rhs);                                                                 \
     }
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/pow.hpp b/source/framework/algorithm/include/lue/framework/algorithm/pow.hpp
index 30759d494..e1f819e72 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/pow.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/pow.hpp
@@ -1,10 +1,7 @@
 #pragma once
 #include "lue/framework/algorithm/binary_local_operation.hpp"
-#include "lue/framework/algorithm/policy/all_values_within_domain.hpp"
-#include "lue/framework/algorithm/policy/default_policies.hpp"
-#include "lue/framework/algorithm/policy/default_value_policies.hpp"
+#include "lue/framework/algorithm/policy.hpp"
 #include <cmath>
-#include <limits>
 
 
 namespace lue {
@@ -21,8 +18,8 @@ namespace lue {
                 using OutputElement = OutputElement_;
 
 
-                OutputElement operator()(
-                    InputElement const input_element, InputElement const exponent) const noexcept
+                auto operator()(InputElement const input_element, InputElement const exponent) const noexcept
+                    -> OutputElement
                 {
                     return std::pow(input_element, exponent);
                 }
@@ -36,34 +33,9 @@ namespace lue {
         template<typename InputElement>
         using DomainPolicy = AllValuesWithinDomain<InputElement, InputElement>;
 
-        template<typename OutputElement, typename InputElement>
-        using DefaultPolicies = policy::DefaultPolicies<
-            DomainPolicy<InputElement>,
-            OutputElements<OutputElement>,
-            InputElements<InputElement, InputElement>>;
+    }
 
-        template<typename OutputElement, typename InputElement>
-        using DefaultValuePolicies = policy::DefaultValuePolicies<
-            DomainPolicy<InputElement>,
-            OutputElements<OutputElement>,
-            InputElements<InputElement, InputElement>>;
 
-    }  // namespace policy::pow
-
-
-    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(pow, detail::Pow)
-
-    namespace default_policies {
-
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(pow, detail::Pow, policy::pow::DefaultPolicies)
-
-    }  // namespace default_policies
-
-    namespace value_policies {
-
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            pow, detail::Pow, policy::pow::DefaultValuePolicies)
-
-    }  // namespace value_policies
+    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(pow, detail::Pow)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/round.hpp b/source/framework/algorithm/include/lue/framework/algorithm/round.hpp
index b5073d97b..26d0add0b 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/round.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/round.hpp
@@ -1,12 +1,32 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
+#include <cmath>
 
 
 namespace lue {
+    namespace detail {
 
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> round(
-        Policies const& policies, PartitionedArray<Element, rank> const& array);
+        template<typename InputElement>
+        class Round
+        {
+
+            public:
+
+                static_assert(std::is_floating_point_v<InputElement>);
+
+                using OutputElement = InputElement;
+
+
+                auto operator()(InputElement const& input_element) const noexcept -> OutputElement
+                {
+                    return std::round(input_element);
+                }
+        };
+
+    }  // namespace detail
+
+
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(round, detail::Round)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/sin.hpp b/source/framework/algorithm/include/lue/framework/algorithm/sin.hpp
index 642c28e5c..9d5b12bf5 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/sin.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/sin.hpp
@@ -1,12 +1,32 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
+#include <cmath>
 
 
 namespace lue {
+    namespace detail {
 
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> sin(
-        Policies const& policies, PartitionedArray<Element, rank> const& array);
+        template<typename InputElement>
+        class Sin
+        {
+
+            public:
+
+                static_assert(std::is_floating_point_v<InputElement>);
+
+                using OutputElement = InputElement;
+
+
+                auto operator()(InputElement const& input_element) const noexcept -> OutputElement
+                {
+                    return std::sin(input_element);
+                }
+        };
+
+    }  // namespace detail
+
+
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(sin, detail::Sin)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/sqrt.hpp b/source/framework/algorithm/include/lue/framework/algorithm/sqrt.hpp
index e08dfadac..9e04bf8c8 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/sqrt.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/sqrt.hpp
@@ -1,9 +1,31 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
+#include <cmath>
 
 
 namespace lue {
+    namespace detail {
+
+        template<typename InputElement>
+        class Sqrt
+        {
+
+            public:
+
+                static_assert(std::is_floating_point_v<InputElement>);
+
+                using OutputElement = InputElement;
+
+                auto operator()(InputElement const& input_element) const noexcept -> OutputElement
+                {
+                    return std::sqrt(input_element);
+                }
+        };
+
+    }  // namespace detail
+
+
     namespace policy::sqrt {
 
         template<typename Element>
@@ -12,7 +34,7 @@ namespace lue {
 
             public:
 
-                static constexpr bool within_domain(Element const element) noexcept
+                static constexpr auto within_domain(Element const element) noexcept -> bool
                 {
                     return element >= 0;
                 }
@@ -21,8 +43,6 @@ namespace lue {
     }  // namespace policy::sqrt
 
 
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> sqrt(
-        Policies const& policies, PartitionedArray<Element, rank> const& array);
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(sqrt, detail::Sqrt)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/subtract.hpp b/source/framework/algorithm/include/lue/framework/algorithm/subtract.hpp
index e0f940b79..5a966ab1f 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/subtract.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/subtract.hpp
@@ -16,8 +16,9 @@ namespace lue {
                 using OutputElement = OutputElement_;
 
 
-                constexpr OutputElement operator()(
+                constexpr auto operator()(
                     InputElement const& input_element1, InputElement const& input_element2) const noexcept
+                    -> OutputElement
                 {
                     return input_element1 - input_element2;
                 }
@@ -26,6 +27,6 @@ namespace lue {
     }  // namespace detail
 
 
-    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES(subtract, detail::Subtract)
+    LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(subtract, detail::Subtract)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/tan.hpp b/source/framework/algorithm/include/lue/framework/algorithm/tan.hpp
index 03fd8a1ab..f74f744ba 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/tan.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/tan.hpp
@@ -1,12 +1,32 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
+#include <cmath>
 
 
 namespace lue {
+    namespace detail {
 
-    template<typename Policies, typename Element, Rank rank>
-    PartitionedArray<Element, rank> tan(
-        Policies const& policies, PartitionedArray<Element, rank> const& array);
+        template<typename InputElement>
+        class Tan
+        {
+
+            public:
+
+                static_assert(std::is_floating_point_v<InputElement>);
+
+                using OutputElement = InputElement;
+
+
+                auto operator()(InputElement const& input_element) const noexcept -> OutputElement
+                {
+                    return std::tan(input_element);
+                }
+        };
+
+    }  // namespace detail
+
+
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(tan, detail::Tan)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/unary_local_operation.hpp b/source/framework/algorithm/include/lue/framework/algorithm/unary_local_operation.hpp
index 5ea31a80b..2e2140c2d 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/unary_local_operation.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/unary_local_operation.hpp
@@ -1,23 +1,165 @@
 #pragma once
-#include "lue/framework/algorithm/functor_traits.hpp"
+#include "lue/framework/algorithm/policy/policy_traits.hpp"
 #include "lue/framework/algorithm/scalar.hpp"
 #include "lue/framework/partitioned_array.hpp"
+#include <type_traits>
 
 
 namespace lue {
 
-    // local_operation(array, array)
-    template<typename Policies, typename InputElement, Rank rank, typename Functor>
+    // local_operation(array)
+    template<typename Policies, Rank rank, typename Functor>
     auto unary_local_operation(
         Policies const& policies,
-        PartitionedArray<InputElement, rank> const& input_array,
-        Functor const& functor) -> PartitionedArray<OutputElementT<Functor>, rank>;
+        PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& input_array,
+        Functor const& functor) -> PartitionedArray<policy::OutputElementT<Policies, 0>, rank>;
 
 
-    // local_operation(scalar, scalar)
-    template<typename Policies, typename InputElement, typename Functor>
+    // local_operation(scalar)
+    template<typename Policies, typename Functor>
     auto unary_local_operation(
-        Policies const& policies, Scalar<InputElement> const& input_scalar, Functor const& functor)
-        -> Scalar<OutputElementT<Functor>>;
+        Policies const& policies,
+        Scalar<policy::InputElementT<Policies, 0>> const& input_scalar,
+        Functor const& functor) -> Scalar<policy::OutputElementT<Policies, 0>>;
 
 }  // namespace lue
+
+
+// All overloads *with* a Policies template parameter
+#define LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_DIFFERENT_OUTPUT_ELEMENT(name, Functor)            \
+                                                                                                             \
+    /* f(policies, array) */                                                                                 \
+    template<typename Policies, Rank rank>                                                                   \
+    auto name(                                                                                               \
+        Policies const& policies, PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& array)   \
+        ->PartitionedArray<policy::OutputElementT<Policies, 0>, rank>                                        \
+    {                                                                                                        \
+        return unary_local_operation(                                                                        \
+            policies,                                                                                        \
+            array,                                                                                           \
+            Functor<policy::InputElementT<Policies, 0>, policy::OutputElementT<Policies, 0>>{});             \
+    }                                                                                                        \
+                                                                                                             \
+                                                                                                             \
+    /* f(policies, scalar) */                                                                                \
+    template<typename Policies>                                                                              \
+    auto name(Policies const& policies, Scalar<policy::InputElementT<Policies, 0>> const& scalar)            \
+        ->Scalar<policy::OutputElementT<Policies, 0>>                                                        \
+    {                                                                                                        \
+        return unary_local_operation(                                                                        \
+            policies,                                                                                        \
+            scalar,                                                                                          \
+            Functor<policy::InputElementT<Policies, 0>, policy::OutputElementT<Policies, 0>>{});             \
+    }                                                                                                        \
+                                                                                                             \
+                                                                                                             \
+    /* f(policies, value) */                                                                                 \
+    template<typename Policies>                                                                              \
+    requires std::is_arithmetic_v<policy::InputElementT<Policies, 0>> auto name(                             \
+        Policies const& policies, policy::InputElementT<Policies, 0> const value)                            \
+        ->Scalar<policy::OutputElementT<Policies, 0>>                                                        \
+    {                                                                                                        \
+        return name(policies, Scalar{value});                                                                \
+    }
+
+
+// All overloads *with* a Policies template parameter
+#define LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_SAME_OUTPUT_ELEMENT(name, Functor)                 \
+                                                                                                             \
+    /* f(policies, array) */                                                                                 \
+    template<typename Policies, Rank rank>                                                                   \
+    auto name(                                                                                               \
+        Policies const& policies, PartitionedArray<policy::InputElementT<Policies, 0>, rank> const& array)   \
+        ->PartitionedArray<policy::OutputElementT<Policies, 0>, rank>                                        \
+    {                                                                                                        \
+        return unary_local_operation(policies, array, Functor<policy::InputElementT<Policies, 0>>{});        \
+    }                                                                                                        \
+                                                                                                             \
+                                                                                                             \
+    /* f(policies, scalar) */                                                                                \
+    template<typename Policies>                                                                              \
+    auto name(Policies const& policies, Scalar<policy::InputElementT<Policies, 0>> const& scalar)            \
+        ->Scalar<policy::OutputElementT<Policies, 0>>                                                        \
+    {                                                                                                        \
+        return unary_local_operation(policies, scalar, Functor<policy::InputElementT<Policies, 0>>{});       \
+    }                                                                                                        \
+                                                                                                             \
+                                                                                                             \
+    /* f(policies, value) */                                                                                 \
+    template<typename Policies>                                                                              \
+    requires std::is_arithmetic_v<policy::InputElementT<Policies, 0>> auto name(                             \
+        Policies const& policies, policy::InputElementT<Policies, 0> const value)                            \
+        ->Scalar<policy::OutputElementT<Policies, 0>>                                                        \
+    {                                                                                                        \
+        return name(policies, Scalar{value});                                                                \
+    }
+
+
+// All overloads *without* a Policies template parameter
+// Create a Policies instance and call the general implementation
+#define LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(name, Policies)        \
+                                                                                                             \
+    /* f(array) */                                                                                           \
+    template<typename OutputElement, typename InputElement, Rank rank>                                       \
+    auto name(PartitionedArray<InputElement, rank> const& array)->PartitionedArray<OutputElement, rank>      \
+    {                                                                                                        \
+        using Policies_ = Policies<OutputElement, InputElement>;                                             \
+                                                                                                             \
+        return name(Policies_{}, array);                                                                     \
+    }                                                                                                        \
+                                                                                                             \
+                                                                                                             \
+    /* f(scalar) */                                                                                          \
+    template<typename OutputElement, typename InputElement>                                                  \
+    auto name(Scalar<InputElement> const& scalar)->Scalar<OutputElement>                                     \
+    {                                                                                                        \
+        using Policies_ = Policies<OutputElement, InputElement>;                                             \
+                                                                                                             \
+        return name(Policies_{}, scalar);                                                                    \
+    }                                                                                                        \
+                                                                                                             \
+                                                                                                             \
+    /* f(value) */                                                                                           \
+    template<typename OutputElement, typename InputElement>                                                  \
+    requires std::is_arithmetic_v<OutputElement>&& std::is_arithmetic_v<InputElement> auto name(             \
+        InputElement const value)                                                                            \
+        ->Scalar<OutputElement>                                                                              \
+    {                                                                                                        \
+        using Policies_ = Policies<OutputElement, InputElement>;                                             \
+                                                                                                             \
+        return lue::name(Policies_{}, value);                                                                \
+    }
+
+
+// All overloads *without* a Policies template parameter
+// Create a Policies instance and call the general implementation
+#define LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(name, Policies)             \
+                                                                                                             \
+    /* f(array) */                                                                                           \
+    template<typename Element, Rank rank>                                                                    \
+    auto name(PartitionedArray<Element, rank> const& array)->PartitionedArray<Element, rank>                 \
+    {                                                                                                        \
+        using Policies_ = Policies<Element>;                                                                 \
+                                                                                                             \
+        return name(Policies_{}, array);                                                                     \
+    }                                                                                                        \
+                                                                                                             \
+                                                                                                             \
+    /* f(scalar) */                                                                                          \
+    template<typename Element>                                                                               \
+    auto name(Scalar<Element> const& scalar)->Scalar<Element>                                                \
+    {                                                                                                        \
+        using Policies_ = Policies<Element>;                                                                 \
+                                                                                                             \
+        return name(Policies_{}, scalar);                                                                    \
+    }                                                                                                        \
+                                                                                                             \
+                                                                                                             \
+    /* f(value) */                                                                                           \
+    template<typename Element>                                                                               \
+    requires std::is_arithmetic_v<Element> auto name(Element const value)->Scalar<Element>                   \
+    {                                                                                                        \
+        using Policies_ = Policies<Element>;                                                                 \
+                                                                                                             \
+        return lue::name(Policies_{}, value);                                                                \
+    }
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/valid.hpp b/source/framework/algorithm/include/lue/framework/algorithm/valid.hpp
index 22e8d5909..62e537cfd 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/valid.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/valid.hpp
@@ -1,16 +1,30 @@
 #pragma once
 #include "lue/framework/algorithm/policy.hpp"
-#include "lue/framework/algorithm/scalar.hpp"
-#include "lue/framework/partitioned_array.hpp"
+#include "lue/framework/algorithm/unary_local_operation.hpp"
 
 
 namespace lue {
+    namespace detail {
 
-    template<typename BooleanElement, typename Policies, typename ExpressionElement, Rank rank>
-    auto valid(Policies const& policies, PartitionedArray<ExpressionElement, rank> const& array)
-        -> PartitionedArray<BooleanElement, rank>;
+        template<typename InputElement, typename OutputElement_ = std::uint8_t>
+        class Valid
+        {
 
-    template<typename BooleanElement, typename Policies, typename ExpressionElement>
-    auto valid(Policies const& policies, Scalar<ExpressionElement> const& scalar) -> Scalar<BooleanElement>;
+            public:
+
+                using OutputElement = OutputElement_;
+
+
+                constexpr auto operator()([[maybe_unused]] InputElement const& input_element) const noexcept
+                    -> OutputElement
+                {
+                    return 1;
+                }
+        };
+
+    }  // namespace detail
+
+
+    LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITH_POLICIES_DIFFERENT_OUTPUT_ELEMENT(valid, detail::Valid)
 
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/abs.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/abs.hpp
index c667a0a79..80f1d5a04 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/abs.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/abs.hpp
@@ -11,8 +11,8 @@ namespace lue {
 
             public:
 
-                constexpr static bool within_range(
-                    Element const& argument, [[maybe_unused]] Element const& result)
+                constexpr static auto within_range(
+                    Element const& argument, [[maybe_unused]] Element const& result) -> bool
                 {
                     if constexpr (std::is_signed_v<Element>)
                     {
@@ -39,13 +39,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        auto abs(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::abs::DefaultValuePolicies<Element>;
-
-            return abs(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            abs, policy::abs::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/acos.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/acos.hpp
index aa38088e7..c15bbcf1c 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/acos.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/acos.hpp
@@ -11,7 +11,7 @@ namespace lue {
 
             public:
 
-                static constexpr bool within_domain(Element const element) noexcept
+                static constexpr auto within_domain(Element const element) noexcept -> bool
                 {
                     return element >= Element{-1} && element <= Element{1};
                 }
@@ -26,13 +26,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        auto acos(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::acos::DefaultValuePolicies<Element>;
-
-            return acos(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            acos, policy::acos::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/add.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/add.hpp
index 82b2034ed..bb04fd093 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/add.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/add.hpp
@@ -22,23 +22,22 @@ namespace lue {
         };
 
 
-        template<typename OutputElement, typename InputElement>
+        template<typename Element>
         using DefaultValuePolicies = policy::Policies<
-            AllValuesWithinDomain<InputElement, InputElement>,
-            OutputsPolicies<OutputPolicies<
-                DefaultOutputNoDataPolicy<OutputElement>,
-                RangePolicy<OutputElement, InputElement>>>,
+            AllValuesWithinDomain<Element, Element>,
+            OutputsPolicies<
+                OutputPolicies<DefaultOutputNoDataPolicy<Element>, RangePolicy<Element, Element>>>,
             InputsPolicies<
-                InputPolicies<DefaultInputNoDataPolicy<InputElement>>,
-                InputPolicies<DefaultInputNoDataPolicy<InputElement>>>>;
+                InputPolicies<DefaultInputNoDataPolicy<Element>>,
+                InputPolicies<DefaultInputNoDataPolicy<Element>>>>;
 
     }  // namespace policy::add
 
 
     namespace value_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            add, detail::Add, policy::add::DefaultValuePolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            add, policy::add::DefaultValuePolicies)
         LUE_BINARY_ARITHMETIC_OPERATOR(+, add)
 
     }  // namespace value_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/asin.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/asin.hpp
index 99414c72e..3c7a12215 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/asin.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/asin.hpp
@@ -11,7 +11,7 @@ namespace lue {
 
             public:
 
-                static constexpr bool within_domain(Element const element) noexcept
+                static constexpr auto within_domain(Element const element) noexcept -> bool
                 {
                     return element >= Element{-1} && element <= Element{1};
                 }
@@ -26,13 +26,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        auto asin(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::asin::DefaultValuePolicies<Element>;
-
-            return asin(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            asin, policy::asin::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/atan.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/atan.hpp
index 5fc9ff511..92a1dcefe 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/atan.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/atan.hpp
@@ -16,13 +16,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        auto atan(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::atan::DefaultValuePolicies<Element>;
-
-            return atan(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            atan, policy::atan::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/cast.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/cast.hpp
index 125a9cef0..5aac2c41e 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/cast.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/cast.hpp
@@ -21,11 +21,13 @@ namespace lue {
 
     }  // namespace detail
 
+
     template<typename From, typename To>
     struct is_narrowing_cast: detail::is_narrowing_cast_impl<From, To>
     {
     };
 
+
     template<typename From, typename To>
     constexpr bool is_narrowing_cast_v = is_narrowing_cast<From, To>::value;
 
@@ -135,13 +137,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename OutputElement, typename InputElement, Rank rank>
-        auto cast(PartitionedArray<InputElement, rank> const& array) -> PartitionedArray<OutputElement, rank>
-        {
-            using Policies = policy::cast::DefaultValuePolicies<OutputElement, InputElement>;
-
-            return lue::cast<OutputElement>(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            cast, policy::cast::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/ceil.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/ceil.hpp
index 880892a37..424593fdc 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/ceil.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/ceil.hpp
@@ -16,13 +16,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        auto ceil(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::ceil::DefaultValuePolicies<Element>;
-
-            return ceil(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            ceil, policy::ceil::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/close_to.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/close_to.hpp
index f9d2900c6..8aa2180dd 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/close_to.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/close_to.hpp
@@ -16,8 +16,8 @@ namespace lue {
 
     namespace value_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            close_to, detail::CloseTo, policy::close_to::DefaultValuePolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            close_to, policy::close_to::DefaultValuePolicies)
 
     }  // namespace value_policies
 
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/cos.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/cos.hpp
index a85237532..2ae980229 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/cos.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/cos.hpp
@@ -16,13 +16,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        auto cos(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::cos::DefaultValuePolicies<Element>;
-
-            return cos(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            cos, policy::cos::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/divide.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/divide.hpp
index 76b1f692a..133ea2bed 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/divide.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/divide.hpp
@@ -14,31 +14,31 @@ namespace lue {
 
                 static_assert(std::is_same_v<InputElement, OutputElement>);
 
-                constexpr static bool within_range(
+                constexpr static auto within_range(
                     InputElement const& argument1, InputElement const& argument2, OutputElement const& result)
+                    -> bool
                 {
                     return divide_within_range(argument1, argument2, result);
                 }
         };
 
 
-        template<typename OutputElement, typename InputElement>
+        template<typename Element>
         using DefaultValuePolicies = policy::Policies<
-            DomainPolicy<InputElement>,
-            OutputsPolicies<OutputPolicies<
-                DefaultOutputNoDataPolicy<OutputElement>,
-                RangePolicy<OutputElement, InputElement>>>,
+            DomainPolicy<Element>,
+            OutputsPolicies<
+                OutputPolicies<DefaultOutputNoDataPolicy<Element>, RangePolicy<Element, Element>>>,
             InputsPolicies<
-                InputPolicies<DefaultInputNoDataPolicy<InputElement>>,
-                InputPolicies<DefaultInputNoDataPolicy<InputElement>>>>;
+                InputPolicies<DefaultInputNoDataPolicy<Element>>,
+                InputPolicies<DefaultInputNoDataPolicy<Element>>>>;
 
     }  // namespace policy::divide
 
 
     namespace value_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            divide, detail::Divide, policy::divide::DefaultValuePolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            divide, policy::divide::DefaultValuePolicies)
         LUE_BINARY_ARITHMETIC_OPERATOR(/, divide)
 
     }  // namespace value_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/equal_to.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/equal_to.hpp
index f53ed44d5..e78d654eb 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/equal_to.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/equal_to.hpp
@@ -18,10 +18,10 @@ namespace lue {
 
         // partition == scalar_f
         template<typename InputElement, typename OutputElement = std::uint8_t, Rank rank>
-        ArrayPartition<OutputElement, rank> equal_to(
+        auto equal_to(
             hpx::id_type const locality_id,
             ArrayPartition<InputElement, rank> const& partition,
-            hpx::shared_future<InputElement> const& scalar)
+            hpx::shared_future<InputElement> const& scalar) -> ArrayPartition<OutputElement, rank>
         {
             using Policies = policy::equal_to::DefaultValuePolicies<OutputElement, InputElement>;
 
@@ -32,18 +32,18 @@ namespace lue {
 
         // partition == scalar
         template<typename InputElement, typename OutputElement = std::uint8_t, Rank rank>
-        ArrayPartition<OutputElement, rank> equal_to(
+        auto equal_to(
             hpx::id_type const locality_id,
             ArrayPartition<InputElement, rank> const& partition,
-            InputElement const& scalar)
+            InputElement const& scalar) -> ArrayPartition<OutputElement, rank>
         {
             return equal_to<InputElement, OutputElement, rank>(
                 locality_id, partition, hpx::make_ready_future<InputElement>(scalar).share());
         }
 
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            equal_to, detail::EqualTo, policy::equal_to::DefaultValuePolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            equal_to, policy::equal_to::DefaultValuePolicies)
         LUE_BINARY_COMPARISON_OPERATOR(==, equal_to)
 
     }  // namespace value_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/exp.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/exp.hpp
index 46ffebce7..16fb998b4 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/exp.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/exp.hpp
@@ -11,8 +11,8 @@ namespace lue {
 
             public:
 
-                constexpr static bool within_range(
-                    [[maybe_unused]] Element const& argument, Element const& result)
+                constexpr static auto within_range(
+                    [[maybe_unused]] Element const& argument, Element const& result) -> bool
                 {
                     return !std::isinf(result);
                 }
@@ -30,13 +30,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        auto exp(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::exp::DefaultValuePolicies<Element>;
-
-            return exp(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            exp, policy::exp::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/floor.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/floor.hpp
index 0d23075ab..3b1f3432f 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/floor.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/floor.hpp
@@ -16,13 +16,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        auto floor(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::floor::DefaultValuePolicies<Element>;
-
-            return floor(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            floor, policy::floor::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/greater_than.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/greater_than.hpp
index 7909f70fb..6c5370762 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/greater_than.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/greater_than.hpp
@@ -16,8 +16,8 @@ namespace lue {
 
     namespace value_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            greater_than, detail::GreaterThan, policy::greater_than::DefaultValuePolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            greater_than, policy::greater_than::DefaultValuePolicies)
         LUE_BINARY_COMPARISON_OPERATOR(>, greater_than)
 
     }  // namespace value_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/greater_than_equal_to.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/greater_than_equal_to.hpp
index eba01bf58..20b3ad9f7 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/greater_than_equal_to.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/greater_than_equal_to.hpp
@@ -16,10 +16,8 @@ namespace lue {
 
     namespace value_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            greater_than_equal_to,
-            detail::GreaterThanEqualTo,
-            policy::greater_than_equal_to::DefaultValuePolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            greater_than_equal_to, policy::greater_than_equal_to::DefaultValuePolicies)
         LUE_BINARY_COMPARISON_OPERATOR(>=, greater_than_equal_to)
 
     }  // namespace value_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/less_than.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/less_than.hpp
index 4bfecee86..0cd8f9195 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/less_than.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/less_than.hpp
@@ -16,8 +16,8 @@ namespace lue {
 
     namespace value_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            less_than, detail::LessThan, policy::less_than::DefaultValuePolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            less_than, policy::less_than::DefaultValuePolicies)
         LUE_BINARY_COMPARISON_OPERATOR(<, less_than)
 
     }  // namespace value_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/less_than_equal_to.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/less_than_equal_to.hpp
index b625530eb..b73618c5a 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/less_than_equal_to.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/less_than_equal_to.hpp
@@ -16,8 +16,8 @@ namespace lue {
 
     namespace value_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            less_than_equal_to, detail::LessThanEqualTo, policy::less_than_equal_to::DefaultValuePolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            less_than_equal_to, policy::less_than_equal_to::DefaultValuePolicies)
         LUE_BINARY_COMPARISON_OPERATOR(<=, less_than_equal_to)
 
     }  // namespace value_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/log.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/log.hpp
index 8f3a63d42..93b7d31ab 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/log.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/log.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        auto log(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::log::DefaultValuePolicies<Element>;
-
-            return log(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            log, policy::log::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/log10.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/log10.hpp
index 3f4d8e507..3a8f352de 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/log10.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/log10.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        auto log10(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::log10::DefaultValuePolicies<Element>;
-
-            return log10(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            log10, policy::log10::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_and.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_and.hpp
index 6d70297f7..e35dac382 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_and.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_and.hpp
@@ -17,8 +17,8 @@ namespace lue {
 
     namespace value_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            logical_and, detail::LogicalAnd, policy::logical_and::DefaultValuePolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            logical_and, policy::logical_and::DefaultValuePolicies)
         LUE_BINARY_LOGICAL_OPERATOR(&&, logical_and)
 
     }  // namespace value_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_exclusive_or.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_exclusive_or.hpp
index 3eb22b213..7d8690c61 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_exclusive_or.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_exclusive_or.hpp
@@ -17,10 +17,8 @@ namespace lue {
 
     namespace value_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            logical_exclusive_or,
-            detail::LogicalExclusiveOr,
-            policy::logical_exclusive_or::DefaultValuePolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            logical_exclusive_or, policy::logical_exclusive_or::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_inclusive_or.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_inclusive_or.hpp
index 76f6beb58..5bbce05f1 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_inclusive_or.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_inclusive_or.hpp
@@ -17,10 +17,8 @@ namespace lue {
 
     namespace value_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            logical_inclusive_or,
-            detail::LogicalInclusiveOr,
-            policy::logical_inclusive_or::DefaultValuePolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            logical_inclusive_or, policy::logical_inclusive_or::DefaultValuePolicies)
         LUE_BINARY_LOGICAL_OPERATOR(||, logical_inclusive_or)
 
     }  // namespace value_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_not.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_not.hpp
index 665899ee5..aa01e2125 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_not.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/logical_not.hpp
@@ -17,14 +17,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        PartitionedArray<std::uint8_t, rank> logical_not(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::logical_not::DefaultValuePolicies<std::uint8_t, Element>;
-
-            return logical_not(Policies{}, array);
-        }
-
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            logical_not, policy::logical_not::DefaultValuePolicies)
 
         LUE_UNARY_LOGICAL_OPERATOR(!, logical_not)
 
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/multiply.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/multiply.hpp
index 6394a7270..461d7299c 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/multiply.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/multiply.hpp
@@ -14,31 +14,31 @@ namespace lue {
 
                 static_assert(std::is_same_v<InputElement, OutputElement>);
 
-                constexpr static bool within_range(
+                constexpr static auto within_range(
                     InputElement const& argument1, InputElement const& argument2, OutputElement const& result)
+                    -> bool
                 {
                     return multiply_within_range(argument1, argument2, result);
                 }
         };
 
 
-        template<typename OutputElement, typename InputElement>
+        template<typename Element>
         using DefaultValuePolicies = policy::Policies<
-            AllValuesWithinDomain<InputElement, InputElement>,
-            OutputsPolicies<OutputPolicies<
-                DefaultOutputNoDataPolicy<OutputElement>,
-                RangePolicy<OutputElement, InputElement>>>,
+            AllValuesWithinDomain<Element, Element>,
+            OutputsPolicies<
+                OutputPolicies<DefaultOutputNoDataPolicy<Element>, RangePolicy<Element, Element>>>,
             InputsPolicies<
-                InputPolicies<DefaultInputNoDataPolicy<InputElement>>,
-                InputPolicies<DefaultInputNoDataPolicy<InputElement>>>>;
+                InputPolicies<DefaultInputNoDataPolicy<Element>>,
+                InputPolicies<DefaultInputNoDataPolicy<Element>>>>;
 
     }  // namespace policy::multiply
 
 
     namespace value_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            multiply, detail::Multiply, policy::multiply::DefaultValuePolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            multiply, policy::multiply::DefaultValuePolicies)
         LUE_BINARY_ARITHMETIC_OPERATOR(*, multiply)
 
     }  // namespace value_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/negate.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/negate.hpp
index 925cf65d6..42db1199b 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/negate.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/negate.hpp
@@ -17,13 +17,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        auto negate(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::negate::DefaultValuePolicies<Element>;
-
-            return negate(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            negate, policy::negate::DefaultValuePolicies)
 
         LUE_UNARY_LOGICAL_OPERATOR(-, negate)
 
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/not_equal_to.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/not_equal_to.hpp
index 26d282d12..2b2746fa8 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/not_equal_to.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/not_equal_to.hpp
@@ -16,8 +16,8 @@ namespace lue {
 
     namespace value_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            not_equal_to, detail::NotEqualTo, policy::not_equal_to::DefaultValuePolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            not_equal_to, policy::not_equal_to::DefaultValuePolicies)
         LUE_BINARY_COMPARISON_OPERATOR(!=, not_equal_to)
 
     }  // namespace value_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/pow.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/pow.hpp
new file mode 100644
index 000000000..7a5975ef3
--- /dev/null
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/pow.hpp
@@ -0,0 +1,23 @@
+#pragma once
+#include "lue/framework/algorithm/pow.hpp"
+
+
+namespace lue {
+    namespace policy::pow {
+
+        template<typename Element>
+        using DefaultValuePolicies = policy::DefaultValuePolicies<
+            DomainPolicy<Element>,
+            OutputElements<Element>,
+            InputElements<Element, Element>>;
+
+    }  // namespace policy::pow
+
+
+    namespace value_policies {
+
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            pow, policy::pow::DefaultValuePolicies)
+
+    }  // namespace value_policies
+}  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/round.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/round.hpp
index e0bf25644..64300e23f 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/round.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/round.hpp
@@ -16,13 +16,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        auto round(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::round::DefaultValuePolicies<Element>;
-
-            return round(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            round, policy::round::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/sin.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/sin.hpp
index ee2b5d7b3..bffcad024 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/sin.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/sin.hpp
@@ -16,13 +16,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        auto sin(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::sin::DefaultValuePolicies<Element>;
-
-            return sin(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            sin, policy::sin::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/sqrt.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/sqrt.hpp
index f22f94f36..5e34c8ddb 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/sqrt.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/sqrt.hpp
@@ -14,13 +14,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        auto sqrt(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::sqrt::DefaultValuePolicies<Element>;
-
-            return sqrt(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            sqrt, policy::sqrt::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/subtract.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/subtract.hpp
index 7ca2d40c6..5de6f0226 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/subtract.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/subtract.hpp
@@ -14,31 +14,31 @@ namespace lue {
 
                 static_assert(std::is_same_v<InputElement, OutputElement>);
 
-                constexpr static bool within_range(
+                constexpr static auto within_range(
                     InputElement const& argument1, InputElement const& argument2, OutputElement const& result)
+                    -> bool
                 {
                     return subtract_within_range(argument1, argument2, result);
                 }
         };
 
 
-        template<typename OutputElement, typename InputElement>
+        template<typename Element>
         using DefaultValuePolicies = policy::Policies<
-            AllValuesWithinDomain<InputElement, InputElement>,
-            OutputsPolicies<OutputPolicies<
-                DefaultOutputNoDataPolicy<OutputElement>,
-                RangePolicy<OutputElement, InputElement>>>,
+            AllValuesWithinDomain<Element, Element>,
+            OutputsPolicies<
+                OutputPolicies<DefaultOutputNoDataPolicy<Element>, RangePolicy<Element, Element>>>,
             InputsPolicies<
-                InputPolicies<DefaultInputNoDataPolicy<InputElement>>,
-                InputPolicies<DefaultInputNoDataPolicy<InputElement>>>>;
+                InputPolicies<DefaultInputNoDataPolicy<Element>>,
+                InputPolicies<DefaultInputNoDataPolicy<Element>>>>;
 
     }  // namespace policy::subtract
 
 
     namespace value_policies {
 
-        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES(
-            subtract, detail::Subtract, policy::subtract::DefaultValuePolicies)
+        LUE_BINARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            subtract, policy::subtract::DefaultValuePolicies)
         LUE_BINARY_ARITHMETIC_OPERATOR(-, subtract)
 
     }  // namespace value_policies
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/tan.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/tan.hpp
index 16cbac7d5..16e1d1a9b 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/tan.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/tan.hpp
@@ -1,6 +1,5 @@
 #pragma once
 #include "lue/framework/algorithm/tan.hpp"
-#include <cmath>  // std::isinf
 
 
 namespace lue {
@@ -28,13 +27,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename Element, Rank rank>
-        auto tan(PartitionedArray<Element, rank> const& array)
-        {
-            using Policies = policy::tan::DefaultValuePolicies<Element>;
-
-            return tan(Policies{}, array);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_SAME_OUTPUT_ELEMENT(
+            tan, policy::tan::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/valid.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/valid.hpp
index ab795a4ce..e83cce8ff 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/valid.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/valid.hpp
@@ -43,23 +43,8 @@ namespace lue {
 
     namespace value_policies {
 
-        template<typename BooleanElement, typename ExpressionElement, Rank rank>
-        auto valid(PartitionedArray<ExpressionElement, rank> const& array)
-            -> PartitionedArray<BooleanElement, rank>
-        {
-            using Policies = policy::valid::DefaultValuePolicies<BooleanElement, ExpressionElement>;
-
-            return valid<BooleanElement>(Policies{}, array);
-        }
-
-
-        template<typename BooleanElement, typename ExpressionElement>
-        auto valid(Scalar<ExpressionElement> const& scalar) -> Scalar<BooleanElement>
-        {
-            using Policies = policy::valid::DefaultValuePolicies<BooleanElement, ExpressionElement>;
-
-            return valid<BooleanElement>(Policies{}, scalar);
-        }
+        LUE_UNARY_LOCAL_OPERATION_OVERLOADS_WITHOUT_POLICIES_DIFFERENT_OUTPUT_ELEMENT(
+            valid, policy::valid::DefaultValuePolicies)
 
     }  // namespace value_policies
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/abs.cpp.in b/source/framework/algorithm/src/local_operation/abs.cpp.in
index d89f8c04e..52fa194b6 100644
--- a/source/framework/algorithm/src/local_operation/abs.cpp.in
+++ b/source/framework/algorithm/src/local_operation/abs.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_ABS(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::abs::{{ Policies }}<{{ Element }}>),
-            {{ Element }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::Abs<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/acos.cpp.in b/source/framework/algorithm/src/local_operation/acos.cpp.in
index 462ef2f48..8ad2bd9a5 100644
--- a/source/framework/algorithm/src/local_operation/acos.cpp.in
+++ b/source/framework/algorithm/src/local_operation/acos.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_ACOS(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::acos::{{ Policies }}<{{ Element }}>),
-            {{ Element }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::ACos<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/add.cpp.in b/source/framework/algorithm/src/local_operation/add.cpp.in
index 8a6ccea76..1cb7cdb30 100644
--- a/source/framework/algorithm/src/local_operation/add.cpp.in
+++ b/source/framework/algorithm/src/local_operation/add.cpp.in
@@ -6,12 +6,9 @@
 namespace lue {
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(
-            ESC(policy::add::{{ Policies }}<{{ Element }}, {{ Element }}>),
-            {{ Element }},
-            {{ Element }},
-            {{ Element }},
+            ESC(policy::add::{{ Policies }}<{{ Element }}>),
             {{ rank }},
-            ESC(detail::Add<{{ Element }}, {{ Element }}>)
+            ESC(detail::Add<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/asin.cpp.in b/source/framework/algorithm/src/local_operation/asin.cpp.in
index 91fa7a451..e34cc9b30 100644
--- a/source/framework/algorithm/src/local_operation/asin.cpp.in
+++ b/source/framework/algorithm/src/local_operation/asin.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_ASIN(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::asin::{{ Policies }}<{{ Element }}>),
-            {{ Element }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::ASin<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/atan.cpp.in b/source/framework/algorithm/src/local_operation/atan.cpp.in
index a680f32fb..0e981dea8 100644
--- a/source/framework/algorithm/src/local_operation/atan.cpp.in
+++ b/source/framework/algorithm/src/local_operation/atan.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_ATAN(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::atan::{{ Policies }}<{{ Element }}>),
-            {{ Element }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::ATan<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/cast.cpp.in b/source/framework/algorithm/src/local_operation/cast.cpp.in
index 859a20346..57e424bae 100644
--- a/source/framework/algorithm/src/local_operation/cast.cpp.in
+++ b/source/framework/algorithm/src/local_operation/cast.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_CAST(
-        ESC(policy::cast::{{ Policies }}<{{ OutputElement }}, {{ InputElement }}>),
-        {{ OutputElement }},
-        {{ InputElement }},
-        {{ rank }});
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
+            ESC(policy::cast::{{ Policies }}<{{ OutputElement }}, {{ InputElement }}>),
+            {{ rank }},
+            ESC(detail::Cast<{{ InputElement }}, {{ OutputElement }}>)
+        );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/ceil.cpp.in b/source/framework/algorithm/src/local_operation/ceil.cpp.in
index 908c0d568..97219e6b3 100644
--- a/source/framework/algorithm/src/local_operation/ceil.cpp.in
+++ b/source/framework/algorithm/src/local_operation/ceil.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_CEIL(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::ceil::{{ Policies }}<{{ Element }}>),
-            {{ Element }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::Ceil<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/close_to.cpp.in b/source/framework/algorithm/src/local_operation/close_to.cpp.in
index e59d82247..677cadbd4 100644
--- a/source/framework/algorithm/src/local_operation/close_to.cpp.in
+++ b/source/framework/algorithm/src/local_operation/close_to.cpp.in
@@ -7,9 +7,6 @@ namespace lue {
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(
             ESC(policy::close_to::{{ Policies }}<{{ BooleanElement }}, {{ ExpressionElement }}>),
-            {{ BooleanElement }},
-            {{ ExpressionElement }},
-            {{ ExpressionElement }},
             {{ rank }},
             ESC(detail::CloseTo<{{ ExpressionElement }}, {{ BooleanElement }}>)
         );
diff --git a/source/framework/algorithm/src/local_operation/cos.cpp.in b/source/framework/algorithm/src/local_operation/cos.cpp.in
index 8a99b28dc..c288f4bad 100644
--- a/source/framework/algorithm/src/local_operation/cos.cpp.in
+++ b/source/framework/algorithm/src/local_operation/cos.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_COS(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::cos::{{ Policies }}<{{ Element }}>),
-            {{ Element }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::Cos<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/divide.cpp.in b/source/framework/algorithm/src/local_operation/divide.cpp.in
index 124264de8..d2eb9be08 100644
--- a/source/framework/algorithm/src/local_operation/divide.cpp.in
+++ b/source/framework/algorithm/src/local_operation/divide.cpp.in
@@ -6,12 +6,9 @@
 namespace lue {
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(
-            ESC(policy::divide::{{ Policies }}<{{ Element }}, {{ Element }}>),
-            {{ Element }},
-            {{ Element }},
-            {{ Element }},
+            ESC(policy::divide::{{ Policies }}<{{ Element }}>),
             {{ rank }},
-            ESC(detail::Divide<{{ Element }}, {{ Element }}>)
+            ESC(detail::Divide<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/equal_to.cpp.in b/source/framework/algorithm/src/local_operation/equal_to.cpp.in
index 771d92e27..5f485e951 100644
--- a/source/framework/algorithm/src/local_operation/equal_to.cpp.in
+++ b/source/framework/algorithm/src/local_operation/equal_to.cpp.in
@@ -12,18 +12,12 @@ namespace lue {
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION_PARTITION(
             ESC(policy::equal_to::{{ Policies }}<{{ BooleanElement }}, {{ ExpressionElement }}>),
-            {{ BooleanElement }},
-            {{ ExpressionElement }},
-            {{ ExpressionElement }},
             {{ rank }},
             ESC(detail::EqualTo<{{ ExpressionElement }}, {{ BooleanElement }}>)
         );
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(
             ESC(policy::equal_to::{{ Policies }}<{{ BooleanElement }}, {{ ExpressionElement }}>),
-            {{ BooleanElement }},
-            {{ ExpressionElement }},
-            {{ ExpressionElement }},
             {{ rank }},
             ESC(detail::EqualTo<{{ ExpressionElement }}, {{ BooleanElement }}>)
         );
diff --git a/source/framework/algorithm/src/local_operation/exp.cpp.in b/source/framework/algorithm/src/local_operation/exp.cpp.in
index 4fb0c706d..fcf24a96e 100644
--- a/source/framework/algorithm/src/local_operation/exp.cpp.in
+++ b/source/framework/algorithm/src/local_operation/exp.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_EXP(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::exp::{{ Policies }}<{{ Element }}>),
-            {{ Element }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::Exp<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/floor.cpp.in b/source/framework/algorithm/src/local_operation/floor.cpp.in
index 2a2bffbbe..e23ebd773 100644
--- a/source/framework/algorithm/src/local_operation/floor.cpp.in
+++ b/source/framework/algorithm/src/local_operation/floor.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_FLOOR(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::floor::{{ Policies }}<{{ Element }}>),
-            {{ Element }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::Floor<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/greater_than.cpp.in b/source/framework/algorithm/src/local_operation/greater_than.cpp.in
index b5113bd2d..102cb1413 100644
--- a/source/framework/algorithm/src/local_operation/greater_than.cpp.in
+++ b/source/framework/algorithm/src/local_operation/greater_than.cpp.in
@@ -7,9 +7,6 @@ namespace lue {
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(
             ESC(policy::greater_than::{{ Policies }}<{{ BooleanElement }}, {{ ExpressionElement }}>),
-            {{ BooleanElement }},
-            {{ ExpressionElement }},
-            {{ ExpressionElement }},
             {{ rank }},
             ESC(detail::GreaterThan<{{ ExpressionElement }}, {{ BooleanElement }}>)
         );
diff --git a/source/framework/algorithm/src/local_operation/greater_than_equal_to.cpp.in b/source/framework/algorithm/src/local_operation/greater_than_equal_to.cpp.in
index 5704dd793..54545a491 100644
--- a/source/framework/algorithm/src/local_operation/greater_than_equal_to.cpp.in
+++ b/source/framework/algorithm/src/local_operation/greater_than_equal_to.cpp.in
@@ -7,9 +7,6 @@ namespace lue {
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(
             ESC(policy::greater_than_equal_to::{{ Policies }}<{{ BooleanElement }}, {{ ExpressionElement }}>),
-            {{ BooleanElement }},
-            {{ ExpressionElement }},
-            {{ ExpressionElement }},
             {{ rank }},
             ESC(detail::GreaterThanEqualTo<{{ ExpressionElement }}, {{ BooleanElement }}>)
         );
diff --git a/source/framework/algorithm/src/local_operation/less_than.cpp.in b/source/framework/algorithm/src/local_operation/less_than.cpp.in
index 29ca99e3b..0af696db5 100644
--- a/source/framework/algorithm/src/local_operation/less_than.cpp.in
+++ b/source/framework/algorithm/src/local_operation/less_than.cpp.in
@@ -7,9 +7,6 @@ namespace lue {
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(
             ESC(policy::less_than::{{ Policies }}<{{ BooleanElement }}, {{ ExpressionElement }}>),
-            {{ BooleanElement }},
-            {{ ExpressionElement }},
-            {{ ExpressionElement }},
             {{ rank }},
             ESC(detail::LessThan<{{ ExpressionElement }}, {{ BooleanElement }}>)
         );
diff --git a/source/framework/algorithm/src/local_operation/less_than_equal_to.cpp.in b/source/framework/algorithm/src/local_operation/less_than_equal_to.cpp.in
index f2d5972e1..c25f9317f 100644
--- a/source/framework/algorithm/src/local_operation/less_than_equal_to.cpp.in
+++ b/source/framework/algorithm/src/local_operation/less_than_equal_to.cpp.in
@@ -7,9 +7,6 @@ namespace lue {
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(
             ESC(policy::less_than_equal_to::{{ Policies }}<{{ BooleanElement }}, {{ ExpressionElement }}>),
-            {{ BooleanElement }},
-            {{ ExpressionElement }},
-            {{ ExpressionElement }},
             {{ rank }},
             ESC(detail::LessThanEqualTo<{{ ExpressionElement }}, {{ BooleanElement }}>)
         );
diff --git a/source/framework/algorithm/src/local_operation/log.cpp.in b/source/framework/algorithm/src/local_operation/log.cpp.in
index c82b74a41..d027effca 100644
--- a/source/framework/algorithm/src/local_operation/log.cpp.in
+++ b/source/framework/algorithm/src/local_operation/log.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_LOG(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::log::{{ Policies }}<{{ Element }}>),
-            {{ Element }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::Log<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/log10.cpp.in b/source/framework/algorithm/src/local_operation/log10.cpp.in
index 10c638481..c40252682 100644
--- a/source/framework/algorithm/src/local_operation/log10.cpp.in
+++ b/source/framework/algorithm/src/local_operation/log10.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_LOG10(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::log10::{{ Policies }}<{{ Element }}>),
-            {{ Element }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::Log10<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/logical_and.cpp.in b/source/framework/algorithm/src/local_operation/logical_and.cpp.in
index 5999b9546..63352ad23 100644
--- a/source/framework/algorithm/src/local_operation/logical_and.cpp.in
+++ b/source/framework/algorithm/src/local_operation/logical_and.cpp.in
@@ -7,9 +7,6 @@ namespace lue {
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(
             ESC(policy::logical_and::{{ Policies }}<{{ BooleanElement }}, {{ ExpressionElement }}>),
-            {{ BooleanElement }},
-            {{ ExpressionElement }},
-            {{ ExpressionElement }},
             {{ rank }},
             ESC(detail::LogicalAnd<{{ ExpressionElement }}, {{ BooleanElement }}>)
         );
diff --git a/source/framework/algorithm/src/local_operation/logical_exclusive_or.cpp.in b/source/framework/algorithm/src/local_operation/logical_exclusive_or.cpp.in
index 3d547179a..b9872f9d9 100644
--- a/source/framework/algorithm/src/local_operation/logical_exclusive_or.cpp.in
+++ b/source/framework/algorithm/src/local_operation/logical_exclusive_or.cpp.in
@@ -7,9 +7,6 @@ namespace lue {
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(
             ESC(policy::logical_exclusive_or::{{ Policies }}<{{ BooleanElement }}, {{ ExpressionElement }}>),
-            {{ BooleanElement }},
-            {{ ExpressionElement }},
-            {{ ExpressionElement }},
             {{ rank }},
             ESC(detail::LogicalExclusiveOr<{{ ExpressionElement }}, {{ BooleanElement }}>)
         );
diff --git a/source/framework/algorithm/src/local_operation/logical_inclusive_or.cpp.in b/source/framework/algorithm/src/local_operation/logical_inclusive_or.cpp.in
index 4f8e7c83b..1f3b1b2ea 100644
--- a/source/framework/algorithm/src/local_operation/logical_inclusive_or.cpp.in
+++ b/source/framework/algorithm/src/local_operation/logical_inclusive_or.cpp.in
@@ -7,9 +7,6 @@ namespace lue {
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(
             ESC(policy::logical_inclusive_or::{{ Policies }}<{{ BooleanElement }}, {{ ExpressionElement }}>),
-            {{ BooleanElement }},
-            {{ ExpressionElement }},
-            {{ ExpressionElement }},
             {{ rank }},
             ESC(detail::LogicalInclusiveOr<{{ ExpressionElement }}, {{ BooleanElement }}>)
         );
diff --git a/source/framework/algorithm/src/local_operation/logical_not.cpp.in b/source/framework/algorithm/src/local_operation/logical_not.cpp.in
index 1773a7624..5ac17f4d2 100644
--- a/source/framework/algorithm/src/local_operation/logical_not.cpp.in
+++ b/source/framework/algorithm/src/local_operation/logical_not.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_LOGICAL_NOT(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::logical_not::{{ Policies }}<{{ BooleanElement }}, {{ ExpressionElement }}>),
-            {{ ExpressionElement }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::LogicalNot<{{ ExpressionElement }}, {{ BooleanElement }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/multiply.cpp.in b/source/framework/algorithm/src/local_operation/multiply.cpp.in
index b36970b41..6a832f5f1 100644
--- a/source/framework/algorithm/src/local_operation/multiply.cpp.in
+++ b/source/framework/algorithm/src/local_operation/multiply.cpp.in
@@ -6,12 +6,9 @@
 namespace lue {
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(
-            ESC(policy::multiply::{{ Policies }}<{{ Element }}, {{ Element }}>),
-            {{ Element }},
-            {{ Element }},
-            {{ Element }},
+            ESC(policy::multiply::{{ Policies }}<{{ Element }}>),
             {{ rank }},
-            ESC(detail::Multiply<{{ Element }}, {{ Element }}>)
+            ESC(detail::Multiply<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/negate.cpp.in b/source/framework/algorithm/src/local_operation/negate.cpp.in
index 8d25b4cc0..a5c4b7dca 100644
--- a/source/framework/algorithm/src/local_operation/negate.cpp.in
+++ b/source/framework/algorithm/src/local_operation/negate.cpp.in
@@ -5,9 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_NEGATE(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::negate::{{ Policies }}<{{ Element }}>),
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::Negate<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/not_equal_to.cpp.in b/source/framework/algorithm/src/local_operation/not_equal_to.cpp.in
index e28ca7a6a..584301aeb 100644
--- a/source/framework/algorithm/src/local_operation/not_equal_to.cpp.in
+++ b/source/framework/algorithm/src/local_operation/not_equal_to.cpp.in
@@ -7,9 +7,6 @@ namespace lue {
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(
             ESC(policy::not_equal_to::{{ Policies }}<{{ BooleanElement }}, {{ ExpressionElement }}>),
-            {{ BooleanElement }},
-            {{ ExpressionElement }},
-            {{ ExpressionElement }},
             {{ rank }},
             ESC(detail::NotEqualTo<{{ ExpressionElement }}, {{ BooleanElement }}>)
         );
diff --git a/source/framework/algorithm/src/local_operation/pow.cpp.in b/source/framework/algorithm/src/local_operation/pow.cpp.in
index be9efe020..346ea3ac4 100644
--- a/source/framework/algorithm/src/local_operation/pow.cpp.in
+++ b/source/framework/algorithm/src/local_operation/pow.cpp.in
@@ -1,15 +1,14 @@
+#include "lue/framework/algorithm/default_policies/pow.hpp"
 #include "lue/framework/algorithm/definition/pow.hpp"
+#include "lue/framework/algorithm/value_policies/pow.hpp"
 
 
 namespace lue {
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(
-            ESC(policy::pow::{{ Policies }}<{{ Element }}, {{ Element }}>),
-            {{ Element }},
-            {{ Element }},
-            {{ Element }},
+            ESC(policy::pow::{{ Policies }}<{{ Element }}>),
             {{ rank }},
-            ESC(detail::Pow<{{ Element }}, {{ Element }}>)
+            ESC(detail::Pow<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/round.cpp.in b/source/framework/algorithm/src/local_operation/round.cpp.in
index cd47b5164..173c6479e 100644
--- a/source/framework/algorithm/src/local_operation/round.cpp.in
+++ b/source/framework/algorithm/src/local_operation/round.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_ROUND(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::round::{{ Policies }}<{{ Element }}>),
-            {{ Element }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::Round<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/sin.cpp.in b/source/framework/algorithm/src/local_operation/sin.cpp.in
index c9bf12e46..8f17151a5 100644
--- a/source/framework/algorithm/src/local_operation/sin.cpp.in
+++ b/source/framework/algorithm/src/local_operation/sin.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_SIN(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::sin::{{ Policies }}<{{ Element }}>),
-            {{ Element }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::Sin<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/sqrt.cpp.in b/source/framework/algorithm/src/local_operation/sqrt.cpp.in
index d64667a86..ddcebccb1 100644
--- a/source/framework/algorithm/src/local_operation/sqrt.cpp.in
+++ b/source/framework/algorithm/src/local_operation/sqrt.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_SQRT(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::sqrt::{{ Policies }}<{{ Element }}>),
-            {{ Element }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::Sqrt<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/subtract.cpp.in b/source/framework/algorithm/src/local_operation/subtract.cpp.in
index ada3c4d18..e9b7d4405 100644
--- a/source/framework/algorithm/src/local_operation/subtract.cpp.in
+++ b/source/framework/algorithm/src/local_operation/subtract.cpp.in
@@ -6,12 +6,9 @@
 namespace lue {
 
     LUE_INSTANTIATE_BINARY_LOCAL_OPERATION(
-            ESC(policy::subtract::{{ Policies }}<{{ Element }}, {{ Element }}>),
-            {{ Element }},
-            {{ Element }},
-            {{ Element }},
+            ESC(policy::subtract::{{ Policies }}<{{ Element }}>),
             {{ rank }},
-            ESC(detail::Subtract<{{ Element }}, {{ Element }}>)
+            ESC(detail::Subtract<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/tan.cpp.in b/source/framework/algorithm/src/local_operation/tan.cpp.in
index c7b0b16cd..0bbb5e4a9 100644
--- a/source/framework/algorithm/src/local_operation/tan.cpp.in
+++ b/source/framework/algorithm/src/local_operation/tan.cpp.in
@@ -5,10 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_TAN(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::tan::{{ Policies }}<{{ Element }}>),
-            {{ Element }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::Tan<{{ Element }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/algorithm/src/local_operation/valid.cpp.in b/source/framework/algorithm/src/local_operation/valid.cpp.in
index 3a61202e1..7a8a14b8f 100644
--- a/source/framework/algorithm/src/local_operation/valid.cpp.in
+++ b/source/framework/algorithm/src/local_operation/valid.cpp.in
@@ -5,11 +5,10 @@
 
 namespace lue {
 
-    LUE_INSTANTIATE_VALID(
+    LUE_INSTANTIATE_UNARY_LOCAL_OPERATION(
             ESC(policy::valid::{{ Policies }}<{{ BooleanElement }}, {{ ExpressionElement }}>),
-            {{ BooleanElement }},
-            {{ ExpressionElement }},
-            {{ rank }}
+            {{ rank }},
+            ESC(detail::Valid<{{ ExpressionElement }}, {{ BooleanElement }}>)
         );
 
 }  // namespace lue
diff --git a/source/framework/python/CMakeLists.txt b/source/framework/python/CMakeLists.txt
index dc23bbbe8..55a618ec6 100644
--- a/source/framework/python/CMakeLists.txt
+++ b/source/framework/python/CMakeLists.txt
@@ -26,7 +26,6 @@ file(GENERATE
 # A pybind11 SHARED library is a CMake runtime output artifact. Target properties to set/get are
 # RUNTIME_OUTPUT_DIRECTORY and RUNTIME_OUTPUT_NAME.
 add_library(lue_py_framework SHARED
-    src/algorithm/abs.cpp
     src/algorithm/accu.cpp
     src/algorithm/accu3.cpp
     src/algorithm/accu_fraction.cpp
@@ -34,33 +33,23 @@ add_library(lue_py_framework SHARED
     src/algorithm/accu_info3.cpp
     src/algorithm/accu_threshold.cpp
     src/algorithm/accu_threshold3.cpp
-    src/algorithm/acos.cpp
     src/algorithm/all.cpp
     src/algorithm/array_partition_id.cpp
     src/algorithm/aspect.cpp
-    src/algorithm/asin.cpp
-    src/algorithm/atan.cpp
     src/algorithm/atan2.cpp
-    src/algorithm/cos.cpp
     src/algorithm/d8_flow_direction.cpp
     src/algorithm/downstream.cpp
     src/algorithm/downstream_distance.cpp
-    src/algorithm/exp.cpp
     src/algorithm/inflow_count.cpp
     src/algorithm/inflow_count3.cpp
     src/algorithm/inter_partition_stream.cpp
     src/algorithm/iterate_per_element.cpp
     src/algorithm/locality_id.cpp
-    src/algorithm/log.cpp
     src/algorithm/normal.cpp
-    src/algorithm/sin.cpp
     src/algorithm/slope.cpp
-    src/algorithm/sqrt.cpp
-    src/algorithm/tan.cpp
     src/algorithm/timestamp.cpp
     src/algorithm/uniform.cpp
     src/algorithm/upstream.cpp
-    src/algorithm/valid.cpp
     src/algorithm/where.cpp
 
     src/algorithm/focal_operation.cpp
@@ -79,17 +68,24 @@ add_library(lue_py_framework SHARED
     src/algorithm/global_operation/sum.cpp
 
     src/algorithm/local_operation.cpp
+    src/algorithm/local_operation/abs.cpp
+    src/algorithm/local_operation/acos.cpp
     src/algorithm/local_operation/add.cpp
+    src/algorithm/local_operation/asin.cpp
+    src/algorithm/local_operation/atan.cpp
     src/algorithm/local_operation/cast.cpp
-    src/algorithm/local_operation/ceil.cpp
     src/algorithm/local_operation/cell_index.cpp
+    src/algorithm/local_operation/cos.cpp
     src/algorithm/local_operation/divide.cpp
     src/algorithm/local_operation/equal_to.cpp
+    src/algorithm/local_operation/ceil.cpp
+    src/algorithm/local_operation/exp.cpp
     src/algorithm/local_operation/floor.cpp
     src/algorithm/local_operation/greater_than.cpp
     src/algorithm/local_operation/greater_than_equal_to.cpp
     src/algorithm/local_operation/less_than.cpp
     src/algorithm/local_operation/less_than_equal_to.cpp
+    src/algorithm/local_operation/log.cpp
     src/algorithm/local_operation/log10.cpp
     src/algorithm/local_operation/logical_and.cpp
     src/algorithm/local_operation/logical_exclusive_or.cpp
@@ -100,8 +96,12 @@ add_library(lue_py_framework SHARED
     src/algorithm/local_operation/not_equal_to.cpp
     src/algorithm/local_operation/pow.cpp
     src/algorithm/local_operation/round.cpp
+    src/algorithm/local_operation/sin.cpp
+    src/algorithm/local_operation/sqrt.cpp
     src/algorithm/local_operation/subtract.cpp
+    src/algorithm/local_operation/tan.cpp
     src/algorithm/local_operation/unique_id.cpp
+    src/algorithm/local_operation/valid.cpp
 
     src/algorithm/routing_operation.cpp
     src/algorithm/routing_operation/decreasing_order.cpp
diff --git a/source/framework/python/doc/design.md b/source/framework/python/doc/design.md
new file mode 100644
index 000000000..3d14cb7ce
--- /dev/null
+++ b/source/framework/python/doc/design.md
@@ -0,0 +1,1 @@
+# Design
diff --git a/source/framework/python/include/lue/py/framework/algorithm/abs.hpp b/source/framework/python/include/lue/py/framework/algorithm/abs.hpp
deleted file mode 100644
index a2fdbdc31..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/abs.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-#include "lue/framework/algorithm/value_policies/abs.hpp"
-
-
-namespace lue::framework {
-
-    template<typename Element, Rank rank>
-    PartitionedArray<Element, rank> abs(PartitionedArray<Element, rank> const& array)
-    {
-        return value_policies::abs(array);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/add.hpp b/source/framework/python/include/lue/py/framework/algorithm/add.hpp
deleted file mode 100644
index 0a2833061..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/add.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-#include "lue/framework/algorithm/value_policies/add.hpp"
-
-
-namespace lue::framework {
-
-    template<typename Element, Rank rank, typename Argument1, typename Argument2>
-    auto add(Argument1 const& argument1, Argument2 const& argument2) -> PartitionedArray<Element, rank>
-    {
-        return value_policies::add(argument1, argument2);
-    }
-
-
-    template<typename Element, typename Argument1, typename Argument2>
-    auto add(Argument1 const& argument1, Argument2 const& argument2) -> Scalar<Element>
-    {
-        return value_policies::add(argument1, argument2);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/all.hpp b/source/framework/python/include/lue/py/framework/algorithm/all.hpp
deleted file mode 100644
index ee0ee1863..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/all.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-#include "lue/framework/algorithm/value_policies/all.hpp"
-
-
-namespace lue::framework {
-
-    template<typename Element, Rank rank>
-    auto all(PartitionedArray<Element, rank> const& array) -> Scalar<Element>
-    {
-        return value_policies::all(array);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/divide.hpp b/source/framework/python/include/lue/py/framework/algorithm/divide.hpp
deleted file mode 100644
index 49d86c284..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/divide.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-#include "lue/framework/algorithm/value_policies/divide.hpp"
-
-
-namespace lue::framework {
-
-    template<typename Element, Rank rank, typename Argument1, typename Argument2>
-    auto divide(Argument1 const& argument1, Argument2 const& argument2) -> PartitionedArray<Element, rank>
-    {
-        return value_policies::divide(argument1, argument2);
-    }
-
-
-    template<typename Element, typename Argument1, typename Argument2>
-    auto divide(Argument1 const& argument1, Argument2 const& argument2) -> Scalar<Element>
-    {
-        return value_policies::divide(argument1, argument2);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/equal_to.hpp b/source/framework/python/include/lue/py/framework/algorithm/equal_to.hpp
deleted file mode 100644
index 73e028f5c..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/equal_to.hpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-#include "lue/framework/algorithm/value_policies/equal_to.hpp"
-#include "lue/py/framework/core/future_traits.hpp"
-
-
-namespace lue::framework {
-
-    template<typename OutputElement, Rank rank, typename Argument1, typename Argument2>
-    auto equal_to(Argument1 const& argument1, Argument2 const& argument2)
-        -> PartitionedArray<OutputElement, rank>
-    {
-        return value_policies::equal_to(argument1, argument2);
-    }
-
-
-    template<typename OutputElement, typename Argument1, typename Argument2>
-    auto equal_to(Argument1 const& argument1, Argument2 const& argument2) -> Scalar<OutputElement>
-    {
-        return value_policies::equal_to(argument1, argument2);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/greater_than.hpp b/source/framework/python/include/lue/py/framework/algorithm/greater_than.hpp
deleted file mode 100644
index dc06343f6..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/greater_than.hpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-#include "lue/framework/algorithm/value_policies/greater_than.hpp"
-#include "lue/py/framework/core/future_traits.hpp"
-
-
-namespace lue::framework {
-
-    template<typename OutputElement, Rank rank, typename Argument1, typename Argument2>
-    auto greater_than(Argument1 const& argument1, Argument2 const& argument2)
-        -> PartitionedArray<OutputElement, rank>
-    {
-        return value_policies::greater_than(argument1, argument2);
-    }
-
-
-    template<typename OutputElement, typename Argument1, typename Argument2>
-    auto greater_than(Argument1 const& argument1, Argument2 const& argument2) -> Scalar<OutputElement>
-    {
-        return value_policies::greater_than(argument1, argument2);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/greater_than_equal_to.hpp b/source/framework/python/include/lue/py/framework/algorithm/greater_than_equal_to.hpp
deleted file mode 100644
index 9d69e6986..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/greater_than_equal_to.hpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-#include "lue/framework/algorithm/value_policies/greater_than_equal_to.hpp"
-#include "lue/py/framework/core/future_traits.hpp"
-
-
-namespace lue::framework {
-
-    template<typename OutputElement, Rank rank, typename Argument1, typename Argument2>
-    auto greater_than_equal_to(Argument1 const& argument1, Argument2 const& argument2)
-        -> PartitionedArray<OutputElement, rank>
-    {
-        return value_policies::greater_than_equal_to(argument1, argument2);
-    }
-
-
-    template<typename OutputElement, typename Argument1, typename Argument2>
-    auto greater_than_equal_to(Argument1 const& argument1, Argument2 const& argument2)
-        -> Scalar<OutputElement>
-    {
-        return value_policies::greater_than_equal_to(argument1, argument2);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/less_than.hpp b/source/framework/python/include/lue/py/framework/algorithm/less_than.hpp
deleted file mode 100644
index 92a7c50cc..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/less_than.hpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-#include "lue/framework/algorithm/value_policies/less_than.hpp"
-#include "lue/py/framework/core/future_traits.hpp"
-
-
-namespace lue::framework {
-
-    template<typename OutputElement, Rank rank, typename Argument1, typename Argument2>
-    auto less_than(Argument1 const& argument1, Argument2 const& argument2)
-        -> PartitionedArray<OutputElement, rank>
-    {
-        return value_policies::less_than(argument1, argument2);
-    }
-
-
-    template<typename OutputElement, typename Argument1, typename Argument2>
-    auto less_than(Argument1 const& argument1, Argument2 const& argument2) -> Scalar<OutputElement>
-    {
-        return value_policies::less_than(argument1, argument2);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/less_than_equal_to.hpp b/source/framework/python/include/lue/py/framework/algorithm/less_than_equal_to.hpp
deleted file mode 100644
index 44ee78fed..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/less_than_equal_to.hpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-#include "lue/framework/algorithm/value_policies/less_than_equal_to.hpp"
-#include "lue/py/framework/core/future_traits.hpp"
-
-
-namespace lue::framework {
-
-    template<typename OutputElement, Rank rank, typename Argument1, typename Argument2>
-    auto less_than_equal_to(Argument1 const& argument1, Argument2 const& argument2)
-        -> PartitionedArray<OutputElement, rank>
-    {
-        return value_policies::less_than_equal_to(argument1, argument2);
-    }
-
-
-    template<typename OutputElement, typename Argument1, typename Argument2>
-    auto less_than_equal_to(Argument1 const& argument1, Argument2 const& argument2) -> Scalar<OutputElement>
-    {
-        return value_policies::less_than_equal_to(argument1, argument2);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/logical_and.hpp b/source/framework/python/include/lue/py/framework/algorithm/logical_and.hpp
deleted file mode 100644
index dbec518b8..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/logical_and.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "lue/framework/algorithm/value_policies/logical_and.hpp"
-
-
-namespace lue::framework {
-
-    template<typename Element, Rank rank>
-    PartitionedArray<std::uint8_t, rank> logical_and(
-        PartitionedArray<Element, rank> const& argument1, PartitionedArray<Element, rank> const& argument2)
-    {
-        return value_policies::logical_and(argument1, argument2);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/logical_exclusive_or.hpp b/source/framework/python/include/lue/py/framework/algorithm/logical_exclusive_or.hpp
deleted file mode 100644
index 3aa24b46e..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/logical_exclusive_or.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "lue/framework/algorithm/value_policies/logical_exclusive_or.hpp"
-
-
-namespace lue::framework {
-
-    template<typename Element, Rank rank>
-    PartitionedArray<std::uint8_t, rank> logical_exclusive_or(
-        PartitionedArray<Element, rank> const& argument1, PartitionedArray<Element, rank> const& argument2)
-    {
-        return value_policies::logical_exclusive_or(argument1, argument2);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/logical_inclusive_or.hpp b/source/framework/python/include/lue/py/framework/algorithm/logical_inclusive_or.hpp
deleted file mode 100644
index 951f4459b..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/logical_inclusive_or.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "lue/framework/algorithm/value_policies/logical_inclusive_or.hpp"
-
-
-namespace lue::framework {
-
-    template<typename Element, Rank rank>
-    PartitionedArray<std::uint8_t, rank> logical_inclusive_or(
-        PartitionedArray<Element, rank> const& argument1, PartitionedArray<Element, rank> const& argument2)
-    {
-        return value_policies::logical_inclusive_or(argument1, argument2);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/logical_not.hpp b/source/framework/python/include/lue/py/framework/algorithm/logical_not.hpp
deleted file mode 100644
index 5cdf6dd68..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/logical_not.hpp
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "lue/framework/algorithm/value_policies/logical_not.hpp"
-
-
-namespace lue::framework {
-
-    template<typename Element, Rank rank>
-    PartitionedArray<std::uint8_t, rank> logical_not(PartitionedArray<Element, rank> const& argument)
-    {
-        return value_policies::logical_not(argument);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/multiply.hpp b/source/framework/python/include/lue/py/framework/algorithm/multiply.hpp
deleted file mode 100644
index 2de8243d2..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/multiply.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-#include "lue/framework/algorithm/value_policies/multiply.hpp"
-
-
-namespace lue::framework {
-
-    template<typename Element, Rank rank, typename Argument1, typename Argument2>
-    auto multiply(Argument1 const& argument1, Argument2 const& argument2) -> PartitionedArray<Element, rank>
-    {
-        return value_policies::multiply(argument1, argument2);
-    }
-
-
-    template<typename Element, typename Argument1, typename Argument2>
-    auto multiply(Argument1 const& argument1, Argument2 const& argument2) -> Scalar<Element>
-    {
-        return value_policies::multiply(argument1, argument2);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/negate.hpp b/source/framework/python/include/lue/py/framework/algorithm/negate.hpp
deleted file mode 100644
index 42a9790d1..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/negate.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-#include "lue/framework/algorithm/value_policies/negate.hpp"
-
-
-namespace lue::framework {
-
-    template<typename Element, Rank rank>
-    auto negate(PartitionedArray<Element, rank> const& array) -> PartitionedArray<Element, rank>
-    {
-        return value_policies::negate(array);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/not_equal_to.hpp b/source/framework/python/include/lue/py/framework/algorithm/not_equal_to.hpp
deleted file mode 100644
index 4223f99d8..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/not_equal_to.hpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-#include "lue/framework/algorithm/value_policies/not_equal_to.hpp"
-#include "lue/py/framework/core/future_traits.hpp"
-
-
-namespace lue::framework {
-
-    template<typename OutputElement, Rank rank, typename Argument1, typename Argument2>
-    auto not_equal_to(Argument1 const& argument1, Argument2 const& argument2)
-        -> PartitionedArray<OutputElement, rank>
-    {
-        return value_policies::not_equal_to(argument1, argument2);
-    }
-
-
-    template<typename OutputElement, typename Argument1, typename Argument2>
-    auto not_equal_to(Argument1 const& argument1, Argument2 const& argument2) -> Scalar<OutputElement>
-    {
-        return value_policies::not_equal_to(argument1, argument2);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/pow.hpp b/source/framework/python/include/lue/py/framework/algorithm/pow.hpp
deleted file mode 100644
index 011abd67a..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/pow.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-#include "lue/framework/algorithm/pow.hpp"
-
-
-namespace lue::framework {
-
-    template<typename Element, Rank rank, typename Argument1, typename Argument2>
-    auto pow(Argument1 const& argument1, Argument2 const& argument2) -> PartitionedArray<Element, rank>
-    {
-        return value_policies::pow(argument1, argument2);
-    }
-
-
-    template<typename Element, typename Argument1, typename Argument2>
-    auto pow(Argument1 const& argument1, Argument2 const& argument2) -> Scalar<Element>
-    {
-        return value_policies::pow(argument1, argument2);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/algorithm/subtract.hpp b/source/framework/python/include/lue/py/framework/algorithm/subtract.hpp
deleted file mode 100644
index be9d8342b..000000000
--- a/source/framework/python/include/lue/py/framework/algorithm/subtract.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-#include "lue/framework/algorithm/value_policies/subtract.hpp"
-
-
-namespace lue::framework {
-
-    template<typename Element, Rank rank, typename Argument1, typename Argument2>
-    auto subtract(Argument1 const& argument1, Argument2 const& argument2) -> PartitionedArray<Element, rank>
-    {
-        return value_policies::subtract(argument1, argument2);
-    }
-
-
-    template<typename Element, typename Argument1, typename Argument2>
-    auto subtract(Argument1 const& argument1, Argument2 const& argument2) -> Scalar<Element>
-    {
-        return value_policies::subtract(argument1, argument2);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/include/lue/py/framework/core/partitioned_array.hpp b/source/framework/python/include/lue/py/framework/core/partitioned_array.hpp
index ee2519cac..fce1b1e61 100644
--- a/source/framework/python/include/lue/py/framework/core/partitioned_array.hpp
+++ b/source/framework/python/include/lue/py/framework/core/partitioned_array.hpp
@@ -1,20 +1,20 @@
-#include "lue/py/framework/algorithm/abs.hpp"
-#include "lue/py/framework/algorithm/add.hpp"
-#include "lue/py/framework/algorithm/divide.hpp"
-#include "lue/py/framework/algorithm/equal_to.hpp"
-#include "lue/py/framework/algorithm/greater_than.hpp"
-#include "lue/py/framework/algorithm/greater_than_equal_to.hpp"
-#include "lue/py/framework/algorithm/less_than.hpp"
-#include "lue/py/framework/algorithm/less_than_equal_to.hpp"
-#include "lue/py/framework/algorithm/logical_and.hpp"
-#include "lue/py/framework/algorithm/logical_exclusive_or.hpp"
-#include "lue/py/framework/algorithm/logical_inclusive_or.hpp"
-#include "lue/py/framework/algorithm/logical_not.hpp"
-#include "lue/py/framework/algorithm/multiply.hpp"
-#include "lue/py/framework/algorithm/negate.hpp"
-#include "lue/py/framework/algorithm/not_equal_to.hpp"
-#include "lue/py/framework/algorithm/pow.hpp"
-#include "lue/py/framework/algorithm/subtract.hpp"
+#include "lue/framework/algorithm/value_policies/abs.hpp"
+#include "lue/framework/algorithm/value_policies/add.hpp"
+#include "lue/framework/algorithm/value_policies/divide.hpp"
+#include "lue/framework/algorithm/value_policies/equal_to.hpp"
+#include "lue/framework/algorithm/value_policies/greater_than.hpp"
+#include "lue/framework/algorithm/value_policies/greater_than_equal_to.hpp"
+#include "lue/framework/algorithm/value_policies/less_than.hpp"
+#include "lue/framework/algorithm/value_policies/less_than_equal_to.hpp"
+#include "lue/framework/algorithm/value_policies/logical_and.hpp"
+#include "lue/framework/algorithm/value_policies/logical_exclusive_or.hpp"
+#include "lue/framework/algorithm/value_policies/logical_inclusive_or.hpp"
+#include "lue/framework/algorithm/value_policies/logical_not.hpp"
+#include "lue/framework/algorithm/value_policies/multiply.hpp"
+#include "lue/framework/algorithm/value_policies/negate.hpp"
+#include "lue/framework/algorithm/value_policies/not_equal_to.hpp"
+#include "lue/framework/algorithm/value_policies/pow.hpp"
+#include "lue/framework/algorithm/value_policies/subtract.hpp"
 #include "lue/py/framework/stream.hpp"
 #include <pybind11/pybind11.h>
 
@@ -22,7 +22,7 @@
 namespace lue::framework {
 
     template<typename Element, Rank rank>
-    static std::string formal_string_representation(PartitionedArray<Element, rank> const& array)
+    static auto formal_string_representation(PartitionedArray<Element, rank> const& array) -> std::string
     {
         return fmt::format(
             "PartitionedArray<{}, {}>{{shape={}, shape_in_partitions={}}}",
@@ -34,7 +34,7 @@ namespace lue::framework {
 
 
     template<typename Element, Rank rank>
-    static std::string informal_string_representation(PartitionedArray<Element, rank> const& array)
+    static auto informal_string_representation(PartitionedArray<Element, rank> const& array) -> std::string
     {
         return formal_string_representation(array);
     }
@@ -43,10 +43,12 @@ namespace lue::framework {
     template<typename Element, Rank rank>
     void bind_partitioned_array(pybind11::module& module)
     {
-        namespace lfr = lue::framework;
+        // https://docs.python.org/3/reference/datamodel.html
+        using namespace lue::value_policies;
 
         using Array = PartitionedArray<Element, rank>;
         using Scalar = Scalar<Element>;
+        using BooleanElement = std::uint8_t;
 
         auto class_ =
             pybind11::class_<Array>(
@@ -115,102 +117,102 @@ namespace lue::framework {
                 .def(
                     "__lt__",
                     [](Array const& argument1, Array const& argument2)
-                    { return lfr::less_than<std::uint8_t, rank>(argument1, argument2); },
+                    { return less_than<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__lt__",
                     [](Array const& argument1, Element const argument2)
-                    { return lfr::less_than<std::uint8_t, rank>(argument1, argument2); },
+                    { return less_than<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__lt__",
                     [](Array const& argument1, Scalar const& argument2)
-                    { return lfr::less_than<std::uint8_t, rank>(argument1, argument2); },
+                    { return less_than<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
 
                 // a <= b
                 .def(
                     "__le__",
                     [](Array const& argument1, Array const& argument2)
-                    { return lfr::less_than_equal_to<std::uint8_t, rank>(argument1, argument2); },
+                    { return less_than_equal_to<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__le__",
                     [](Array const& argument1, Element const argument2)
-                    { return lfr::less_than_equal_to<std::uint8_t, rank>(argument1, argument2); },
+                    { return less_than_equal_to<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__le__",
                     [](Array const& argument1, Scalar const& argument2)
-                    { return lfr::less_than_equal_to<std::uint8_t, rank>(argument1, argument2); },
+                    { return less_than_equal_to<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
 
                 // a == b
                 .def(
                     "__eq__",
                     [](Array const& argument1, Array const& argument2)
-                    { return lfr::equal_to<std::uint8_t, rank>(argument1, argument2); },
+                    { return equal_to<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__eq__",
                     [](Array const& argument1, Element const argument2)
-                    { return lfr::equal_to<std::uint8_t, rank>(argument1, argument2); },
+                    { return equal_to<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__eq__",
                     [](Array const& argument1, Scalar const& argument2)
-                    { return lfr::equal_to<std::uint8_t, rank>(argument1, argument2); },
+                    { return equal_to<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
 
                 // a != b
                 .def(
                     "__ne__",
                     [](Array const& argument1, Array const& argument2)
-                    { return lfr::not_equal_to<std::uint8_t, rank>(argument1, argument2); },
+                    { return not_equal_to<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__ne__",
                     [](Array const& argument1, Element const argument2)
-                    { return lfr::not_equal_to<std::uint8_t, rank>(argument1, argument2); },
+                    { return not_equal_to<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__ne__",
                     [](Array const& argument1, Scalar const& argument2)
-                    { return lfr::not_equal_to<std::uint8_t, rank>(argument1, argument2); },
+                    { return not_equal_to<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
 
                 // a > b
                 .def(
                     "__gt__",
                     [](Array const& argument1, Array const& argument2)
-                    { return lfr::greater_than<std::uint8_t, rank>(argument1, argument2); },
+                    { return greater_than<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__gt__",
                     [](Array const& argument1, Element const argument2)
-                    { return lfr::greater_than<std::uint8_t, rank>(argument1, argument2); },
+                    { return greater_than<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__gt__",
                     [](Array const& argument1, Scalar const& argument2)
-                    { return lfr::greater_than<std::uint8_t, rank>(argument1, argument2); },
+                    { return greater_than<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
 
                 // a >= b
                 .def(
                     "__ge__",
                     [](Array const& argument1, Array const& argument2)
-                    { return lfr::greater_than_equal_to<std::uint8_t, rank>(argument1, argument2); },
+                    { return greater_than_equal_to<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__ge__",
                     [](Array const& argument1, Element const argument2)
-                    { return lfr::greater_than_equal_to<std::uint8_t, rank>(argument1, argument2); },
+                    { return greater_than_equal_to<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__ge__",
                     [](Array const& argument1, Scalar const& argument2)
-                    { return lfr::greater_than_equal_to<std::uint8_t, rank>(argument1, argument2); },
+                    { return greater_than_equal_to<BooleanElement>(argument1, argument2); },
                     pybind11::is_operator())
 
             ;
@@ -220,71 +222,61 @@ namespace lue::framework {
         class_
             .def(
                 "__add__",
-                [](Array const& argument1, Array const& argument2)
-                { return lfr::add<ElementT<Array>, rank>(argument1, argument2); },
+                [](Array const& argument1, Array const& argument2) { return add(argument1, argument2); },
                 pybind11::is_operator())
             .def(
                 "__add__",
-                [](Array const& argument1, Element const argument2)
-                { return lfr::add<ElementT<Array>, rank>(argument1, argument2); },
+                [](Array const& argument1, Element const argument2) { return add(argument1, argument2); },
                 pybind11::is_operator())
             .def(
                 "__add__",
-                [](Array const& argument1, Scalar const& argument2)
-                { return lfr::add<ElementT<Array>, rank>(argument1, argument2); },
+                [](Array const& argument1, Scalar const& argument2) { return add(argument1, argument2); },
                 pybind11::is_operator())
             .def(
                 "__radd__",
-                [](Array const& argument2, Element const argument1)
-                { return lfr::add<ElementT<Array>, rank>(argument1, argument2); },
+                [](Array const& argument2, Element const argument1) { return add(argument1, argument2); },
                 pybind11::is_operator())
             .def(
                 "__radd__",
-                [](Array const& argument2, Scalar const& argument1)
-                { return lfr::add<ElementT<Array>, rank>(argument1, argument2); },
+                [](Array const& argument2, Scalar const& argument1) { return add(argument1, argument2); },
                 pybind11::is_operator());
 
         // a - b, b - a, a -= b
         class_
             .def(
                 "__sub__",
-                [](Array const& argument1, Array const& argument2)
-                { return lfr::subtract<ElementT<Array>, rank>(argument1, argument2); },
+                [](Array const& argument1, Array const& argument2) { return subtract(argument1, argument2); },
                 pybind11::is_operator())
             .def(
                 "__sub__",
                 [](Array const& argument1, Element const argument2)
-                { return lfr::subtract<ElementT<Array>, rank>(argument1, argument2); },
+                { return subtract(argument1, argument2); },
                 pybind11::is_operator())
             .def(
                 "__sub__",
                 [](Array const& argument1, Scalar const& argument2)
-                { return lfr::subtract<ElementT<Array>, rank>(argument1, argument2); },
+                { return subtract(argument1, argument2); },
                 pybind11::is_operator())
             .def(
                 "__rsub__",
                 [](Array const& argument2, Element const argument1)
-                { return lfr::subtract<ElementT<Array>, rank>(argument1, argument2); },
+                { return subtract(argument1, argument2); },
                 pybind11::is_operator())
             .def(
                 "__rsub__",
                 [](Array const& argument2, Scalar const& argument1)
-                { return lfr::subtract<ElementT<Array>, rank>(argument1, argument2); },
+                { return subtract(argument1, argument2); },
                 pybind11::is_operator());
 
         if constexpr (std::is_signed_v<Element> || std::is_floating_point_v<Element>)
         {
             // abs(a)
             class_.def(
-                "__abs__",
-                [](Array const& argument) { return lfr::abs<ElementT<Array>, rank>(argument); },
-                pybind11::is_operator());
+                "__abs__", [](Array const& self) { return abs(self); }, pybind11::is_operator());
 
             // -a
             class_.def(
-                "__neg__",
-                [](Array const& argument) { return lfr::negate<ElementT<Array>, rank>(argument); },
-                pybind11::is_operator());
+                "__neg__", [](Array const& self) { return negate(self); }, pybind11::is_operator());
         }
 
         if constexpr (std::is_integral_v<Element>)
@@ -293,27 +285,27 @@ namespace lue::framework {
             class_.def(
                 "__or__",
                 [](Array const& argument1, Array const& argument2)
-                { return lfr::logical_inclusive_or<ElementT<Array>, rank>(argument1, argument2); },
+                { return logical_inclusive_or<BooleanElement>(argument1, argument2); },
                 pybind11::is_operator());
 
             // a ^ b
             class_.def(
                 "__xor__",
                 [](Array const& argument1, Array const& argument2)
-                { return lfr::logical_exclusive_or<ElementT<Array>, rank>(argument1, argument2); },
+                { return logical_exclusive_or<BooleanElement>(argument1, argument2); },
                 pybind11::is_operator());
 
             // a & b
             class_.def(
                 "__and__",
                 [](Array const& argument1, Array const& argument2)
-                { return lfr::logical_and<ElementT<Array>, rank>(argument1, argument2); },
+                { return logical_and<BooleanElement>(argument1, argument2); },
                 pybind11::is_operator());
 
             // ~a
             class_.def(
                 "__invert__",
-                [](Array const& argument) { return lfr::logical_not<ElementT<Array>, rank>(argument); },
+                [](Array const& self) { return logical_not<BooleanElement>(self); },
                 pybind11::is_operator());
         }
 
@@ -324,27 +316,27 @@ namespace lue::framework {
                 .def(
                     "__mul__",
                     [](Array const& argument1, Array const& argument2)
-                    { return lfr::multiply<ElementT<Array>, rank>(argument1, argument2); },
+                    { return multiply(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__mul__",
                     [](Array const& argument1, Element const argument2)
-                    { return lfr::multiply<ElementT<Array>, rank>(argument1, argument2); },
+                    { return multiply(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__mul__",
                     [](Array const& argument1, Scalar const& argument2)
-                    { return lfr::multiply<ElementT<Array>, rank>(argument1, argument2); },
+                    { return multiply(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__rmul__",
                     [](Array const& argument2, Element const argument1)
-                    { return lfr::multiply<ElementT<Array>, rank>(argument1, argument2); },
+                    { return multiply(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__rmul__",
                     [](Array const& argument2, Scalar const& argument1)
-                    { return lfr::multiply<ElementT<Array>, rank>(argument1, argument2); },
+                    { return multiply(argument1, argument2); },
                     pybind11::is_operator());
 
             // a / b, b / a, a /= b
@@ -352,55 +344,50 @@ namespace lue::framework {
                 .def(
                     "__truediv__",
                     [](Array const& argument1, Array const& argument2)
-                    { return lfr::divide<ElementT<Array>, rank>(argument1, argument2); },
+                    { return divide(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__truediv__",
                     [](Array const& argument1, Element const argument2)
-                    { return lfr::divide<ElementT<Array>, rank>(argument1, argument2); },
+                    { return divide(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__truediv__",
                     [](Array const& argument1, Scalar const& argument2)
-                    { return lfr::divide<ElementT<Array>, rank>(argument1, argument2); },
+                    { return divide(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__rtruediv__",
                     [](Array const& argument2, Element const argument1)
-                    { return lfr::divide<ElementT<Array>, rank>(argument1, argument2); },
+                    { return divide(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__rtruediv__",
                     [](Array const& argument2, Scalar const& argument1)
-                    { return lfr::divide<ElementT<Array>, rank>(argument1, argument2); },
+                    { return divide(argument1, argument2); },
                     pybind11::is_operator());
 
             // a ** b, b ** a, a **= b
             class_
                 .def(
                     "__pow__",
-                    [](Array const& argument1, Array const& argument2)
-                    { return lfr::pow<ElementT<Array>, rank>(argument1, argument2); },
+                    [](Array const& argument1, Array const& argument2) { return pow(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__pow__",
-                    [](Array const& argument1, Element const argument2)
-                    { return lfr::pow<ElementT<Array>, rank>(argument1, argument2); },
+                    [](Array const& argument1, Element const argument2) { return pow(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__pow__",
-                    [](Array const& argument1, Scalar const& argument2)
-                    { return lfr::pow<ElementT<Array>, rank>(argument1, argument2); },
+                    [](Array const& argument1, Scalar const& argument2) { return pow(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__rpow__",
-                    [](Array const& argument2, Element const argument1)
-                    { return lfr::pow<ElementT<Array>, rank>(argument1, argument2); },
+                    [](Array const& argument2, Element const argument1) { return pow(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__rpow__",
-                    [](Array const& argument2, Scalar const& argument1)
-                    { return lfr::pow<ElementT<Array>, rank>(argument1, argument2); },
+                    [](Array const& argument2, Scalar const& argument1) { return pow(argument1, argument2); },
                     pybind11::is_operator());
         }
     }
diff --git a/source/framework/python/include/lue/py/framework/core/scalar.hpp b/source/framework/python/include/lue/py/framework/core/scalar.hpp
index 51bfe168b..e151beb18 100644
--- a/source/framework/python/include/lue/py/framework/core/scalar.hpp
+++ b/source/framework/python/include/lue/py/framework/core/scalar.hpp
@@ -1,6 +1,6 @@
 // #include "lue/py/framework/algorithm/abs.hpp"
-#include "lue/py/framework/algorithm/add.hpp"
-#include "lue/py/framework/algorithm/divide.hpp"
+#include "lue/framework/algorithm/value_policies/add.hpp"
+#include "lue/framework/algorithm/value_policies/divide.hpp"
 // #include "lue/py/framework/algorithm/equal_to.hpp"
 // #include "lue/py/framework/algorithm/greater_than.hpp"
 // #include "lue/py/framework/algorithm/greater_than_equal_to.hpp"
@@ -10,11 +10,11 @@
 // #include "lue/py/framework/algorithm/logical_exclusive_or.hpp"
 // #include "lue/py/framework/algorithm/logical_inclusive_or.hpp"
 // #include "lue/py/framework/algorithm/logical_not.hpp"
-#include "lue/py/framework/algorithm/multiply.hpp"
+#include "lue/framework/algorithm/value_policies/multiply.hpp"
 // #include "lue/py/framework/algorithm/negate.hpp"
 // #include "lue/py/framework/algorithm/not_equal_to.hpp"
-#include "lue/py/framework/algorithm/pow.hpp"
-#include "lue/py/framework/algorithm/subtract.hpp"
+#include "lue/framework/algorithm/value_policies/pow.hpp"
+#include "lue/framework/algorithm/value_policies/subtract.hpp"
 #include "lue/py/framework/stream.hpp"
 #include <pybind11/pybind11.h>
 
@@ -138,8 +138,7 @@ namespace lue::framework {
     template<typename Element>
     void bind_scalar(pybind11::module& module)
     {
-        namespace lfr = lue::framework;
-
+        using namespace lue::value_policies;
         using Scalar = lue::Scalar<Element>;
         using Value = Element;
 
@@ -300,28 +299,15 @@ namespace lue::framework {
         class_
             .def(
                 "__add__",
-                [](Scalar const& argument1, Scalar const& argument2)
-                { return lfr::add<ElementT<Scalar>>(argument1, argument2); },
+                [](Scalar const& argument1, Scalar const& argument2) { return add(argument1, argument2); },
                 pybind11::is_operator())
             .def(
                 "__add__",
-                [](Scalar const& argument1, Element const argument2)
-                { return lfr::add<ElementT<Scalar>>(argument1, argument2); },
-                pybind11::is_operator())
-            .def(
-                "__add__",
-                [](Scalar const& argument1, Value const& argument2)
-                { return lfr::add<ElementT<Scalar>>(argument1, argument2); },
+                [](Scalar const& argument1, Value const& argument2) { return add(argument1, argument2); },
                 pybind11::is_operator())
             .def(
                 "__radd__",
-                [](Scalar const& argument2, Element const argument1)
-                { return lfr::add<ElementT<Scalar>>(argument1, argument2); },
-                pybind11::is_operator())
-            .def(
-                "__radd__",
-                [](Scalar const& argument2, Value const& argument1)
-                { return lfr::add<ElementT<Scalar>>(argument1, argument2); },
+                [](Scalar const& argument2, Value const& argument1) { return add(argument1, argument2); },
                 pybind11::is_operator());
 
         // a - b, b - a, a -= b
@@ -329,27 +315,27 @@ namespace lue::framework {
             .def(
                 "__sub__",
                 [](Scalar const& argument1, Scalar const& argument2)
-                { return lfr::subtract<ElementT<Scalar>>(argument1, argument2); },
+                { return subtract(argument1, argument2); },
                 pybind11::is_operator())
             .def(
                 "__sub__",
                 [](Scalar const& argument1, Element const argument2)
-                { return lfr::subtract<ElementT<Scalar>>(argument1, argument2); },
+                { return subtract(argument1, argument2); },
                 pybind11::is_operator())
             .def(
                 "__sub__",
                 [](Scalar const& argument1, Value const& argument2)
-                { return lfr::subtract<ElementT<Scalar>>(argument1, argument2); },
+                { return subtract(argument1, argument2); },
                 pybind11::is_operator())
             .def(
                 "__rsub__",
                 [](Scalar const& argument2, Element const argument1)
-                { return lfr::subtract<ElementT<Scalar>>(argument1, argument2); },
+                { return subtract(argument1, argument2); },
                 pybind11::is_operator())
             .def(
                 "__rsub__",
                 [](Scalar const& argument2, Value const& argument1)
-                { return lfr::subtract<ElementT<Scalar>>(argument1, argument2); },
+                { return subtract(argument1, argument2); },
                 pybind11::is_operator());
 
 
@@ -405,27 +391,27 @@ namespace lue::framework {
                 .def(
                     "__mul__",
                     [](Scalar const& argument1, Scalar const& argument2)
-                    { return lfr::multiply<ElementT<Scalar>>(argument1, argument2); },
+                    { return multiply(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__mul__",
                     [](Scalar const& argument1, Element const argument2)
-                    { return lfr::multiply<ElementT<Scalar>>(argument1, argument2); },
+                    { return multiply(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__mul__",
                     [](Scalar const& argument1, Value const& argument2)
-                    { return lfr::multiply<ElementT<Scalar>>(argument1, argument2); },
+                    { return multiply(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__rmul__",
                     [](Scalar const& argument2, Element const argument1)
-                    { return lfr::multiply<ElementT<Scalar>>(argument1, argument2); },
+                    { return multiply(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__rmul__",
                     [](Scalar const& argument2, Value const& argument1)
-                    { return lfr::multiply<ElementT<Scalar>>(argument1, argument2); },
+                    { return multiply(argument1, argument2); },
                     pybind11::is_operator());
 
             // a / b, b / a, a /= b
@@ -433,27 +419,27 @@ namespace lue::framework {
                 .def(
                     "__truediv__",
                     [](Scalar const& argument1, Scalar const& argument2)
-                    { return lfr::divide<ElementT<Scalar>>(argument1, argument2); },
+                    { return divide(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__truediv__",
                     [](Scalar const& argument1, Element const argument2)
-                    { return lfr::divide<ElementT<Scalar>>(argument1, argument2); },
+                    { return divide(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__truediv__",
                     [](Scalar const& argument1, Value const& argument2)
-                    { return lfr::divide<ElementT<Scalar>>(argument1, argument2); },
+                    { return divide(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__rtruediv__",
                     [](Scalar const& argument2, Element const argument1)
-                    { return lfr::divide<ElementT<Scalar>>(argument1, argument2); },
+                    { return divide(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__rtruediv__",
                     [](Scalar const& argument2, Value const& argument1)
-                    { return lfr::divide<ElementT<Scalar>>(argument1, argument2); },
+                    { return divide(argument1, argument2); },
                     pybind11::is_operator());
 
             // a ** b, b ** a, a **= b
@@ -461,27 +447,25 @@ namespace lue::framework {
                 .def(
                     "__pow__",
                     [](Scalar const& argument1, Scalar const& argument2)
-                    { return lfr::pow<ElementT<Scalar>>(argument1, argument2); },
+                    { return pow(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__pow__",
                     [](Scalar const& argument1, Element const argument2)
-                    { return lfr::pow<ElementT<Scalar>>(argument1, argument2); },
+                    { return pow(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__pow__",
-                    [](Scalar const& argument1, Value const& argument2)
-                    { return lfr::pow<ElementT<Scalar>>(argument1, argument2); },
+                    [](Scalar const& argument1, Value const& argument2) { return pow(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__rpow__",
                     [](Scalar const& argument2, Element const argument1)
-                    { return lfr::pow<ElementT<Scalar>>(argument1, argument2); },
+                    { return pow(argument1, argument2); },
                     pybind11::is_operator())
                 .def(
                     "__rpow__",
-                    [](Scalar const& argument2, Value const& argument1)
-                    { return lfr::pow<ElementT<Scalar>>(argument1, argument2); },
+                    [](Scalar const& argument2, Value const& argument1) { return pow(argument1, argument2); },
                     pybind11::is_operator());
         }
 
diff --git a/source/framework/python/src/algorithm/abs.cpp b/source/framework/python/src/algorithm/abs.cpp
deleted file mode 100644
index a282599df..000000000
--- a/source/framework/python/src/algorithm/abs.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include "lue/py/framework/algorithm/abs.hpp"
-#include <pybind11/pybind11.h>
-
-
-namespace lue::framework {
-
-    void bind_abs(pybind11::module& module)
-    {
-        module.def("abs", abs<std::int32_t, 2>);
-        module.def("abs", abs<std::int64_t, 2>);
-        module.def("abs", abs<float, 2>);
-        module.def("abs", abs<double, 2>);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/acos.cpp b/source/framework/python/src/algorithm/acos.cpp
deleted file mode 100644
index e49a33feb..000000000
--- a/source/framework/python/src/algorithm/acos.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "lue/framework/algorithm/value_policies/acos.hpp"
-#include <pybind11/pybind11.h>
-
-
-namespace lue::framework {
-    namespace {
-
-        template<typename Element, Rank rank>
-        PartitionedArray<Element, rank> acos(PartitionedArray<Element, rank> const& array)
-        {
-            return value_policies::acos(array);
-        }
-
-    }  // Anonymous namespace
-
-
-    void bind_acos(pybind11::module& module)
-    {
-        module.def("acos", acos<float, 2>);
-        module.def("acos", acos<double, 2>);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/all.cpp b/source/framework/python/src/algorithm/all.cpp
index 10e65c7f0..174241bf2 100644
--- a/source/framework/python/src/algorithm/all.cpp
+++ b/source/framework/python/src/algorithm/all.cpp
@@ -1,22 +1,32 @@
-#include "lue/py/framework/algorithm/all.hpp"
+#include "lue/framework/algorithm/value_policies/all.hpp"
 #include <pybind11/pybind11.h>
 
 
 namespace lue::framework {
+    namespace {
 
-#define LUE_ALL_OVERLOADS(type, rank) module.def("all", all<type, rank>);
+        template<typename Element>
+        constexpr void define_all_overloads(pybind11::module& module)
+        {
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+
+            module.def("all", [](Array const& array) { return all(array); });
+        }
+
+    }  // Anonymous namespace
 
 
     void bind_all(pybind11::module& module)
     {
-        // TODO How to document these?
-        LUE_ALL_OVERLOADS(std::uint8_t, 2)
-        LUE_ALL_OVERLOADS(std::uint32_t, 2)
-        LUE_ALL_OVERLOADS(std::uint64_t, 2)
-        LUE_ALL_OVERLOADS(std::int32_t, 2)
-        LUE_ALL_OVERLOADS(std::int64_t, 2)
-        LUE_ALL_OVERLOADS(float, 2)
-        LUE_ALL_OVERLOADS(double, 2)
+        define_all_overloads<std::uint8_t>(module);
+        define_all_overloads<std::int32_t>(module);
+        define_all_overloads<std::uint32_t>(module);
+        define_all_overloads<std::int64_t>(module);
+        define_all_overloads<std::uint64_t>(module);
+        define_all_overloads<float>(module);
+        define_all_overloads<double>(module);
     }
 
 }  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/asin.cpp b/source/framework/python/src/algorithm/asin.cpp
deleted file mode 100644
index 8514122ca..000000000
--- a/source/framework/python/src/algorithm/asin.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "lue/framework/algorithm/value_policies/asin.hpp"
-#include <pybind11/pybind11.h>
-
-
-namespace lue::framework {
-    namespace {
-
-        template<typename Element, Rank rank>
-        PartitionedArray<Element, rank> asin(PartitionedArray<Element, rank> const& array)
-        {
-            return value_policies::asin(array);
-        }
-
-    }  // Anonymous namespace
-
-
-    void bind_asin(pybind11::module& module)
-    {
-        module.def("asin", asin<float, 2>);
-        module.def("asin", asin<double, 2>);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/atan.cpp b/source/framework/python/src/algorithm/atan.cpp
deleted file mode 100644
index e445e96c2..000000000
--- a/source/framework/python/src/algorithm/atan.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "lue/framework/algorithm/value_policies/atan.hpp"
-#include <pybind11/pybind11.h>
-
-
-namespace lue::framework {
-    namespace {
-
-        template<typename Element, Rank rank>
-        PartitionedArray<Element, rank> atan(PartitionedArray<Element, rank> const& array)
-        {
-            return value_policies::atan(array);
-        }
-
-    }  // Anonymous namespace
-
-
-    void bind_atan(pybind11::module& module)
-    {
-        module.def("atan", atan<float, 2>);
-        module.def("atan", atan<double, 2>);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/cos.cpp b/source/framework/python/src/algorithm/cos.cpp
deleted file mode 100644
index 7061ac144..000000000
--- a/source/framework/python/src/algorithm/cos.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "lue/framework/algorithm/value_policies/cos.hpp"
-#include <pybind11/pybind11.h>
-
-
-namespace lue::framework {
-    namespace {
-
-        template<typename Element, Rank rank>
-        PartitionedArray<Element, rank> cos(PartitionedArray<Element, rank> const& array)
-        {
-            return value_policies::cos(array);
-        }
-
-    }  // Anonymous namespace
-
-
-    void bind_cos(pybind11::module& module)
-    {
-        module.def("cos", cos<float, 2>);
-        module.def("cos", cos<double, 2>);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/exp.cpp b/source/framework/python/src/algorithm/exp.cpp
deleted file mode 100644
index f20f95d08..000000000
--- a/source/framework/python/src/algorithm/exp.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "lue/framework/algorithm/value_policies/exp.hpp"
-#include <pybind11/pybind11.h>
-
-
-namespace lue::framework {
-    namespace {
-
-        template<typename Element, Rank rank>
-        PartitionedArray<Element, rank> exp(PartitionedArray<Element, rank> const& array)
-        {
-            return value_policies::exp(array);
-        }
-
-    }  // Anonymous namespace
-
-
-    void bind_exp(pybind11::module& module)
-    {
-        module.def("exp", exp<float, 2>);
-        module.def("exp", exp<double, 2>);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/abs.cpp b/source/framework/python/src/algorithm/local_operation/abs.cpp
new file mode 100644
index 000000000..065916b60
--- /dev/null
+++ b/source/framework/python/src/algorithm/local_operation/abs.cpp
@@ -0,0 +1,32 @@
+#include "lue/framework/algorithm/value_policies/abs.hpp"
+#include <pybind11/pybind11.h>
+
+
+namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_abs_overloads(pybind11::module& module)
+        {
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def("abs", [](Array const& array) { return abs(array); });
+            module.def("abs", [](Scalar const& scalar) { return abs(scalar); });
+            module.def("abs", [](Value const value) { return abs(value); });
+        }
+
+    }  // Anonymous namespace
+
+    void bind_abs(pybind11::module& module)
+    {
+        define_abs_overloads<std::int32_t>(module);
+        define_abs_overloads<std::int64_t>(module);
+        define_abs_overloads<float>(module);
+        define_abs_overloads<double>(module);
+    }
+
+}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/acos.cpp b/source/framework/python/src/algorithm/local_operation/acos.cpp
new file mode 100644
index 000000000..6ecfd2304
--- /dev/null
+++ b/source/framework/python/src/algorithm/local_operation/acos.cpp
@@ -0,0 +1,31 @@
+#include "lue/framework/algorithm/value_policies/acos.hpp"
+#include <pybind11/pybind11.h>
+
+
+namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_acos_overloads(pybind11::module& module)
+        {
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def("acos", [](Array const& array) { return acos(array); });
+            module.def("acos", [](Scalar const& scalar) { return acos(scalar); });
+            module.def("acos", [](Value const value) { return acos(value); });
+        }
+
+    }  // Anonymous namespace
+
+
+    void bind_acos(pybind11::module& module)
+    {
+        define_acos_overloads<float>(module);
+        define_acos_overloads<double>(module);
+    }
+
+}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/add.cpp b/source/framework/python/src/algorithm/local_operation/add.cpp
index 58cd45895..96181ba74 100644
--- a/source/framework/python/src/algorithm/local_operation/add.cpp
+++ b/source/framework/python/src/algorithm/local_operation/add.cpp
@@ -1,4 +1,4 @@
-#include "lue/py/framework/algorithm/add.hpp"
+#include "lue/framework/algorithm/value_policies/add.hpp"
 #include <pybind11/pybind11.h>
 
 
@@ -8,18 +8,25 @@ namespace lue::framework {
         template<typename Element>
         constexpr void define_add_overloads(pybind11::module& module)
         {
+            using namespace lue::value_policies;
             Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
 
+            module.def("add", [](Array const& array1, Array const& array2) { return add(array1, array2); });
+            module.def("add", [](Array const& array, Scalar const& scalar) { return add(array, scalar); });
+            module.def("add", [](Array const& array, Value const value) { return add(array, value); });
+
+            module.def("add", [](Scalar const& scalar, Array const& array) { return add(scalar, array); });
             module.def(
-                "add", add<Element, rank, PartitionedArray<Element, rank>, PartitionedArray<Element, rank>>);
-            module.def("add", add<Element, rank, PartitionedArray<Element, rank>, Scalar<Element>>);
-            module.def("add", add<Element, rank, PartitionedArray<Element, rank>, Element>);
+                "add", [](Scalar const& scalar1, Scalar const& scalar2) { return add(scalar1, scalar2); });
+            module.def("add", [](Scalar const& scalar, Value const value) { return add(scalar, value); });
 
-            module.def("add", add<Element, rank, Scalar<Element>, PartitionedArray<Element, rank>>);
-            module.def("add", add<Element, rank, Element, PartitionedArray<Element, rank>>);
+            module.def("add", [](Value const value, Array const& array) { return add(value, array); });
+            module.def("add", [](Value const value, Scalar const& scalar) { return add(value, scalar); });
 
-            module.def("add", add<Element, Scalar<Element>, Element>);
-            module.def("add", add<Element, Element, Scalar<Element>>);
+            module.def("add", [](Value const value1, Value const value2) { return add(value1, value2); });
         }
 
     }  // Anonymous namespace
diff --git a/source/framework/python/src/algorithm/local_operation/asin.cpp b/source/framework/python/src/algorithm/local_operation/asin.cpp
new file mode 100644
index 000000000..c268dfca4
--- /dev/null
+++ b/source/framework/python/src/algorithm/local_operation/asin.cpp
@@ -0,0 +1,31 @@
+#include "lue/framework/algorithm/value_policies/asin.hpp"
+#include <pybind11/pybind11.h>
+
+
+namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_asin_overloads(pybind11::module& module)
+        {
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def("asin", [](Array const& array) { return asin(array); });
+            module.def("asin", [](Scalar const& scalar) { return asin(scalar); });
+            module.def("asin", [](Value const value) { return asin(value); });
+        }
+
+    }  // Anonymous namespace
+
+
+    void bind_asin(pybind11::module& module)
+    {
+        define_asin_overloads<float>(module);
+        define_asin_overloads<double>(module);
+    }
+
+}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/atan.cpp b/source/framework/python/src/algorithm/local_operation/atan.cpp
new file mode 100644
index 000000000..5d61cf876
--- /dev/null
+++ b/source/framework/python/src/algorithm/local_operation/atan.cpp
@@ -0,0 +1,31 @@
+#include "lue/framework/algorithm/value_policies/atan.hpp"
+#include <pybind11/pybind11.h>
+
+
+namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_atan_overloads(pybind11::module& module)
+        {
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def("atan", [](Array const& array) { return atan(array); });
+            module.def("atan", [](Scalar const& scalar) { return atan(scalar); });
+            module.def("atan", [](Value const value) { return atan(value); });
+        }
+
+    }  // Anonymous namespace
+
+
+    void bind_atan(pybind11::module& module)
+    {
+        define_atan_overloads<float>(module);
+        define_atan_overloads<double>(module);
+    }
+
+}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/cast.cpp b/source/framework/python/src/algorithm/local_operation/cast.cpp
index 98296d4de..429aeab5b 100644
--- a/source/framework/python/src/algorithm/local_operation/cast.cpp
+++ b/source/framework/python/src/algorithm/local_operation/cast.cpp
@@ -5,16 +5,8 @@
 namespace lue::framework {
     namespace {
 
-        template<typename OutputElement, typename InputElement, Rank rank>
-        auto cast(PartitionedArray<InputElement, rank> const& array) -> PartitionedArray<OutputElement, rank>
-        {
-            return value_policies::cast<OutputElement>(array);
-        }
-
-
-        template<typename InputElement, Rank rank>
-        auto cast(PartitionedArray<InputElement, rank> const& array, pybind11::object const& dtype_args)
-            -> pybind11::object
+        template<typename Argument>
+        auto cast(Argument const& argument, pybind11::object const& dtype_args) -> pybind11::object
         {
             pybind11::dtype const dtype{pybind11::dtype::from_args(dtype_args)};
 
@@ -33,12 +25,12 @@ namespace lue::framework {
                     {
                         case 4:
                         {
-                            result = pybind11::cast(cast<std::int32_t, InputElement>(array));
+                            result = pybind11::cast(value_policies::cast<std::int32_t>(argument));
                             break;
                         }
                         case 8:
                         {
-                            result = pybind11::cast(cast<std::int64_t, InputElement>(array));
+                            result = pybind11::cast(value_policies::cast<std::int64_t>(argument));
                             break;
                         }
                     }
@@ -52,17 +44,17 @@ namespace lue::framework {
                     {
                         case 1:
                         {
-                            result = pybind11::cast(cast<std::uint8_t, InputElement>(array));
+                            result = pybind11::cast(value_policies::cast<std::uint8_t>(argument));
                             break;
                         }
                         case 4:
                         {
-                            result = pybind11::cast(cast<std::uint32_t, InputElement>(array));
+                            result = pybind11::cast(value_policies::cast<std::uint32_t>(argument));
                             break;
                         }
                         case 8:
                         {
-                            result = pybind11::cast(cast<std::uint64_t, InputElement>(array));
+                            result = pybind11::cast(value_policies::cast<std::uint64_t>(argument));
                             break;
                         }
                     }
@@ -76,12 +68,12 @@ namespace lue::framework {
                     {
                         case 4:
                         {
-                            result = pybind11::cast(cast<float, InputElement>(array));
+                            result = pybind11::cast(value_policies::cast<float>(argument));
                             break;
                         }
                         case 8:
                         {
-                            result = pybind11::cast(cast<double, InputElement>(array));
+                            result = pybind11::cast(value_policies::cast<double>(argument));
                             break;
                         }
                     }
@@ -98,18 +90,41 @@ namespace lue::framework {
             return result;
         }
 
+
+        template<typename Element>
+        void bind_cast_overloads(pybind11::module& module)
+        {
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def(
+                "cast",
+                [](Array const& array, pybind11::object const& dtype_args)
+                { return cast(array, dtype_args); });
+            module.def(
+                "cast",
+                [](Scalar const& scalar, pybind11::object const& dtype_args)
+                { return cast(scalar, dtype_args); });
+            module.def(
+                "cast",
+                [](Value const value, pybind11::object const& dtype_args)
+                { return cast(value, dtype_args); });
+        }
+
     }  // Anonymous namespace
 
 
     void bind_cast(pybind11::module& module)
     {
-        module.def("cast", cast<std::uint8_t, 2>);
-        module.def("cast", cast<std::uint32_t, 2>);
-        module.def("cast", cast<std::int32_t, 2>);
-        module.def("cast", cast<std::uint64_t, 2>);
-        module.def("cast", cast<std::int64_t, 2>);
-        module.def("cast", cast<float, 2>);
-        module.def("cast", cast<double, 2>);
+        bind_cast_overloads<std::uint8_t>(module);
+        bind_cast_overloads<std::uint32_t>(module);
+        bind_cast_overloads<std::int32_t>(module);
+        bind_cast_overloads<std::uint64_t>(module);
+        bind_cast_overloads<std::int64_t>(module);
+        bind_cast_overloads<float>(module);
+        bind_cast_overloads<double>(module);
     }
 
 }  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/ceil.cpp b/source/framework/python/src/algorithm/local_operation/ceil.cpp
index a22eac1ea..200f597f2 100644
--- a/source/framework/python/src/algorithm/local_operation/ceil.cpp
+++ b/source/framework/python/src/algorithm/local_operation/ceil.cpp
@@ -5,10 +5,18 @@
 namespace lue::framework {
     namespace {
 
-        template<typename Element, Rank rank>
-        PartitionedArray<Element, rank> ceil(PartitionedArray<Element, rank> const& array)
+        template<typename Element>
+        constexpr void define_ceil_overloads(pybind11::module& module)
         {
-            return value_policies::ceil(array);
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def("ceil", [](Array const& array) { return ceil(array); });
+            module.def("ceil", [](Scalar const& scalar) { return ceil(scalar); });
+            module.def("ceil", [](Value const value) { return ceil(value); });
         }
 
     }  // Anonymous namespace
@@ -16,8 +24,8 @@ namespace lue::framework {
 
     void bind_ceil(pybind11::module& module)
     {
-        module.def("ceil", ceil<float, 2>);
-        module.def("ceil", ceil<double, 2>);
+        define_ceil_overloads<float>(module);
+        define_ceil_overloads<double>(module);
     }
 
 }  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/cos.cpp b/source/framework/python/src/algorithm/local_operation/cos.cpp
new file mode 100644
index 000000000..16ecf2a5d
--- /dev/null
+++ b/source/framework/python/src/algorithm/local_operation/cos.cpp
@@ -0,0 +1,31 @@
+#include "lue/framework/algorithm/value_policies/cos.hpp"
+#include <pybind11/pybind11.h>
+
+
+namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_cos_overloads(pybind11::module& module)
+        {
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def("cos", [](Array const& array) { return cos(array); });
+            module.def("cos", [](Scalar const& scalar) { return cos(scalar); });
+            module.def("cos", [](Value const value) { return cos(value); });
+        }
+
+    }  // Anonymous namespace
+
+
+    void bind_cos(pybind11::module& module)
+    {
+        define_cos_overloads<float>(module);
+        define_cos_overloads<double>(module);
+    }
+
+}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/divide.cpp b/source/framework/python/src/algorithm/local_operation/divide.cpp
index c37c303d7..0bcc20939 100644
--- a/source/framework/python/src/algorithm/local_operation/divide.cpp
+++ b/source/framework/python/src/algorithm/local_operation/divide.cpp
@@ -1,4 +1,4 @@
-#include "lue/py/framework/algorithm/divide.hpp"
+#include "lue/framework/algorithm/value_policies/divide.hpp"
 #include <pybind11/pybind11.h>
 
 
@@ -8,19 +8,32 @@ namespace lue::framework {
         template<typename Element>
         constexpr void define_divide_overloads(pybind11::module& module)
         {
+            using namespace lue::value_policies;
             Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
 
+            module.def(
+                "divide", [](Array const& array1, Array const& array2) { return divide(array1, array2); });
+            module.def(
+                "divide", [](Array const& array, Scalar const& scalar) { return divide(array, scalar); });
+            module.def("divide", [](Array const& array, Value const value) { return divide(array, value); });
+
+            module.def(
+                "divide", [](Scalar const& scalar, Array const& array) { return divide(scalar, array); });
             module.def(
                 "divide",
-                divide<Element, rank, PartitionedArray<Element, rank>, PartitionedArray<Element, rank>>);
-            module.def("divide", divide<Element, rank, PartitionedArray<Element, rank>, Scalar<Element>>);
-            module.def("divide", divide<Element, rank, PartitionedArray<Element, rank>, Element>);
+                [](Scalar const& scalar1, Scalar const& scalar2) { return divide(scalar1, scalar2); });
+            module.def(
+                "divide", [](Scalar const& scalar, Value const value) { return divide(scalar, value); });
 
-            module.def("divide", divide<Element, rank, Scalar<Element>, PartitionedArray<Element, rank>>);
-            module.def("divide", divide<Element, rank, Element, PartitionedArray<Element, rank>>);
+            module.def("divide", [](Value const value, Array const& array) { return divide(value, array); });
+            module.def(
+                "divide", [](Value const value, Scalar const& scalar) { return divide(value, scalar); });
 
-            module.def("divide", divide<Element, Scalar<Element>, Element>);
-            module.def("divide", divide<Element, Element, Scalar<Element>>);
+            module.def(
+                "divide", [](Value const value1, Value const value2) { return divide(value1, value2); });
         }
 
     }  // Anonymous namespace
diff --git a/source/framework/python/src/algorithm/local_operation/equal_to.cpp b/source/framework/python/src/algorithm/local_operation/equal_to.cpp
index 1ccbbc824..051099bf6 100644
--- a/source/framework/python/src/algorithm/local_operation/equal_to.cpp
+++ b/source/framework/python/src/algorithm/local_operation/equal_to.cpp
@@ -1,5 +1,4 @@
-#include "lue/py/framework/algorithm/equal_to.hpp"
-#include "lue/py/framework/type_traits.hpp"
+#include "lue/framework/algorithm/value_policies/equal_to.hpp"
 #include <pybind11/pybind11.h>
 
 
@@ -9,27 +8,50 @@ namespace lue::framework {
         template<typename Element>
         constexpr void define_equal_to_overloads(pybind11::module& module)
         {
+            using namespace value_policies;
             Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+            using BooleanElement = std::uint8_t;
 
-            using OutputElement = std::uint8_t;
+            module.def(
+                "equal_to",
+                [](Array const& array1, Array const& array2)
+                { return equal_to<BooleanElement>(array1, array2); });
+            module.def(
+                "equal_to",
+                [](Array const& array, Scalar const& scalar)
+                { return equal_to<BooleanElement>(array, scalar); });
+            module.def(
+                "equal_to",
+                [](Array const& array, Value const value) { return equal_to<BooleanElement>(array, value); });
 
             module.def(
                 "equal_to",
-                equal_to<
-                    OutputElement,
-                    rank,
-                    PartitionedArray<Element, rank>,
-                    PartitionedArray<Element, rank>>);
+                [](Scalar const& scalar, Array const& array)
+                { return equal_to<BooleanElement>(scalar, array); });
+            module.def(
+                "equal_to",
+                [](Scalar const& scalar1, Scalar const& scalar2)
+                { return equal_to<BooleanElement>(scalar1, scalar2); });
             module.def(
-                "equal_to", equal_to<OutputElement, rank, PartitionedArray<Element, rank>, Scalar<Element>>);
-            module.def("equal_to", equal_to<OutputElement, rank, PartitionedArray<Element, rank>, Element>);
+                "equal_to",
+                [](Scalar const& scalar, Value const value)
+                { return equal_to<BooleanElement>(scalar, value); });
 
             module.def(
-                "equal_to", equal_to<OutputElement, rank, Scalar<Element>, PartitionedArray<Element, rank>>);
-            module.def("equal_to", equal_to<OutputElement, rank, Element, PartitionedArray<Element, rank>>);
+                "equal_to",
+                [](Value const value, Array const& array) { return equal_to<BooleanElement>(value, array); });
+            module.def(
+                "equal_to",
+                [](Value const value, Scalar const& scalar)
+                { return equal_to<BooleanElement>(value, scalar); });
 
-            module.def("equal_to", equal_to<OutputElement, Scalar<Element>, Element>);
-            module.def("equal_to", equal_to<OutputElement, Element, Scalar<Element>>);
+            module.def(
+                "equal_to",
+                [](Value const value1, Value const value2)
+                { return equal_to<BooleanElement>(value1, value2); });
         }
 
     }  // Anonymous namespace
diff --git a/source/framework/python/src/algorithm/local_operation/exp.cpp b/source/framework/python/src/algorithm/local_operation/exp.cpp
new file mode 100644
index 000000000..dcbe30472
--- /dev/null
+++ b/source/framework/python/src/algorithm/local_operation/exp.cpp
@@ -0,0 +1,31 @@
+#include "lue/framework/algorithm/value_policies/exp.hpp"
+#include <pybind11/pybind11.h>
+
+
+namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_exp_overloads(pybind11::module& module)
+        {
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def("exp", [](Array const& array) { return exp(array); });
+            module.def("exp", [](Scalar const& scalar) { return exp(scalar); });
+            module.def("exp", [](Value const value) { return exp(value); });
+        }
+
+    }  // Anonymous namespace
+
+
+    void bind_exp(pybind11::module& module)
+    {
+        define_exp_overloads<float>(module);
+        define_exp_overloads<double>(module);
+    }
+
+}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/floor.cpp b/source/framework/python/src/algorithm/local_operation/floor.cpp
index dafac72e1..00375975b 100644
--- a/source/framework/python/src/algorithm/local_operation/floor.cpp
+++ b/source/framework/python/src/algorithm/local_operation/floor.cpp
@@ -5,10 +5,18 @@
 namespace lue::framework {
     namespace {
 
-        template<typename Element, Rank rank>
-        PartitionedArray<Element, rank> floor(PartitionedArray<Element, rank> const& array)
+        template<typename Element>
+        constexpr void define_floor_overloads(pybind11::module& module)
         {
-            return value_policies::floor(array);
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def("floor", [](Array const& array) { return floor(array); });
+            module.def("floor", [](Scalar const& scalar) { return floor(scalar); });
+            module.def("floor", [](Value const value) { return floor(value); });
         }
 
     }  // Anonymous namespace
@@ -16,8 +24,8 @@ namespace lue::framework {
 
     void bind_floor(pybind11::module& module)
     {
-        module.def("floor", floor<float, 2>);
-        module.def("floor", floor<double, 2>);
+        define_floor_overloads<float>(module);
+        define_floor_overloads<double>(module);
     }
 
 }  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/greater_than.cpp b/source/framework/python/src/algorithm/local_operation/greater_than.cpp
index ecfd9e553..fa6daa72c 100644
--- a/source/framework/python/src/algorithm/local_operation/greater_than.cpp
+++ b/source/framework/python/src/algorithm/local_operation/greater_than.cpp
@@ -1,5 +1,4 @@
-#include "lue/py/framework/algorithm/greater_than.hpp"
-#include "lue/py/framework/type_traits.hpp"
+#include "lue/framework/algorithm/value_policies/greater_than.hpp"
 #include <pybind11/pybind11.h>
 
 
@@ -9,31 +8,52 @@ namespace lue::framework {
         template<typename Element>
         constexpr void define_greater_than_overloads(pybind11::module& module)
         {
+            using namespace value_policies;
             Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+            using BooleanElement = std::uint8_t;
 
-            using OutputElement = std::uint8_t;
+            module.def(
+                "greater_than",
+                [](Array const& array1, Array const& array2)
+                { return greater_than<BooleanElement>(array1, array2); });
+            module.def(
+                "greater_than",
+                [](Array const& array, Scalar const& scalar)
+                { return greater_than<BooleanElement>(array, scalar); });
+            module.def(
+                "greater_than",
+                [](Array const& array, Value const value)
+                { return greater_than<BooleanElement>(array, value); });
 
             module.def(
                 "greater_than",
-                greater_than<
-                    OutputElement,
-                    rank,
-                    PartitionedArray<Element, rank>,
-                    PartitionedArray<Element, rank>>);
+                [](Scalar const& scalar, Array const& array)
+                { return greater_than<BooleanElement>(scalar, array); });
             module.def(
                 "greater_than",
-                greater_than<OutputElement, rank, PartitionedArray<Element, rank>, Scalar<Element>>);
+                [](Scalar const& scalar1, Scalar const& scalar2)
+                { return greater_than<BooleanElement>(scalar1, scalar2); });
             module.def(
-                "greater_than", greater_than<OutputElement, rank, PartitionedArray<Element, rank>, Element>);
+                "greater_than",
+                [](Scalar const& scalar, Value const value)
+                { return greater_than<BooleanElement>(scalar, value); });
 
             module.def(
                 "greater_than",
-                greater_than<OutputElement, rank, Scalar<Element>, PartitionedArray<Element, rank>>);
+                [](Value const value, Array const& array)
+                { return greater_than<BooleanElement>(value, array); });
             module.def(
-                "greater_than", greater_than<OutputElement, rank, Element, PartitionedArray<Element, rank>>);
+                "greater_than",
+                [](Value const value, Scalar const& scalar)
+                { return greater_than<BooleanElement>(value, scalar); });
 
-            module.def("greater_than", greater_than<OutputElement, Scalar<Element>, Element>);
-            module.def("greater_than", greater_than<OutputElement, Element, Scalar<Element>>);
+            module.def(
+                "greater_than",
+                [](Value const value1, Value const value2)
+                { return greater_than<BooleanElement>(value1, value2); });
         }
 
     }  // Anonymous namespace
diff --git a/source/framework/python/src/algorithm/local_operation/greater_than_equal_to.cpp b/source/framework/python/src/algorithm/local_operation/greater_than_equal_to.cpp
index e8f1882fa..12e84e9d3 100644
--- a/source/framework/python/src/algorithm/local_operation/greater_than_equal_to.cpp
+++ b/source/framework/python/src/algorithm/local_operation/greater_than_equal_to.cpp
@@ -1,5 +1,4 @@
-#include "lue/py/framework/algorithm/greater_than_equal_to.hpp"
-#include "lue/py/framework/type_traits.hpp"
+#include "lue/framework/algorithm/value_policies/greater_than_equal_to.hpp"
 #include <pybind11/pybind11.h>
 
 
@@ -9,35 +8,52 @@ namespace lue::framework {
         template<typename Element>
         constexpr void define_greater_than_equal_to_overloads(pybind11::module& module)
         {
+            using namespace value_policies;
             Rank const rank{2};
-
-            using OutputElement = std::uint8_t;
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+            using BooleanElement = std::uint8_t;
 
             module.def(
                 "greater_than_equal_to",
-                greater_than_equal_to<
-                    OutputElement,
-                    rank,
-                    PartitionedArray<Element, rank>,
-                    PartitionedArray<Element, rank>>);
+                [](Array const& array1, Array const& array2)
+                { return greater_than_equal_to<BooleanElement>(array1, array2); });
             module.def(
                 "greater_than_equal_to",
-                greater_than_equal_to<OutputElement, rank, PartitionedArray<Element, rank>, Scalar<Element>>);
+                [](Array const& array, Scalar const& scalar)
+                { return greater_than_equal_to<BooleanElement>(array, scalar); });
             module.def(
                 "greater_than_equal_to",
-                greater_than_equal_to<OutputElement, rank, PartitionedArray<Element, rank>, Element>);
+                [](Array const& array, Value const value)
+                { return greater_than_equal_to<BooleanElement>(array, value); });
 
             module.def(
                 "greater_than_equal_to",
-                greater_than_equal_to<OutputElement, rank, Scalar<Element>, PartitionedArray<Element, rank>>);
+                [](Scalar const& scalar, Array const& array)
+                { return greater_than_equal_to<BooleanElement>(scalar, array); });
+            module.def(
+                "greater_than_equal_to",
+                [](Scalar const& scalar1, Scalar const& scalar2)
+                { return greater_than_equal_to<BooleanElement>(scalar1, scalar2); });
             module.def(
                 "greater_than_equal_to",
-                greater_than_equal_to<OutputElement, rank, Element, PartitionedArray<Element, rank>>);
+                [](Scalar const& scalar, Value const value)
+                { return greater_than_equal_to<BooleanElement>(scalar, value); });
 
             module.def(
-                "greater_than_equal_to", greater_than_equal_to<OutputElement, Scalar<Element>, Element>);
+                "greater_than_equal_to",
+                [](Value const value, Array const& array)
+                { return greater_than_equal_to<BooleanElement>(value, array); });
+            module.def(
+                "greater_than_equal_to",
+                [](Value const value, Scalar const& scalar)
+                { return greater_than_equal_to<BooleanElement>(value, scalar); });
+
             module.def(
-                "greater_than_equal_to", greater_than_equal_to<OutputElement, Element, Scalar<Element>>);
+                "greater_than_equal_to",
+                [](Value const value1, Value const value2)
+                { return greater_than_equal_to<BooleanElement>(value1, value2); });
         }
 
     }  // Anonymous namespace
diff --git a/source/framework/python/src/algorithm/local_operation/less_than.cpp b/source/framework/python/src/algorithm/local_operation/less_than.cpp
index 4c38cc121..87c58a4b7 100644
--- a/source/framework/python/src/algorithm/local_operation/less_than.cpp
+++ b/source/framework/python/src/algorithm/local_operation/less_than.cpp
@@ -1,5 +1,4 @@
-#include "lue/py/framework/algorithm/less_than.hpp"
-#include "lue/py/framework/type_traits.hpp"
+#include "lue/framework/algorithm/value_policies/less_than.hpp"
 #include <pybind11/pybind11.h>
 
 
@@ -9,29 +8,52 @@ namespace lue::framework {
         template<typename Element>
         constexpr void define_less_than_overloads(pybind11::module& module)
         {
+            using namespace value_policies;
             Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+            using BooleanElement = std::uint8_t;
 
-            using OutputElement = std::uint8_t;
+            module.def(
+                "less_than",
+                [](Array const& array1, Array const& array2)
+                { return less_than<BooleanElement>(array1, array2); });
+            module.def(
+                "less_than",
+                [](Array const& array, Scalar const& scalar)
+                { return less_than<BooleanElement>(array, scalar); });
+            module.def(
+                "less_than",
+                [](Array const& array, Value const value)
+                { return less_than<BooleanElement>(array, value); });
 
             module.def(
                 "less_than",
-                less_than<
-                    OutputElement,
-                    rank,
-                    PartitionedArray<Element, rank>,
-                    PartitionedArray<Element, rank>>);
+                [](Scalar const& scalar, Array const& array)
+                { return less_than<BooleanElement>(scalar, array); });
             module.def(
                 "less_than",
-                less_than<OutputElement, rank, PartitionedArray<Element, rank>, Scalar<Element>>);
-            module.def("less_than", less_than<OutputElement, rank, PartitionedArray<Element, rank>, Element>);
+                [](Scalar const& scalar1, Scalar const& scalar2)
+                { return less_than<BooleanElement>(scalar1, scalar2); });
+            module.def(
+                "less_than",
+                [](Scalar const& scalar, Value const value)
+                { return less_than<BooleanElement>(scalar, value); });
 
             module.def(
                 "less_than",
-                less_than<OutputElement, rank, Scalar<Element>, PartitionedArray<Element, rank>>);
-            module.def("less_than", less_than<OutputElement, rank, Element, PartitionedArray<Element, rank>>);
+                [](Value const value, Array const& array)
+                { return less_than<BooleanElement>(value, array); });
+            module.def(
+                "less_than",
+                [](Value const value, Scalar const& scalar)
+                { return less_than<BooleanElement>(value, scalar); });
 
-            module.def("less_than", less_than<OutputElement, Scalar<Element>, Element>);
-            module.def("less_than", less_than<OutputElement, Element, Scalar<Element>>);
+            module.def(
+                "less_than",
+                [](Value const value1, Value const value2)
+                { return less_than<BooleanElement>(value1, value2); });
         }
 
     }  // Anonymous namespace
diff --git a/source/framework/python/src/algorithm/local_operation/less_than_equal_to.cpp b/source/framework/python/src/algorithm/local_operation/less_than_equal_to.cpp
index 500150eed..0eb4f3d2d 100644
--- a/source/framework/python/src/algorithm/local_operation/less_than_equal_to.cpp
+++ b/source/framework/python/src/algorithm/local_operation/less_than_equal_to.cpp
@@ -1,5 +1,4 @@
-#include "lue/py/framework/algorithm/less_than_equal_to.hpp"
-#include "lue/py/framework/type_traits.hpp"
+#include "lue/framework/algorithm/value_policies/less_than_equal_to.hpp"
 #include <pybind11/pybind11.h>
 
 
@@ -9,33 +8,52 @@ namespace lue::framework {
         template<typename Element>
         constexpr void define_less_than_equal_to_overloads(pybind11::module& module)
         {
+            using namespace value_policies;
             Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+            using BooleanElement = std::uint8_t;
 
-            using OutputElement = std::uint8_t;
+            module.def(
+                "less_than_equal_to",
+                [](Array const& array1, Array const& array2)
+                { return less_than_equal_to<BooleanElement>(array1, array2); });
+            module.def(
+                "less_than_equal_to",
+                [](Array const& array, Scalar const& scalar)
+                { return less_than_equal_to<BooleanElement>(array, scalar); });
+            module.def(
+                "less_than_equal_to",
+                [](Array const& array, Value const value)
+                { return less_than_equal_to<BooleanElement>(array, value); });
 
             module.def(
                 "less_than_equal_to",
-                less_than_equal_to<
-                    OutputElement,
-                    rank,
-                    PartitionedArray<Element, rank>,
-                    PartitionedArray<Element, rank>>);
+                [](Scalar const& scalar, Array const& array)
+                { return less_than_equal_to<BooleanElement>(scalar, array); });
             module.def(
                 "less_than_equal_to",
-                less_than_equal_to<OutputElement, rank, PartitionedArray<Element, rank>, Scalar<Element>>);
+                [](Scalar const& scalar1, Scalar const& scalar2)
+                { return less_than_equal_to<BooleanElement>(scalar1, scalar2); });
             module.def(
                 "less_than_equal_to",
-                less_than_equal_to<OutputElement, rank, PartitionedArray<Element, rank>, Element>);
+                [](Scalar const& scalar, Value const value)
+                { return less_than_equal_to<BooleanElement>(scalar, value); });
 
             module.def(
                 "less_than_equal_to",
-                less_than_equal_to<OutputElement, rank, Scalar<Element>, PartitionedArray<Element, rank>>);
+                [](Value const value, Array const& array)
+                { return less_than_equal_to<BooleanElement>(value, array); });
             module.def(
                 "less_than_equal_to",
-                less_than_equal_to<OutputElement, rank, Element, PartitionedArray<Element, rank>>);
+                [](Value const value, Scalar const& scalar)
+                { return less_than_equal_to<BooleanElement>(value, scalar); });
 
-            module.def("less_than_equal_to", less_than_equal_to<OutputElement, Scalar<Element>, Element>);
-            module.def("less_than_equal_to", less_than_equal_to<OutputElement, Element, Scalar<Element>>);
+            module.def(
+                "less_than_equal_to",
+                [](Value const value1, Value const value2)
+                { return less_than_equal_to<BooleanElement>(value1, value2); });
         }
 
     }  // Anonymous namespace
diff --git a/source/framework/python/src/algorithm/local_operation/log.cpp b/source/framework/python/src/algorithm/local_operation/log.cpp
new file mode 100644
index 000000000..c6f90c8e2
--- /dev/null
+++ b/source/framework/python/src/algorithm/local_operation/log.cpp
@@ -0,0 +1,31 @@
+#include "lue/framework/algorithm/value_policies/log.hpp"
+#include <pybind11/pybind11.h>
+
+
+namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_log_overloads(pybind11::module& module)
+        {
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def("log", [](Array const& array) { return log(array); });
+            module.def("log", [](Scalar const& scalar) { return log(scalar); });
+            module.def("log", [](Value const value) { return log(value); });
+        }
+
+    }  // Anonymous namespace
+
+
+    void bind_log(pybind11::module& module)
+    {
+        define_log_overloads<float>(module);
+        define_log_overloads<double>(module);
+    }
+
+}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/log10.cpp b/source/framework/python/src/algorithm/local_operation/log10.cpp
index dfe9094e5..066116bb3 100644
--- a/source/framework/python/src/algorithm/local_operation/log10.cpp
+++ b/source/framework/python/src/algorithm/local_operation/log10.cpp
@@ -5,10 +5,18 @@
 namespace lue::framework {
     namespace {
 
-        template<typename Element, Rank rank>
-        PartitionedArray<Element, rank> log10(PartitionedArray<Element, rank> const& array)
+        template<typename Element>
+        constexpr void define_log10_overloads(pybind11::module& module)
         {
-            return value_policies::log10(array);
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def("log10", [](Array const& array) { return log10(array); });
+            module.def("log10", [](Scalar const& scalar) { return log10(scalar); });
+            module.def("log10", [](Value const value) { return log10(value); });
         }
 
     }  // Anonymous namespace
@@ -16,8 +24,8 @@ namespace lue::framework {
 
     void bind_log10(pybind11::module& module)
     {
-        module.def("log10", log10<float, 2>);
-        module.def("log10", log10<double, 2>);
+        define_log10_overloads<float>(module);
+        define_log10_overloads<double>(module);
     }
 
 }  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/logical_and.cpp b/source/framework/python/src/algorithm/local_operation/logical_and.cpp
index 3439e0e7d..21053c1ed 100644
--- a/source/framework/python/src/algorithm/local_operation/logical_and.cpp
+++ b/source/framework/python/src/algorithm/local_operation/logical_and.cpp
@@ -1,16 +1,71 @@
-#include "lue/py/framework/algorithm/logical_and.hpp"
+#include "lue/framework/algorithm/value_policies/logical_and.hpp"
 #include <pybind11/pybind11.h>
 
 
 namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_logical_and_overloads(pybind11::module& module)
+        {
+            using namespace value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+            using BooleanElement = std::uint8_t;
+
+            module.def(
+                "logical_and",
+                [](Array const& array1, Array const& array2)
+                { return logical_and<BooleanElement>(array1, array2); });
+            module.def(
+                "logical_and",
+                [](Array const& array, Scalar const& scalar)
+                { return logical_and<BooleanElement>(array, scalar); });
+            module.def(
+                "logical_and",
+                [](Array const& array, Value const value)
+                { return logical_and<BooleanElement>(array, value); });
+
+            module.def(
+                "logical_and",
+                [](Scalar const& scalar, Array const& array)
+                { return logical_and<BooleanElement>(scalar, array); });
+            module.def(
+                "logical_and",
+                [](Scalar const& scalar1, Scalar const& scalar2)
+                { return logical_and<BooleanElement>(scalar1, scalar2); });
+            module.def(
+                "logical_and",
+                [](Scalar const& scalar, Value const value)
+                { return logical_and<BooleanElement>(scalar, value); });
+
+            module.def(
+                "logical_and",
+                [](Value const value, Array const& array)
+                { return logical_and<BooleanElement>(value, array); });
+            module.def(
+                "logical_and",
+                [](Value const value, Scalar const& scalar)
+                { return logical_and<BooleanElement>(value, scalar); });
+
+            module.def(
+                "logical_and",
+                [](Value const value1, Value const value2)
+                { return logical_and<BooleanElement>(value1, value2); });
+        }
+
+    }  // Anonymous namespace
+
 
     void bind_logical_and(pybind11::module& module)
     {
-        module.def("logical_and", logical_and<std::uint8_t, 2>);
-        module.def("logical_and", logical_and<std::int32_t, 2>);
-        module.def("logical_and", logical_and<std::uint32_t, 2>);
-        module.def("logical_and", logical_and<std::int64_t, 2>);
-        module.def("logical_and", logical_and<std::uint64_t, 2>);
+        define_logical_and_overloads<std::uint8_t>(module);
+        define_logical_and_overloads<std::uint32_t>(module);
+        define_logical_and_overloads<std::uint64_t>(module);
+        define_logical_and_overloads<std::int32_t>(module);
+        define_logical_and_overloads<std::int64_t>(module);
     }
 
 }  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/logical_exclusive_or.cpp b/source/framework/python/src/algorithm/local_operation/logical_exclusive_or.cpp
index 8915d9567..01891b9b0 100644
--- a/source/framework/python/src/algorithm/local_operation/logical_exclusive_or.cpp
+++ b/source/framework/python/src/algorithm/local_operation/logical_exclusive_or.cpp
@@ -1,16 +1,71 @@
-#include "lue/py/framework/algorithm/logical_exclusive_or.hpp"
+#include "lue/framework/algorithm/value_policies/logical_exclusive_or.hpp"
 #include <pybind11/pybind11.h>
 
 
 namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_logical_exclusive_or_overloads(pybind11::module& module)
+        {
+            using namespace value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+            using BooleanElement = std::uint8_t;
+
+            module.def(
+                "logical_exclusive_or",
+                [](Array const& array1, Array const& array2)
+                { return logical_exclusive_or<BooleanElement>(array1, array2); });
+            module.def(
+                "logical_exclusive_or",
+                [](Array const& array, Scalar const& scalar)
+                { return logical_exclusive_or<BooleanElement>(array, scalar); });
+            module.def(
+                "logical_exclusive_or",
+                [](Array const& array, Value const value)
+                { return logical_exclusive_or<BooleanElement>(array, value); });
+
+            module.def(
+                "logical_exclusive_or",
+                [](Scalar const& scalar, Array const& array)
+                { return logical_exclusive_or<BooleanElement>(scalar, array); });
+            module.def(
+                "logical_exclusive_or",
+                [](Scalar const& scalar1, Scalar const& scalar2)
+                { return logical_exclusive_or<BooleanElement>(scalar1, scalar2); });
+            module.def(
+                "logical_exclusive_or",
+                [](Scalar const& scalar, Value const value)
+                { return logical_exclusive_or<BooleanElement>(scalar, value); });
+
+            module.def(
+                "logical_exclusive_or",
+                [](Value const value, Array const& array)
+                { return logical_exclusive_or<BooleanElement>(value, array); });
+            module.def(
+                "logical_exclusive_or",
+                [](Value const value, Scalar const& scalar)
+                { return logical_exclusive_or<BooleanElement>(value, scalar); });
+
+            module.def(
+                "logical_exclusive_or",
+                [](Value const value1, Value const value2)
+                { return logical_exclusive_or<BooleanElement>(value1, value2); });
+        }
+
+    }  // Anonymous namespace
+
 
     void bind_logical_exclusive_or(pybind11::module& module)
     {
-        module.def("logical_exclusive_or", logical_exclusive_or<std::uint8_t, 2>);
-        module.def("logical_exclusive_or", logical_exclusive_or<std::int32_t, 2>);
-        module.def("logical_exclusive_or", logical_exclusive_or<std::uint32_t, 2>);
-        module.def("logical_exclusive_or", logical_exclusive_or<std::int64_t, 2>);
-        module.def("logical_exclusive_or", logical_exclusive_or<std::uint64_t, 2>);
+        define_logical_exclusive_or_overloads<std::uint8_t>(module);
+        define_logical_exclusive_or_overloads<std::uint32_t>(module);
+        define_logical_exclusive_or_overloads<std::uint64_t>(module);
+        define_logical_exclusive_or_overloads<std::int32_t>(module);
+        define_logical_exclusive_or_overloads<std::int64_t>(module);
     }
 
 }  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/logical_inclusive_or.cpp b/source/framework/python/src/algorithm/local_operation/logical_inclusive_or.cpp
index 18046efa1..0c8d4747e 100644
--- a/source/framework/python/src/algorithm/local_operation/logical_inclusive_or.cpp
+++ b/source/framework/python/src/algorithm/local_operation/logical_inclusive_or.cpp
@@ -1,16 +1,71 @@
-#include "lue/py/framework/algorithm/logical_inclusive_or.hpp"
+#include "lue/framework/algorithm/value_policies/logical_inclusive_or.hpp"
 #include <pybind11/pybind11.h>
 
 
 namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_logical_inclusive_or_overloads(pybind11::module& module)
+        {
+            using namespace value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+            using BooleanElement = std::uint8_t;
+
+            module.def(
+                "logical_inclusive_or",
+                [](Array const& array1, Array const& array2)
+                { return logical_inclusive_or<BooleanElement>(array1, array2); });
+            module.def(
+                "logical_inclusive_or",
+                [](Array const& array, Scalar const& scalar)
+                { return logical_inclusive_or<BooleanElement>(array, scalar); });
+            module.def(
+                "logical_inclusive_or",
+                [](Array const& array, Value const value)
+                { return logical_inclusive_or<BooleanElement>(array, value); });
+
+            module.def(
+                "logical_inclusive_or",
+                [](Scalar const& scalar, Array const& array)
+                { return logical_inclusive_or<BooleanElement>(scalar, array); });
+            module.def(
+                "logical_inclusive_or",
+                [](Scalar const& scalar1, Scalar const& scalar2)
+                { return logical_inclusive_or<BooleanElement>(scalar1, scalar2); });
+            module.def(
+                "logical_inclusive_or",
+                [](Scalar const& scalar, Value const value)
+                { return logical_inclusive_or<BooleanElement>(scalar, value); });
+
+            module.def(
+                "logical_inclusive_or",
+                [](Value const value, Array const& array)
+                { return logical_inclusive_or<BooleanElement>(value, array); });
+            module.def(
+                "logical_inclusive_or",
+                [](Value const value, Scalar const& scalar)
+                { return logical_inclusive_or<BooleanElement>(value, scalar); });
+
+            module.def(
+                "logical_inclusive_or",
+                [](Value const value1, Value const value2)
+                { return logical_inclusive_or<BooleanElement>(value1, value2); });
+        }
+
+    }  // Anonymous namespace
+
 
     void bind_logical_inclusive_or(pybind11::module& module)
     {
-        module.def("logical_inclusive_or", logical_inclusive_or<std::uint8_t, 2>);
-        module.def("logical_inclusive_or", logical_inclusive_or<std::int32_t, 2>);
-        module.def("logical_inclusive_or", logical_inclusive_or<std::uint32_t, 2>);
-        module.def("logical_inclusive_or", logical_inclusive_or<std::int64_t, 2>);
-        module.def("logical_inclusive_or", logical_inclusive_or<std::uint64_t, 2>);
+        define_logical_inclusive_or_overloads<std::uint8_t>(module);
+        define_logical_inclusive_or_overloads<std::uint32_t>(module);
+        define_logical_inclusive_or_overloads<std::uint64_t>(module);
+        define_logical_inclusive_or_overloads<std::int32_t>(module);
+        define_logical_inclusive_or_overloads<std::int64_t>(module);
     }
 
 }  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/logical_not.cpp b/source/framework/python/src/algorithm/local_operation/logical_not.cpp
index 3524c8587..f39a5182a 100644
--- a/source/framework/python/src/algorithm/local_operation/logical_not.cpp
+++ b/source/framework/python/src/algorithm/local_operation/logical_not.cpp
@@ -1,16 +1,36 @@
-#include "lue/py/framework/algorithm/logical_not.hpp"
+#include "lue/framework/algorithm/value_policies/logical_not.hpp"
 #include <pybind11/pybind11.h>
 
 
 namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_logical_not_overloads(pybind11::module& module)
+        {
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+            using BooleanElement = std::uint8_t;
+
+            module.def("logical_not", [](Array const& array) { return logical_not<BooleanElement>(array); });
+            module.def(
+                "logical_not", [](Scalar const& scalar) { return logical_not<BooleanElement>(scalar); });
+            module.def("logical_not", [](Value const value) { return logical_not<BooleanElement>(value); });
+        }
+
+    }  // Anonymous namespace
+
 
     void bind_logical_not(pybind11::module& module)
     {
-        module.def("logical_not", logical_not<std::uint8_t, 2>);
-        module.def("logical_not", logical_not<std::int32_t, 2>);
-        module.def("logical_not", logical_not<std::uint32_t, 2>);
-        module.def("logical_not", logical_not<std::int64_t, 2>);
-        module.def("logical_not", logical_not<std::uint64_t, 2>);
+        define_logical_not_overloads<std::uint8_t>(module);
+        define_logical_not_overloads<std::int32_t>(module);
+        define_logical_not_overloads<std::uint32_t>(module);
+        define_logical_not_overloads<std::int64_t>(module);
+        define_logical_not_overloads<std::uint64_t>(module);
     }
 
 }  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/multiply.cpp b/source/framework/python/src/algorithm/local_operation/multiply.cpp
index cde9e63ca..faf8a681a 100644
--- a/source/framework/python/src/algorithm/local_operation/multiply.cpp
+++ b/source/framework/python/src/algorithm/local_operation/multiply.cpp
@@ -1,4 +1,4 @@
-#include "lue/py/framework/algorithm/multiply.hpp"
+#include "lue/framework/algorithm/value_policies/multiply.hpp"
 #include <pybind11/pybind11.h>
 
 
@@ -8,19 +8,35 @@ namespace lue::framework {
         template<typename Element>
         constexpr void define_multiply_overloads(pybind11::module& module)
         {
+            using namespace lue::value_policies;
             Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
 
             module.def(
                 "multiply",
-                multiply<Element, rank, PartitionedArray<Element, rank>, PartitionedArray<Element, rank>>);
-            module.def("multiply", multiply<Element, rank, PartitionedArray<Element, rank>, Scalar<Element>>);
-            module.def("multiply", multiply<Element, rank, PartitionedArray<Element, rank>, Element>);
+                [](Array const& array1, Array const& array2) { return multiply(array1, array2); });
+            module.def(
+                "multiply", [](Array const& array, Scalar const& scalar) { return multiply(array, scalar); });
+            module.def(
+                "multiply", [](Array const& array, Value const value) { return multiply(array, value); });
+
+            module.def(
+                "multiply", [](Scalar const& scalar, Array const& array) { return multiply(scalar, array); });
+            module.def(
+                "multiply",
+                [](Scalar const& scalar1, Scalar const& scalar2) { return multiply(scalar1, scalar2); });
+            module.def(
+                "multiply", [](Scalar const& scalar, Value const value) { return multiply(scalar, value); });
 
-            module.def("multiply", multiply<Element, rank, Scalar<Element>, PartitionedArray<Element, rank>>);
-            module.def("multiply", multiply<Element, rank, Element, PartitionedArray<Element, rank>>);
+            module.def(
+                "multiply", [](Value const value, Array const& array) { return multiply(value, array); });
+            module.def(
+                "multiply", [](Value const value, Scalar const& scalar) { return multiply(value, scalar); });
 
-            module.def("multiply", multiply<Element, Scalar<Element>, Element>);
-            module.def("multiply", multiply<Element, Element, Scalar<Element>>);
+            module.def(
+                "multiply", [](Value const value1, Value const value2) { return multiply(value1, value2); });
         }
 
     }  // Anonymous namespace
diff --git a/source/framework/python/src/algorithm/local_operation/negate.cpp b/source/framework/python/src/algorithm/local_operation/negate.cpp
index a3ba62e26..c50c4cc07 100644
--- a/source/framework/python/src/algorithm/local_operation/negate.cpp
+++ b/source/framework/python/src/algorithm/local_operation/negate.cpp
@@ -1,15 +1,33 @@
-#include "lue/py/framework/algorithm/negate.hpp"
+#include "lue/framework/algorithm/value_policies/negate.hpp"
 #include <pybind11/pybind11.h>
 
 
 namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_negate_overloads(pybind11::module& module)
+        {
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def("negate", [](Array const& array) { return negate(array); });
+            module.def("negate", [](Scalar const& scalar) { return negate(scalar); });
+            module.def("negate", [](Value const value) { return negate(value); });
+        }
+
+    }  // Anonymous namespace
+
 
     void bind_negate(pybind11::module& module)
     {
-        module.def("negate", negate<std::int32_t, 2>);
-        module.def("negate", negate<std::int64_t, 2>);
-        module.def("negate", negate<float, 2>);
-        module.def("negate", negate<double, 2>);
+        define_negate_overloads<std::int32_t>(module);
+        define_negate_overloads<std::int64_t>(module);
+        define_negate_overloads<float>(module);
+        define_negate_overloads<double>(module);
     }
 
 }  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/not_equal_to.cpp b/source/framework/python/src/algorithm/local_operation/not_equal_to.cpp
index 48f968737..1fbb169c0 100644
--- a/source/framework/python/src/algorithm/local_operation/not_equal_to.cpp
+++ b/source/framework/python/src/algorithm/local_operation/not_equal_to.cpp
@@ -1,5 +1,4 @@
-#include "lue/py/framework/algorithm/not_equal_to.hpp"
-#include "lue/py/framework/type_traits.hpp"
+#include "lue/framework/algorithm/value_policies/not_equal_to.hpp"
 #include <pybind11/pybind11.h>
 
 
@@ -9,31 +8,52 @@ namespace lue::framework {
         template<typename Element>
         constexpr void define_not_equal_to_overloads(pybind11::module& module)
         {
+            using namespace value_policies;
             Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+            using BooleanElement = std::uint8_t;
 
-            using OutputElement = std::uint8_t;
+            module.def(
+                "not_equal_to",
+                [](Array const& array1, Array const& array2)
+                { return not_equal_to<BooleanElement>(array1, array2); });
+            module.def(
+                "not_equal_to",
+                [](Array const& array, Scalar const& scalar)
+                { return not_equal_to<BooleanElement>(array, scalar); });
+            module.def(
+                "not_equal_to",
+                [](Array const& array, Value const value)
+                { return not_equal_to<BooleanElement>(array, value); });
 
             module.def(
                 "not_equal_to",
-                not_equal_to<
-                    OutputElement,
-                    rank,
-                    PartitionedArray<Element, rank>,
-                    PartitionedArray<Element, rank>>);
+                [](Scalar const& scalar, Array const& array)
+                { return not_equal_to<BooleanElement>(scalar, array); });
             module.def(
                 "not_equal_to",
-                not_equal_to<OutputElement, rank, PartitionedArray<Element, rank>, Scalar<Element>>);
+                [](Scalar const& scalar1, Scalar const& scalar2)
+                { return not_equal_to<BooleanElement>(scalar1, scalar2); });
             module.def(
-                "not_equal_to", not_equal_to<OutputElement, rank, PartitionedArray<Element, rank>, Element>);
+                "not_equal_to",
+                [](Scalar const& scalar, Value const value)
+                { return not_equal_to<BooleanElement>(scalar, value); });
 
             module.def(
                 "not_equal_to",
-                not_equal_to<OutputElement, rank, Scalar<Element>, PartitionedArray<Element, rank>>);
+                [](Value const value, Array const& array)
+                { return not_equal_to<BooleanElement>(value, array); });
             module.def(
-                "not_equal_to", not_equal_to<OutputElement, rank, Element, PartitionedArray<Element, rank>>);
+                "not_equal_to",
+                [](Value const value, Scalar const& scalar)
+                { return not_equal_to<BooleanElement>(value, scalar); });
 
-            module.def("not_equal_to", not_equal_to<OutputElement, Scalar<Element>, Element>);
-            module.def("not_equal_to", not_equal_to<OutputElement, Element, Scalar<Element>>);
+            module.def(
+                "not_equal_to",
+                [](Value const value1, Value const value2)
+                { return not_equal_to<BooleanElement>(value1, value2); });
         }
 
     }  // Anonymous namespace
diff --git a/source/framework/python/src/algorithm/local_operation/pow.cpp b/source/framework/python/src/algorithm/local_operation/pow.cpp
index aea6530a2..7a4c5a44d 100644
--- a/source/framework/python/src/algorithm/local_operation/pow.cpp
+++ b/source/framework/python/src/algorithm/local_operation/pow.cpp
@@ -1,4 +1,4 @@
-#include "lue/py/framework/algorithm/pow.hpp"
+#include "lue/framework/algorithm/value_policies/pow.hpp"
 #include <pybind11/pybind11.h>
 
 
@@ -8,18 +8,25 @@ namespace lue::framework {
         template<typename Element>
         constexpr void define_pow_overloads(pybind11::module& module)
         {
+            using namespace lue::value_policies;
             Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
 
+            module.def("pow", [](Array const& array1, Array const& array2) { return pow(array1, array2); });
+            module.def("pow", [](Array const& array, Scalar const& scalar) { return pow(array, scalar); });
+            module.def("pow", [](Array const& array, Value const value) { return pow(array, value); });
+
+            module.def("pow", [](Scalar const& scalar, Array const& array) { return pow(scalar, array); });
             module.def(
-                "pow", pow<Element, rank, PartitionedArray<Element, rank>, PartitionedArray<Element, rank>>);
-            module.def("pow", pow<Element, rank, PartitionedArray<Element, rank>, Scalar<Element>>);
-            module.def("pow", pow<Element, rank, PartitionedArray<Element, rank>, Element>);
+                "pow", [](Scalar const& scalar1, Scalar const& scalar2) { return pow(scalar1, scalar2); });
+            module.def("pow", [](Scalar const& scalar, Value const value) { return pow(scalar, value); });
 
-            module.def("pow", pow<Element, rank, Scalar<Element>, PartitionedArray<Element, rank>>);
-            module.def("pow", pow<Element, rank, Element, PartitionedArray<Element, rank>>);
+            module.def("pow", [](Value const value, Array const& array) { return pow(value, array); });
+            module.def("pow", [](Value const value, Scalar const& scalar) { return pow(value, scalar); });
 
-            module.def("pow", pow<Element, Scalar<Element>, Element>);
-            module.def("pow", pow<Element, Element, Scalar<Element>>);
+            module.def("pow", [](Value const value1, Value const value2) { return pow(value1, value2); });
         }
 
     }  // Anonymous namespace
diff --git a/source/framework/python/src/algorithm/local_operation/round.cpp b/source/framework/python/src/algorithm/local_operation/round.cpp
index c7ed314ca..5a1b15520 100644
--- a/source/framework/python/src/algorithm/local_operation/round.cpp
+++ b/source/framework/python/src/algorithm/local_operation/round.cpp
@@ -5,10 +5,18 @@
 namespace lue::framework {
     namespace {
 
-        template<typename Element, Rank rank>
-        PartitionedArray<Element, rank> round(PartitionedArray<Element, rank> const& array)
+        template<typename Element>
+        constexpr void define_round_overloads(pybind11::module& module)
         {
-            return value_policies::round(array);
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def("round", [](Array const& array) { return round(array); });
+            module.def("round", [](Scalar const& scalar) { return round(scalar); });
+            module.def("round", [](Value const value) { return round(value); });
         }
 
     }  // Anonymous namespace
@@ -16,8 +24,8 @@ namespace lue::framework {
 
     void bind_round(pybind11::module& module)
     {
-        module.def("round", round<float, 2>);
-        module.def("round", round<double, 2>);
+        define_round_overloads<float>(module);
+        define_round_overloads<double>(module);
     }
 
 }  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/sin.cpp b/source/framework/python/src/algorithm/local_operation/sin.cpp
new file mode 100644
index 000000000..6465cb12a
--- /dev/null
+++ b/source/framework/python/src/algorithm/local_operation/sin.cpp
@@ -0,0 +1,31 @@
+#include "lue/framework/algorithm/value_policies/sin.hpp"
+#include <pybind11/pybind11.h>
+
+
+namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_sin_overloads(pybind11::module& module)
+        {
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def("sin", [](Array const& array) { return sin(array); });
+            module.def("sin", [](Scalar const& scalar) { return sin(scalar); });
+            module.def("sin", [](Value const value) { return sin(value); });
+        }
+
+    }  // Anonymous namespace
+
+
+    void bind_sin(pybind11::module& module)
+    {
+        define_sin_overloads<float>(module);
+        define_sin_overloads<double>(module);
+    }
+
+}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/sqrt.cpp b/source/framework/python/src/algorithm/local_operation/sqrt.cpp
new file mode 100644
index 000000000..d7f29ea88
--- /dev/null
+++ b/source/framework/python/src/algorithm/local_operation/sqrt.cpp
@@ -0,0 +1,31 @@
+#include "lue/framework/algorithm/value_policies/sqrt.hpp"
+#include <pybind11/pybind11.h>
+
+
+namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_sqrt_overloads(pybind11::module& module)
+        {
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def("sqrt", [](Array const& array) { return sqrt(array); });
+            module.def("sqrt", [](Scalar const& scalar) { return sqrt(scalar); });
+            module.def("sqrt", [](Value const value) { return sqrt(value); });
+        }
+
+    }  // Anonymous namespace
+
+
+    void bind_sqrt(pybind11::module& module)
+    {
+        define_sqrt_overloads<float>(module);
+        define_sqrt_overloads<double>(module);
+    }
+
+}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/subtract.cpp b/source/framework/python/src/algorithm/local_operation/subtract.cpp
index b2ff735e4..468a25e9b 100644
--- a/source/framework/python/src/algorithm/local_operation/subtract.cpp
+++ b/source/framework/python/src/algorithm/local_operation/subtract.cpp
@@ -1,4 +1,4 @@
-#include "lue/py/framework/algorithm/subtract.hpp"
+#include "lue/framework/algorithm/value_policies/subtract.hpp"
 #include <pybind11/pybind11.h>
 
 
@@ -8,19 +8,35 @@ namespace lue::framework {
         template<typename Element>
         constexpr void define_subtract_overloads(pybind11::module& module)
         {
+            using namespace lue::value_policies;
             Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
 
             module.def(
                 "subtract",
-                subtract<Element, rank, PartitionedArray<Element, rank>, PartitionedArray<Element, rank>>);
-            module.def("subtract", subtract<Element, rank, PartitionedArray<Element, rank>, Scalar<Element>>);
-            module.def("subtract", subtract<Element, rank, PartitionedArray<Element, rank>, Element>);
+                [](Array const& array1, Array const& array2) { return subtract(array1, array2); });
+            module.def(
+                "subtract", [](Array const& array, Scalar const& scalar) { return subtract(array, scalar); });
+            module.def(
+                "subtract", [](Array const& array, Value const value) { return subtract(array, value); });
+
+            module.def(
+                "subtract", [](Scalar const& scalar, Array const& array) { return subtract(scalar, array); });
+            module.def(
+                "subtract",
+                [](Scalar const& scalar1, Scalar const& scalar2) { return subtract(scalar1, scalar2); });
+            module.def(
+                "subtract", [](Scalar const& scalar, Value const value) { return subtract(scalar, value); });
 
-            module.def("subtract", subtract<Element, rank, Scalar<Element>, PartitionedArray<Element, rank>>);
-            module.def("subtract", subtract<Element, rank, Element, PartitionedArray<Element, rank>>);
+            module.def(
+                "subtract", [](Value const value, Array const& array) { return subtract(value, array); });
+            module.def(
+                "subtract", [](Value const value, Scalar const& scalar) { return subtract(value, scalar); });
 
-            module.def("subtract", subtract<Element, Scalar<Element>, Element>);
-            module.def("subtract", subtract<Element, Element, Scalar<Element>>);
+            module.def(
+                "subtract", [](Value const value1, Value const value2) { return subtract(value1, value2); });
         }
 
     }  // Anonymous namespace
diff --git a/source/framework/python/src/algorithm/local_operation/tan.cpp b/source/framework/python/src/algorithm/local_operation/tan.cpp
new file mode 100644
index 000000000..d37759c83
--- /dev/null
+++ b/source/framework/python/src/algorithm/local_operation/tan.cpp
@@ -0,0 +1,31 @@
+#include "lue/framework/algorithm/value_policies/tan.hpp"
+#include <pybind11/pybind11.h>
+
+
+namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_tan_overloads(pybind11::module& module)
+        {
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+
+            module.def("tan", [](Array const& array) { return tan(array); });
+            module.def("tan", [](Scalar const& scalar) { return tan(scalar); });
+            module.def("tan", [](Value const value) { return tan(value); });
+        }
+
+    }  // Anonymous namespace
+
+
+    void bind_tan(pybind11::module& module)
+    {
+        define_tan_overloads<float>(module);
+        define_tan_overloads<double>(module);
+    }
+
+}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/local_operation/valid.cpp b/source/framework/python/src/algorithm/local_operation/valid.cpp
new file mode 100644
index 000000000..91022b6ec
--- /dev/null
+++ b/source/framework/python/src/algorithm/local_operation/valid.cpp
@@ -0,0 +1,37 @@
+#include "lue/framework/algorithm/value_policies/valid.hpp"
+#include <pybind11/pybind11.h>
+
+
+namespace lue::framework {
+    namespace {
+
+        template<typename Element>
+        constexpr void define_valid_overloads(pybind11::module& module)
+        {
+            using namespace lue::value_policies;
+            Rank const rank{2};
+            using Array = PartitionedArray<Element, rank>;
+            using Scalar = Scalar<Element>;
+            using Value = Element;
+            using BooleanElement = std::uint8_t;
+
+            module.def("valid", [](Array const& array) { return valid<BooleanElement>(array); });
+            module.def("valid", [](Scalar const& scalar) { return valid<BooleanElement>(scalar); });
+            module.def("valid", [](Value const value) { return valid<BooleanElement>(value); });
+        }
+
+    }  // Anonymous namespace
+
+
+    void bind_valid(pybind11::module& module)
+    {
+        define_valid_overloads<std::uint8_t>(module);
+        define_valid_overloads<std::int32_t>(module);
+        define_valid_overloads<std::uint32_t>(module);
+        define_valid_overloads<std::int64_t>(module);
+        define_valid_overloads<std::uint64_t>(module);
+        define_valid_overloads<float>(module);
+        define_valid_overloads<double>(module);
+    }
+
+}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/log.cpp b/source/framework/python/src/algorithm/log.cpp
deleted file mode 100644
index 9dec6e696..000000000
--- a/source/framework/python/src/algorithm/log.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "lue/framework/algorithm/value_policies/log.hpp"
-#include <pybind11/pybind11.h>
-
-
-namespace lue::framework {
-    namespace {
-
-        template<typename Element, Rank rank>
-        PartitionedArray<Element, rank> log(PartitionedArray<Element, rank> const& array)
-        {
-            return value_policies::log(array);
-        }
-
-    }  // Anonymous namespace
-
-
-    void bind_log(pybind11::module& module)
-    {
-        module.def("log", log<float, 2>);
-        module.def("log", log<double, 2>);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/sin.cpp b/source/framework/python/src/algorithm/sin.cpp
deleted file mode 100644
index 3d9ea8521..000000000
--- a/source/framework/python/src/algorithm/sin.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "lue/framework/algorithm/value_policies/sin.hpp"
-#include <pybind11/pybind11.h>
-
-
-namespace lue::framework {
-    namespace {
-
-        template<typename Element, Rank rank>
-        PartitionedArray<Element, rank> sin(PartitionedArray<Element, rank> const& array)
-        {
-            return value_policies::sin(array);
-        }
-
-    }  // Anonymous namespace
-
-
-    void bind_sin(pybind11::module& module)
-    {
-        module.def("sin", sin<float, 2>);
-        module.def("sin", sin<double, 2>);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/sqrt.cpp b/source/framework/python/src/algorithm/sqrt.cpp
deleted file mode 100644
index ef3432d09..000000000
--- a/source/framework/python/src/algorithm/sqrt.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "lue/framework/algorithm/value_policies/sqrt.hpp"
-#include <pybind11/pybind11.h>
-
-
-namespace lue::framework {
-    namespace {
-
-        template<typename Element, Rank rank>
-        PartitionedArray<Element, rank> sqrt(PartitionedArray<Element, rank> const& array)
-        {
-            return value_policies::sqrt(array);
-        }
-
-    }  // Anonymous namespace
-
-
-    void bind_sqrt(pybind11::module& module)
-    {
-        // TODO How to document these?
-        module.def("sqrt", sqrt<float, 2>);
-        module.def("sqrt", sqrt<double, 2>);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/tan.cpp b/source/framework/python/src/algorithm/tan.cpp
deleted file mode 100644
index db50fcb23..000000000
--- a/source/framework/python/src/algorithm/tan.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "lue/framework/algorithm/value_policies/tan.hpp"
-#include <pybind11/pybind11.h>
-
-
-namespace lue::framework {
-    namespace {
-
-        template<typename Element, Rank rank>
-        PartitionedArray<Element, rank> tan(PartitionedArray<Element, rank> const& array)
-        {
-            return value_policies::tan(array);
-        }
-
-    }  // Anonymous namespace
-
-
-    void bind_tan(pybind11::module& module)
-    {
-        module.def("tan", tan<float, 2>);
-        module.def("tan", tan<double, 2>);
-    }
-
-}  // namespace lue::framework
diff --git a/source/framework/python/src/algorithm/valid.cpp b/source/framework/python/src/algorithm/valid.cpp
deleted file mode 100644
index 1fde37455..000000000
--- a/source/framework/python/src/algorithm/valid.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "lue/framework/algorithm/value_policies/valid.hpp"
-#include <pybind11/pybind11.h>
-
-
-namespace lue::framework {
-    namespace {
-
-        using BooleanElement = std::uint8_t;
-
-
-        template<typename Element, Rank rank>
-        PartitionedArray<BooleanElement, rank> valid(PartitionedArray<Element, rank> const& array)
-        {
-            using BooleanElement = std::uint8_t;
-
-            return value_policies::valid<BooleanElement>(array);
-        }
-
-    }  // Anonymous namespace
-
-
-    void bind_valid(pybind11::module& module)
-    {
-        module.def("valid", valid<std::uint8_t, 2>);
-        module.def("valid", valid<std::uint32_t, 2>);
-        module.def("valid", valid<std::uint64_t, 2>);
-        module.def("valid", valid<std::int32_t, 2>);
-        module.def("valid", valid<std::int64_t, 2>);
-        module.def("valid", valid<float, 2>);
-        module.def("valid", valid<double, 2>);
-    }
-
-}  // namespace lue::framework


Test patch:
diff --git a/source/framework/algorithm/test/close_to_test.cpp b/source/framework/algorithm/test/close_to_test.cpp
index 1dcdff64f..4ac3eb64b 100644
--- a/source/framework/algorithm/test/close_to_test.cpp
+++ b/source/framework/algorithm/test/close_to_test.cpp
@@ -26,24 +26,24 @@ namespace detail {
 
         // Compare two arrays with different values
         {
-            BOOST_CHECK(none(close_to(array1, array2)).future().get());
+            BOOST_CHECK(none(close_to<std::uint8_t>(array1, array2)).future().get());
         }
 
         // Compare two arrays with the same values
         {
-            BOOST_CHECK(all(close_to(array1, array1)).future().get());
+            BOOST_CHECK(all(close_to<std::uint8_t>(array1, array1)).future().get());
         }
 
         // Compare array with scalar
         // array == scalar
         {
-            BOOST_CHECK(all(close_to(array1, fill_value1)).future().get());
+            BOOST_CHECK(all(close_to<std::uint8_t>(array1, fill_value1)).future().get());
         }
 
         // Compare array with scalar
         // scalar == array
         {
-            BOOST_CHECK(all(close_to(fill_value1, array1)).future().get());
+            BOOST_CHECK(all(close_to<std::uint8_t>(fill_value1, array1)).future().get());
         }
 
         // TODO Add tests with close values
diff --git a/source/framework/algorithm/test/create_partitioned_array_test.cpp b/source/framework/algorithm/test/create_partitioned_array_test.cpp
index c2d76655c..532ba4420 100644
--- a/source/framework/algorithm/test/create_partitioned_array_test.cpp
+++ b/source/framework/algorithm/test/create_partitioned_array_test.cpp
@@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(instantiate_partitions_individually)
     // The number of unique values per partition is 1
     // Per partition a single count >= 0
     lue::PartitionedArray<std::int64_t, 2> counts = lue::partition_count_unique(array);
-    BOOST_CHECK(all(equal_to(counts, std::int64_t{1})).future().get());
+    BOOST_CHECK(all(counts == std::int64_t{1}).future().get());
 
     // The number of unique values in the array equals the number of partitions
     std::set<Element> const unique_values = unique(array).get();
@@ -233,7 +233,7 @@ BOOST_AUTO_TEST_CASE(instantiate_partitions_per_locality)
 
     // The number of unique values per partition is 1
     lue::PartitionedArray<std::int64_t, rank> counts = lue::partition_count_unique(array);
-    BOOST_CHECK(all(equal_to(counts, std::int64_t{1})).future().get());
+    BOOST_CHECK(all(counts == std::int64_t{1}).future().get());
 
     // The number of unique values in the array equals the number of localities
     std::set<Element> const unique_values = unique(array).get();
@@ -298,7 +298,7 @@ BOOST_AUTO_TEST_CASE(use_case_1)
 
     Array array = lue::create_partitioned_array(array_shape, partition_shape, fill_value);
 
-    BOOST_CHECK(all(equal_to(array, fill_value)).future().get());
+    BOOST_CHECK(all(array == fill_value).future().get());
 }
 
 
diff --git a/source/framework/algorithm/test/logical_exclusive_or_test.cpp b/source/framework/algorithm/test/logical_exclusive_or_test.cpp
index c0a1a83bf..51c99c512 100644
--- a/source/framework/algorithm/test/logical_exclusive_or_test.cpp
+++ b/source/framework/algorithm/test/logical_exclusive_or_test.cpp
@@ -26,21 +26,24 @@ namespace detail {
 
         // array || array
         {
-            BOOST_CHECK(all(logical_exclusive_or(array1, array2)).future().get());   // true || false
-            BOOST_CHECK(none(logical_exclusive_or(array1, array1)).future().get());  // true || true
-            BOOST_CHECK(none(logical_exclusive_or(array2, array2)).future().get());  // false || false
+            BOOST_CHECK(
+                all(logical_exclusive_or<std::uint8_t>(array1, array2)).future().get());  // true || false
+            BOOST_CHECK(
+                none(logical_exclusive_or<std::uint8_t>(array1, array1)).future().get());  // true || true
+            BOOST_CHECK(
+                none(logical_exclusive_or<std::uint8_t>(array2, array2)).future().get());  // false || false
         }
 
         // array || scalar
         {
-            BOOST_CHECK(none(logical_exclusive_or(array1, fill_value1)).future().get());
-            BOOST_CHECK(all(logical_exclusive_or(array1, fill_value2)).future().get());
+            BOOST_CHECK(none(logical_exclusive_or<std::uint8_t>(array1, fill_value1)).future().get());
+            BOOST_CHECK(all(logical_exclusive_or<std::uint8_t>(array1, fill_value2)).future().get());
         }
 
         // scalar || array
         {
-            BOOST_CHECK(none(logical_exclusive_or(fill_value1, array1)).future().get());
-            BOOST_CHECK(all(logical_exclusive_or(fill_value2, array1)).future().get());
+            BOOST_CHECK(none(logical_exclusive_or<std::uint8_t>(fill_value1, array1)).future().get());
+            BOOST_CHECK(all(logical_exclusive_or<std::uint8_t>(fill_value2, array1)).future().get());
         }
     }
 
diff --git a/source/framework/algorithm/test/pow_test.cpp b/source/framework/algorithm/test/pow_test.cpp
index 65ac37e92..0624b421f 100644
--- a/source/framework/algorithm/test/pow_test.cpp
+++ b/source/framework/algorithm/test/pow_test.cpp
@@ -2,7 +2,7 @@
 #include "lue/framework/algorithm/create_partitioned_array.hpp"
 #include "lue/framework/algorithm/default_policies/all.hpp"
 #include "lue/framework/algorithm/default_policies/equal_to.hpp"
-#include "lue/framework/algorithm/definition/pow.hpp"
+#include "lue/framework/algorithm/default_policies/pow.hpp"
 #include "lue/framework/test/hpx_unit_test.hpp"
 
 
diff --git a/source/framework/algorithm/test/uniform_test.cpp b/source/framework/algorithm/test/uniform_test.cpp
index 1b6c568f2..d36bf427e 100644
--- a/source/framework/algorithm/test/uniform_test.cpp
+++ b/source/framework/algorithm/test/uniform_test.cpp
@@ -133,8 +133,5 @@ BOOST_AUTO_TEST_CASE(use_case_1)
 
     Array array = uniform(array_shape, partition_shape, min_value, max_value);
 
-    BOOST_CHECK(
-        all(logical_and(greater_than_equal_to(array, min_value), less_than_equal_to(array, max_value)))
-            .future()
-            .get());
+    BOOST_CHECK(all(array >= min_value && array <= max_value).future().get());
 }
diff --git a/source/framework/python/test/algorithm/abs_test.py b/source/framework/python/test/algorithm/abs_test.py
deleted file mode 100644
index 638a4b842..000000000
--- a/source/framework/python/test/algorithm/abs_test.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import numpy as np
-
-import lue.framework as lfr
-import lue_test
-
-
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class AbsTest(lue_test.TestCase):
-    @lue_test.framework_test_case
-    def test_overloads(self):
-        array_shape = (60, 40)
-        fill_value = 5
-
-        for dtype in [np.int32, np.int64, np.float32, np.float64]:
-            array = lfr.create_array(array_shape, dtype, fill_value)
-            lfr.abs(array)
diff --git a/source/framework/python/test/algorithm/acos_test.py b/source/framework/python/test/algorithm/acos_test.py
deleted file mode 100644
index 3a3c7e30b..000000000
--- a/source/framework/python/test/algorithm/acos_test.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import numpy as np
-
-import lue.framework as lfr
-import lue_test
-
-
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class ACosTest(lue_test.TestCase):
-    @lue_test.framework_test_case
-    def test_overloads(self):
-        array_shape = (60, 40)
-        fill_value = 5.5
-
-        for dtype in [np.float32, np.float64]:
-            array = lfr.create_array(array_shape, dtype, fill_value)
-            lfr.acos(array)
diff --git a/source/framework/python/test/algorithm/asin_test.py b/source/framework/python/test/algorithm/asin_test.py
deleted file mode 100644
index 4cff05658..000000000
--- a/source/framework/python/test/algorithm/asin_test.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import numpy as np
-
-import lue.framework as lfr
-import lue_test
-
-
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class ASinTest(lue_test.TestCase):
-    @lue_test.framework_test_case
-    def test_overloads(self):
-        array_shape = (60, 40)
-        fill_value = 5.5
-
-        for dtype in [np.float32, np.float64]:
-            array = lfr.create_array(array_shape, dtype, fill_value)
-            lfr.asin(array)
diff --git a/source/framework/python/test/algorithm/atan_test.py b/source/framework/python/test/algorithm/atan_test.py
deleted file mode 100644
index 9541bbae9..000000000
--- a/source/framework/python/test/algorithm/atan_test.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import numpy as np
-
-import lue.framework as lfr
-import lue_test
-
-
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class ATanTest(lue_test.TestCase):
-    @lue_test.framework_test_case
-    def test_overloads(self):
-        array_shape = (60, 40)
-        fill_value = 5.5
-
-        for dtype in [np.float32, np.float64]:
-            array = lfr.create_array(array_shape, dtype, fill_value)
-            lfr.atan(array)
diff --git a/source/framework/python/test/algorithm/cos_test.py b/source/framework/python/test/algorithm/cos_test.py
deleted file mode 100644
index 1b8312712..000000000
--- a/source/framework/python/test/algorithm/cos_test.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import numpy as np
-
-import lue.framework as lfr
-import lue_test
-
-
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class CosTest(lue_test.TestCase):
-    @lue_test.framework_test_case
-    def test_overloads(self):
-        array_shape = (60, 40)
-        fill_value = 5.5
-
-        for dtype in [np.float32, np.float64]:
-            array = lfr.create_array(array_shape, dtype, fill_value)
-            lfr.cos(array)
diff --git a/source/framework/python/test/algorithm/exp_test.py b/source/framework/python/test/algorithm/exp_test.py
deleted file mode 100644
index 03c815357..000000000
--- a/source/framework/python/test/algorithm/exp_test.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import numpy as np
-
-import lue.framework as lfr
-import lue_test
-
-
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class ExpTest(lue_test.TestCase):
-    @lue_test.framework_test_case
-    def test_overloads(self):
-        array_shape = (60, 40)
-        fill_value = 5.5
-
-        for dtype in [np.float32, np.float64]:
-            array = lfr.create_array(array_shape, dtype, fill_value)
-            lfr.exp(array)
diff --git a/source/framework/python/test/algorithm/local_operation/abs_test.py b/source/framework/python/test/algorithm/local_operation/abs_test.py
new file mode 100644
index 000000000..5d280ccca
--- /dev/null
+++ b/source/framework/python/test/algorithm/local_operation/abs_test.py
@@ -0,0 +1,17 @@
+import lue.framework as lfr
+import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
+
+
+class AbsTest(OperationTest):
+    @lue_test.framework_test_case
+    def test_overloads(self):
+
+        for type_ in set(self.numeric_types) - set(self.unsigned_integral_types):
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.abs(array)
+            _ = lfr.abs(scalar)
+            _ = lfr.abs(value)
diff --git a/source/framework/python/test/algorithm/local_operation/acos_test.py b/source/framework/python/test/algorithm/local_operation/acos_test.py
new file mode 100644
index 000000000..5c337c7be
--- /dev/null
+++ b/source/framework/python/test/algorithm/local_operation/acos_test.py
@@ -0,0 +1,17 @@
+import lue.framework as lfr
+import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
+
+
+class ACosTest(OperationTest):
+    @lue_test.framework_test_case
+    def test_overloads(self):
+
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.acos(array)
+            _ = lfr.acos(scalar)
+            _ = lfr.acos(value)
diff --git a/source/framework/python/test/algorithm/local_operation/add_test.py b/source/framework/python/test/algorithm/local_operation/add_test.py
index b2131c819..bbb881da4 100644
--- a/source/framework/python/test/algorithm/local_operation/add_test.py
+++ b/source/framework/python/test/algorithm/local_operation/add_test.py
@@ -1,9 +1,6 @@
-import numpy as np
-
 import lue.framework as lfr
 import lue_test
-
-from ..operation_test import OperationTest, setUpModule, tearDownModule
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
 
 
 class AddTest(OperationTest):
@@ -15,23 +12,17 @@ def test_overloads(self):
             scalar = self.scalar[type_]
             array = self.array[type_]
 
-            # value icw scalar
-            _ = lfr.add(value, scalar)
-            _ = lfr.add(scalar, value)
-
-            _ = value + scalar
-            _ = scalar + value
-
-            # value icw array
-            _ = lfr.add(value, array)
+            # array icw something else
+            _ = lfr.add(array, array)
+            _ = lfr.add(array, scalar)
             _ = lfr.add(array, value)
-
-            _ = value + array
-            _ = array + value
-
-            # scalar icw array
             _ = lfr.add(scalar, array)
-            _ = lfr.add(array, scalar)
+            _ = lfr.add(value, array)
+
+            # scalar icw something else, if not handled already
+            _ = lfr.add(scalar, scalar)
+            _ = lfr.add(scalar, value)
+            _ = lfr.add(value, scalar)
 
-            _ = scalar + array
-            _ = array + scalar
+            # value icw something else, if not handled already
+            _ = lfr.add(value, value)
diff --git a/source/framework/python/test/algorithm/local_operation/asin_test.py b/source/framework/python/test/algorithm/local_operation/asin_test.py
new file mode 100644
index 000000000..b7fa1ba22
--- /dev/null
+++ b/source/framework/python/test/algorithm/local_operation/asin_test.py
@@ -0,0 +1,17 @@
+import lue.framework as lfr
+import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
+
+
+class ASinTest(OperationTest):
+    @lue_test.framework_test_case
+    def test_overloads(self):
+
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.asin(array)
+            _ = lfr.asin(scalar)
+            _ = lfr.asin(value)
diff --git a/source/framework/python/test/algorithm/local_operation/atan_test.py b/source/framework/python/test/algorithm/local_operation/atan_test.py
new file mode 100644
index 000000000..b8e05eb16
--- /dev/null
+++ b/source/framework/python/test/algorithm/local_operation/atan_test.py
@@ -0,0 +1,17 @@
+import lue.framework as lfr
+import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
+
+
+class ATanTest(OperationTest):
+    @lue_test.framework_test_case
+    def test_overloads(self):
+
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.atan(array)
+            _ = lfr.atan(scalar)
+            _ = lfr.atan(value)
diff --git a/source/framework/python/test/algorithm/local_operation/cast_test.py b/source/framework/python/test/algorithm/local_operation/cast_test.py
index ff28a0bcf..85311a638 100644
--- a/source/framework/python/test/algorithm/local_operation/cast_test.py
+++ b/source/framework/python/test/algorithm/local_operation/cast_test.py
@@ -1,41 +1,19 @@
-import numpy as np
-
 import lue.framework as lfr
 import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
 
 
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class CastTest(lue_test.TestCase):
+class CastTest(OperationTest):
     @lue_test.framework_test_case
     def test_overloads(self):
-        array_shape = (60, 40)
-        fill_value = 5
 
-        for input_type in [
-            np.uint8,
-            np.uint32,
-            np.int32,
-            np.uint64,
-            np.int64,
-            np.float32,
-            np.float64,
-        ]:
-            input_array = lfr.create_array(array_shape, input_type, fill_value)
+        for input_type in self.numeric_types:
+            value = self.value[input_type]
+            scalar = self.scalar[input_type]
+            array = self.array[input_type]
+
+            for output_type in self.numeric_types:
 
-            for output_type in [
-                np.uint8,
-                np.uint32,
-                np.int32,
-                np.uint64,
-                np.int64,
-                np.float32,
-                np.float64,
-            ]:
-                _ = lfr.cast(input_array, output_type)
+                _ = lfr.cast(array, output_type)
+                _ = lfr.cast(scalar, output_type)
+                _ = lfr.cast(value, output_type)
diff --git a/source/framework/python/test/algorithm/local_operation/ceil_test.py b/source/framework/python/test/algorithm/local_operation/ceil_test.py
index eb8c969c0..65b98eef5 100644
--- a/source/framework/python/test/algorithm/local_operation/ceil_test.py
+++ b/source/framework/python/test/algorithm/local_operation/ceil_test.py
@@ -1,23 +1,17 @@
-import numpy as np
-
 import lue.framework as lfr
 import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
 
 
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class CeilTest(lue_test.TestCase):
+class CeilTest(OperationTest):
     @lue_test.framework_test_case
     def test_overloads(self):
-        array_shape = (60, 40)
-        fill_value = 5.5
 
-        for dtype in [np.float32, np.float64]:
-            array = lfr.create_array(array_shape, dtype, fill_value)
-            lfr.ceil(array)
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.ceil(array)
+            _ = lfr.ceil(scalar)
+            _ = lfr.ceil(value)
diff --git a/source/framework/python/test/algorithm/local_operation/cos_test.py b/source/framework/python/test/algorithm/local_operation/cos_test.py
new file mode 100644
index 000000000..8f1006294
--- /dev/null
+++ b/source/framework/python/test/algorithm/local_operation/cos_test.py
@@ -0,0 +1,17 @@
+import lue.framework as lfr
+import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
+
+
+class CosTest(OperationTest):
+    @lue_test.framework_test_case
+    def test_overloads(self):
+
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.cos(array)
+            _ = lfr.cos(scalar)
+            _ = lfr.cos(value)
diff --git a/source/framework/python/test/algorithm/local_operation/divide_test.py b/source/framework/python/test/algorithm/local_operation/divide_test.py
new file mode 100644
index 000000000..8551af0f8
--- /dev/null
+++ b/source/framework/python/test/algorithm/local_operation/divide_test.py
@@ -0,0 +1,28 @@
+import lue.framework as lfr
+import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
+
+
+class DivideTest(OperationTest):
+    @lue_test.framework_test_case
+    def test_overloads(self):
+
+        for type_ in self.floating_point_types:
+            value = self.value[type_]
+            scalar = self.scalar[type_]
+            array = self.array[type_]
+
+            # array icw something else
+            _ = lfr.divide(array, array)
+            _ = lfr.divide(array, scalar)
+            _ = lfr.divide(array, value)
+            _ = lfr.divide(scalar, array)
+            _ = lfr.divide(value, array)
+
+            # scalar icw something else, if not handled already
+            _ = lfr.divide(scalar, scalar)
+            _ = lfr.divide(scalar, value)
+            _ = lfr.divide(value, scalar)
+
+            # value icw something else, if not handled already
+            _ = lfr.divide(value, value)
diff --git a/source/framework/python/test/algorithm/local_operation/exp_test.py b/source/framework/python/test/algorithm/local_operation/exp_test.py
new file mode 100644
index 000000000..25543e88d
--- /dev/null
+++ b/source/framework/python/test/algorithm/local_operation/exp_test.py
@@ -0,0 +1,17 @@
+import lue.framework as lfr
+import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
+
+
+class ExpTest(OperationTest):
+    @lue_test.framework_test_case
+    def test_overloads(self):
+
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.exp(array)
+            _ = lfr.exp(scalar)
+            _ = lfr.exp(value)
diff --git a/source/framework/python/test/algorithm/local_operation/floor_test.py b/source/framework/python/test/algorithm/local_operation/floor_test.py
index ecae73cf9..047019e71 100644
--- a/source/framework/python/test/algorithm/local_operation/floor_test.py
+++ b/source/framework/python/test/algorithm/local_operation/floor_test.py
@@ -1,23 +1,17 @@
-import numpy as np
-
 import lue.framework as lfr
 import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
 
 
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class FloorTest(lue_test.TestCase):
+class FloorTest(OperationTest):
     @lue_test.framework_test_case
     def test_overloads(self):
-        array_shape = (60, 40)
-        fill_value = 5.5
 
-        for dtype in [np.float32, np.float64]:
-            array = lfr.create_array(array_shape, dtype, fill_value)
-            lfr.floor(array)
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.floor(array)
+            _ = lfr.floor(scalar)
+            _ = lfr.floor(value)
diff --git a/source/framework/python/test/algorithm/local_operation/log10_test.py b/source/framework/python/test/algorithm/local_operation/log10_test.py
index 04fe59107..6d7b6bfeb 100644
--- a/source/framework/python/test/algorithm/local_operation/log10_test.py
+++ b/source/framework/python/test/algorithm/local_operation/log10_test.py
@@ -1,23 +1,17 @@
-import numpy as np
-
 import lue.framework as lfr
 import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
 
 
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class Log10Test(lue_test.TestCase):
+class Log10Test(OperationTest):
     @lue_test.framework_test_case
     def test_overloads(self):
-        array_shape = (60, 40)
-        dtype = np.float64
-        fill_value = 5.5
-        array = lfr.create_array(array_shape, dtype, fill_value)
 
-        lfr.log10(array)
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.log10(array)
+            _ = lfr.log10(scalar)
+            _ = lfr.log10(value)
diff --git a/source/framework/python/test/algorithm/local_operation/log_test.py b/source/framework/python/test/algorithm/local_operation/log_test.py
new file mode 100644
index 000000000..b37476540
--- /dev/null
+++ b/source/framework/python/test/algorithm/local_operation/log_test.py
@@ -0,0 +1,17 @@
+import lue.framework as lfr
+import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
+
+
+class LogTest(OperationTest):
+    @lue_test.framework_test_case
+    def test_overloads(self):
+
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.log(array)
+            _ = lfr.log(scalar)
+            _ = lfr.log(value)
diff --git a/source/framework/python/test/algorithm/local_operation/logical_not_test.py b/source/framework/python/test/algorithm/local_operation/logical_not_test.py
index 70c427365..7cab31ce2 100644
--- a/source/framework/python/test/algorithm/local_operation/logical_not_test.py
+++ b/source/framework/python/test/algorithm/local_operation/logical_not_test.py
@@ -1,24 +1,17 @@
-import numpy as np
-
 import lue.framework as lfr
 import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
 
 
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class LogicalNotTest(lue_test.TestCase):
+class LogicalNotTest(OperationTest):
     @lue_test.framework_test_case
     def test_overloads(self):
-        array_shape = (60, 40)
-        fill_value = 5
 
-        for dtype in [np.uint8, np.int32, np.uint32, np.int64, np.uint64]:
-            array = lfr.create_array(array_shape, dtype, fill_value)
-            tmp = lfr.logical_not(array)
-            tmp = ~array
+        for type_ in self.integral_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.logical_not(array)
+            _ = lfr.logical_not(scalar)
+            _ = lfr.logical_not(value)
diff --git a/source/framework/python/test/algorithm/local_operation/multiply_test.py b/source/framework/python/test/algorithm/local_operation/multiply_test.py
new file mode 100644
index 000000000..9bd8b4286
--- /dev/null
+++ b/source/framework/python/test/algorithm/local_operation/multiply_test.py
@@ -0,0 +1,28 @@
+import lue.framework as lfr
+import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
+
+
+class MultiplyTest(OperationTest):
+    @lue_test.framework_test_case
+    def test_overloads(self):
+
+        for type_ in self.floating_point_types:
+            value = self.value[type_]
+            scalar = self.scalar[type_]
+            array = self.array[type_]
+
+            # array icw something else
+            _ = lfr.multiply(array, array)
+            _ = lfr.multiply(array, scalar)
+            _ = lfr.multiply(array, value)
+            _ = lfr.multiply(scalar, array)
+            _ = lfr.multiply(value, array)
+
+            # scalar icw something else, if not handled already
+            _ = lfr.multiply(scalar, scalar)
+            _ = lfr.multiply(scalar, value)
+            _ = lfr.multiply(value, scalar)
+
+            # value icw something else, if not handled already
+            _ = lfr.multiply(value, value)
diff --git a/source/framework/python/test/algorithm/local_operation/negate_test.py b/source/framework/python/test/algorithm/local_operation/negate_test.py
new file mode 100644
index 000000000..1d941bacb
--- /dev/null
+++ b/source/framework/python/test/algorithm/local_operation/negate_test.py
@@ -0,0 +1,17 @@
+import lue.framework as lfr
+import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
+
+
+class NegateTest(OperationTest):
+    @lue_test.framework_test_case
+    def test_overloads(self):
+
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.negate(array)
+            _ = lfr.negate(scalar)
+            _ = lfr.negate(value)
diff --git a/source/framework/python/test/algorithm/local_operation/round_test.py b/source/framework/python/test/algorithm/local_operation/round_test.py
index ae6cc0a01..697bd7be1 100644
--- a/source/framework/python/test/algorithm/local_operation/round_test.py
+++ b/source/framework/python/test/algorithm/local_operation/round_test.py
@@ -1,23 +1,17 @@
-import numpy as np
-
 import lue.framework as lfr
 import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
 
 
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class RoundTest(lue_test.TestCase):
+class RoundTest(OperationTest):
     @lue_test.framework_test_case
     def test_overloads(self):
-        array_shape = (60, 40)
-        fill_value = 5.5
 
-        for dtype in [np.float32, np.float64]:
-            array = lfr.create_array(array_shape, dtype, fill_value)
-            lfr.round(array)
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.round(array)
+            _ = lfr.round(scalar)
+            _ = lfr.round(value)
diff --git a/source/framework/python/test/algorithm/local_operation/sin_test.py b/source/framework/python/test/algorithm/local_operation/sin_test.py
new file mode 100644
index 000000000..15c93851c
--- /dev/null
+++ b/source/framework/python/test/algorithm/local_operation/sin_test.py
@@ -0,0 +1,17 @@
+import lue.framework as lfr
+import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
+
+
+class SinTest(OperationTest):
+    @lue_test.framework_test_case
+    def test_overloads(self):
+
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.sin(array)
+            _ = lfr.sin(scalar)
+            _ = lfr.sin(value)
diff --git a/source/framework/python/test/algorithm/local_operation/sqrt_test.py b/source/framework/python/test/algorithm/local_operation/sqrt_test.py
new file mode 100644
index 000000000..b10778179
--- /dev/null
+++ b/source/framework/python/test/algorithm/local_operation/sqrt_test.py
@@ -0,0 +1,17 @@
+import lue.framework as lfr
+import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
+
+
+class SqrtTest(OperationTest):
+    @lue_test.framework_test_case
+    def test_overloads(self):
+
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.sqrt(array)
+            _ = lfr.sqrt(scalar)
+            _ = lfr.sqrt(value)
diff --git a/source/framework/python/test/algorithm/local_operation/subtract_test.py b/source/framework/python/test/algorithm/local_operation/subtract_test.py
new file mode 100644
index 000000000..bde356ea0
--- /dev/null
+++ b/source/framework/python/test/algorithm/local_operation/subtract_test.py
@@ -0,0 +1,28 @@
+import lue.framework as lfr
+import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
+
+
+class SubtractTest(OperationTest):
+    @lue_test.framework_test_case
+    def test_overloads(self):
+
+        for type_ in self.numeric_types:
+            value = self.value[type_]
+            scalar = self.scalar[type_]
+            array = self.array[type_]
+
+            # array icw something else
+            _ = lfr.subtract(array, array)
+            _ = lfr.subtract(array, scalar)
+            _ = lfr.subtract(array, value)
+            _ = lfr.subtract(scalar, array)
+            _ = lfr.subtract(value, array)
+
+            # scalar icw something else, if not handled already
+            _ = lfr.subtract(scalar, scalar)
+            _ = lfr.subtract(scalar, value)
+            _ = lfr.subtract(value, scalar)
+
+            # value icw something else, if not handled already
+            _ = lfr.subtract(value, value)
diff --git a/source/framework/python/test/algorithm/local_operation/tan_test.py b/source/framework/python/test/algorithm/local_operation/tan_test.py
new file mode 100644
index 000000000..461316fd6
--- /dev/null
+++ b/source/framework/python/test/algorithm/local_operation/tan_test.py
@@ -0,0 +1,17 @@
+import lue.framework as lfr
+import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
+
+
+class TanTest(OperationTest):
+    @lue_test.framework_test_case
+    def test_overloads(self):
+
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = lfr.tan(array)
+            _ = lfr.tan(scalar)
+            _ = lfr.tan(value)
diff --git a/source/framework/python/test/algorithm/local_operation/valid_test.py b/source/framework/python/test/algorithm/local_operation/valid_test.py
new file mode 100644
index 000000000..99a2ff715
--- /dev/null
+++ b/source/framework/python/test/algorithm/local_operation/valid_test.py
@@ -0,0 +1,17 @@
+import lue.framework as lfr
+import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
+
+
+class ValidTest(OperationTest):
+    @lue_test.framework_test_case
+    def test_overloads(self):
+
+        for type_ in self.numeric_types:
+            value = self.value[type_]
+            scalar = self.scalar[type_]
+            array = self.array[type_]
+
+            _ = lfr.valid(array)
+            _ = lfr.valid(scalar)
+            _ = lfr.valid(value)
diff --git a/source/framework/python/test/algorithm/log_test.py b/source/framework/python/test/algorithm/log_test.py
deleted file mode 100644
index 05d84d734..000000000
--- a/source/framework/python/test/algorithm/log_test.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import numpy as np
-
-import lue.framework as lfr
-import lue_test
-
-
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class LogTest(lue_test.TestCase):
-    @lue_test.framework_test_case
-    def test_overloads(self):
-        array_shape = (60, 40)
-        dtype = np.float64
-        fill_value = 5.5
-        array = lfr.create_array(array_shape, dtype, fill_value)
-
-        lfr.log(array)
diff --git a/source/framework/python/test/algorithm/operation_test.py b/source/framework/python/test/algorithm/operation_test.py
deleted file mode 100644
index a394fe617..000000000
--- a/source/framework/python/test/algorithm/operation_test.py
+++ /dev/null
@@ -1,54 +0,0 @@
-import numpy as np
-
-import lue.framework as lfr
-import lue_test
-
-
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class OperationTest(lue_test.TestCase):
-    @classmethod
-    @lue_test.framework_test_case
-    def setUpClass(cls):
-        cls.array_shape = (60, 40)
-        cls.partition_shape = (10, 10)
-
-        cls.numeric_types = [
-            np.uint8,
-            # np.int8,
-            np.uint32,
-            np.uint64,
-            np.int32,
-            np.int64,
-            np.float32,
-            np.float64,
-        ]
-
-        cls.value = {
-            np.uint8: np.uint8(8),
-            # np.int8: np.int8(-8),
-            np.uint32: np.uint32(32),
-            np.uint64: np.uint32(64),
-            np.int32: np.int64(-32),
-            np.int64: np.int64(-64),
-            np.float32: np.float32(3.2),
-            np.float64: np.float64(6.4),
-        }
-
-        cls.array = {
-            type_: lfr.create_array(
-                cls.array_shape,
-                type_,
-                fill_value=value,
-                partition_shape=cls.partition_shape,
-            )
-            for type_, value in cls.value.items()
-        }
-
-        cls.scalar = {type_: lfr.maximum(array) for type_, array in cls.array.items()}
diff --git a/source/framework/python/test/algorithm/sin_test.py b/source/framework/python/test/algorithm/sin_test.py
deleted file mode 100644
index 11ca99f10..000000000
--- a/source/framework/python/test/algorithm/sin_test.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import numpy as np
-
-import lue.framework as lfr
-import lue_test
-
-
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class SinTest(lue_test.TestCase):
-    @lue_test.framework_test_case
-    def test_overloads(self):
-        array_shape = (60, 40)
-        fill_value = 5.5
-
-        for dtype in [np.float32, np.float64]:
-            array = lfr.create_array(array_shape, dtype, fill_value)
-            lfr.sin(array)
diff --git a/source/framework/python/test/algorithm/sqrt_test.py b/source/framework/python/test/algorithm/sqrt_test.py
deleted file mode 100644
index fbe6f93a9..000000000
--- a/source/framework/python/test/algorithm/sqrt_test.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import numpy as np
-
-import lue.framework as lfr
-import lue_test
-
-
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class SqrtTest(lue_test.TestCase):
-    @lue_test.framework_test_case
-    def test_overloads(self):
-        array_shape = (60, 40)
-        fill_value = 5.5
-
-        for dtype in [np.float32, np.float64]:
-            array = lfr.create_array(array_shape, dtype, fill_value)
-            lfr.sqrt(array)
diff --git a/source/framework/python/test/algorithm/tan_test.py b/source/framework/python/test/algorithm/tan_test.py
deleted file mode 100644
index f651beaae..000000000
--- a/source/framework/python/test/algorithm/tan_test.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import numpy as np
-
-import lue.framework as lfr
-import lue_test
-
-
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class TanTest(lue_test.TestCase):
-    @lue_test.framework_test_case
-    def test_overloads(self):
-        array_shape = (60, 40)
-        fill_value = 5.5
-
-        for dtype in [np.float32, np.float64]:
-            array = lfr.create_array(array_shape, dtype, fill_value)
-            lfr.tan(array)
diff --git a/source/framework/python/test/algorithm/valid_test.py b/source/framework/python/test/algorithm/valid_test.py
deleted file mode 100644
index eb1fee41d..000000000
--- a/source/framework/python/test/algorithm/valid_test.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import numpy as np
-
-import lue.framework as lfr
-import lue_test
-
-
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class ValidTest(lue_test.TestCase):
-    @lue_test.framework_test_case
-    def test_all_valid(self):
-        array_shape = (60, 40)
-        dtype = np.int32
-        fill_value = 5  # Valid value
-        array = lfr.create_array(array_shape, dtype, fill_value)
-
-        result = lfr.valid(array)
-
-        self.assertTrue(lfr.all(result == 1).future.get())
-
-    @lue_test.framework_test_case
-    def test_all_invalid(self):
-        array_shape = (60, 40)
-        dtype = np.dtype(np.int32)
-        fill_value = 5  # Valid value
-        array = lfr.create_array(array_shape, dtype, fill_value)
-
-        # Turn all valid values into invalid ones
-        array = lfr.where(array != fill_value, 7)
-
-        result = lfr.valid(array)
-
-        self.assertTrue(lfr.all(result == 0).future.get())
diff --git a/source/framework/python/test/core/partitioned_array_test.py b/source/framework/python/test/core/partitioned_array_test.py
index 59b8f2bce..962ba0b32 100644
--- a/source/framework/python/test/core/partitioned_array_test.py
+++ b/source/framework/python/test/core/partitioned_array_test.py
@@ -1,141 +1,176 @@
-import numpy as np
-
-import lue.framework as lfr
 import lue_test
+from lue_test.operation_test import OperationTest, setUpModule, tearDownModule
 
 
-def setUpModule():
-    lue_test.start_hpx_runtime()
-
-
-def tearDownModule():
-    lue_test.stop_hpx_runtime()
-
-
-class CreatePartitionedArrayTest(lue_test.TestCase):
-    @classmethod
-    @lue_test.framework_test_case
-    def setUpClass(cls):
-        cls.value = 5.5
-        cls.array = lfr.create_array(
-            array_shape=(60, 40),
-            partition_shape=(10, 10),
-            dtype=np.float32,
-            fill_value=cls.value,
-        )
-        cls.value_f = lfr.maximum(cls.array)
-
+class CreatePartitionedArrayTest(OperationTest):
     @lue_test.framework_test_case
     def test_operator_add_overloads(self):
-        array, value, value_f = self.array, self.value, self.value_f
-        tmp = array + array
-        tmp = array + value
-        tmp = array + value_f
-        tmp = value + array
-        tmp = value_f + array
+        for type_ in self.numeric_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = array + array
+            _ = array + scalar
+            _ = array + value
+            _ = scalar + array
+            _ = value + array
 
     @lue_test.framework_test_case
     def test_operator_sub_overloads(self):
-        array, value, value_f = self.array, self.value, self.value_f
-        tmp = array - array
-        tmp = array - value
-        tmp = array - value_f
-        tmp = value - array
-        tmp = value_f - array
+        for type_ in self.numeric_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = array - array
+            _ = array - scalar
+            _ = array - value
+            _ = scalar - array
+            _ = value - array
 
     @lue_test.framework_test_case
     def test_operator_mul_overloads(self):
-        array, value, value_f = self.array, self.value, self.value_f
-        tmp = array * array
-        tmp = array * value
-        tmp = array * value_f
-        tmp = value * array
-        tmp = value_f * array
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = array * array
+            _ = array * scalar
+            _ = array * value
+            _ = scalar * array
+            _ = value * array
 
     @lue_test.framework_test_case
     def test_operator_div_overloads(self):
-        array, value, value_f = self.array, self.value, self.value_f
-        tmp = array / array
-        tmp = array / value
-        tmp = array / value_f
-        tmp = value / array
-        tmp = value_f / array
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = array / array
+            _ = array / scalar
+            _ = array / value
+            _ = scalar / array
+            _ = value / array
 
     @lue_test.framework_test_case
     def test_operator_gt_overloads(self):
-        array, value, value_f = self.array, self.value, self.value_f
-        tmp = array > array
-        tmp = array > value
-        tmp = array > value_f
-        tmp = value > array
-        tmp = value_f > array
+        for type_ in self.numeric_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = array > array
+            _ = array > scalar
+            _ = array > value
+            _ = scalar > array
+            # _ = value > array
 
     @lue_test.framework_test_case
     def test_operator_ge_overloads(self):
-        array, value, value_f = self.array, self.value, self.value_f
-        tmp = array >= array
-        tmp = array >= value
-        tmp = array >= value_f
-        tmp = value >= array
-        tmp = value_f >= array
+        for type_ in self.numeric_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = array >= array
+            _ = array >= scalar
+            _ = array >= value
+            _ = scalar >= array
+            # _ = value >= array
 
     @lue_test.framework_test_case
     def test_operator_eq_overloads(self):
-        array, value, value_f = self.array, self.value, self.value_f
-        tmp = array == array
-        tmp = array == value
-        tmp = array == value_f
-        tmp = value == array
-        tmp = value_f == array
+        for type_ in self.numeric_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = array == array
+            _ = array == scalar
+            _ = array == value
+            _ = scalar == array
+            # _ = value == array
 
     @lue_test.framework_test_case
     def test_operator_ne_overloads(self):
-        array, value, value_f = self.array, self.value, self.value_f
-        tmp = array != array
-        tmp = array != value
-        tmp = array != value_f
-        tmp = value != array
-        tmp = value_f != array
+        for type_ in self.numeric_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = array != array
+            _ = array != scalar
+            _ = array != value
+            _ = scalar != array
+            # _ = value != array
 
     @lue_test.framework_test_case
     def test_operator_lt_overloads(self):
-        array, value, value_f = self.array, self.value, self.value_f
-        tmp = array < array
-        tmp = array < value
-        tmp = array < value_f
-        tmp = value < array
-        tmp = value_f < array
+        for type_ in self.numeric_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = array < array
+            _ = array < scalar
+            _ = array < value
+            _ = scalar < array
+            # _ = value < array
 
     @lue_test.framework_test_case
     def test_operator_le_overloads(self):
-        array, value, value_f = self.array, self.value, self.value_f
-        tmp = array <= array
-        tmp = array <= value
-        tmp = array <= value_f
-        tmp = value <= array
-        tmp = value_f <= array
+        for type_ in self.numeric_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = array <= array
+            _ = array <= scalar
+            _ = array <= value
+            _ = scalar <= array
+            # _ = value <= array
 
     @lue_test.framework_test_case
     def test_operator_abs_overloads(self):
-        array = self.array
-        tmp = abs(array)
+        for type_ in set(self.numeric_types) - set(self.unsigned_integral_types):
+            array = self.array[type_]
+
+            _ = abs(array)
 
     @lue_test.framework_test_case
     def test_operator_pow_overloads(self):
-        array, value, value_f = self.array, self.value, self.value_f
-        tmp = array**array
-        tmp = array**value
-        tmp = array**value_f
-        tmp = value**array
-        tmp = value_f**array
+        for type_ in self.floating_point_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+            value = self.value[type_]
+
+            _ = array**array
+            _ = array**scalar
+            _ = array**value
+            _ = scalar**array
+            _ = value**array
+
+    @lue_test.framework_test_case
+    def test_operator_bool_overloads(self):
+        for type_ in self.numeric_types:
+            array = self.array[type_]
+            scalar = self.scalar[type_]
+
+            with self.assertRaises(ValueError):
+                _ = bool(array)
+                _ = bool(scalar)
 
     @lue_test.framework_test_case
-    def test_operator_bool(self):
-        array = self.array
-        with self.assertRaises(ValueError):
-            tmp = bool(array)
+    def test_operator_negate_overloads(self):
+        for type_ in self.signed_integral_types:
+            array = self.array[type_]
+            _ = -array
 
     @lue_test.framework_test_case
-    def test_operator_negate(self):
-        array = self.array
-        tmp = -array
+    def test_operator_logical_not_overloads(self):
+        for type_ in self.integral_types:
+            array = self.array[type_]
+            _ = ~array
diff --git a/source/framework/python/test/core/scalar_test.py b/source/framework/python/test/core/scalar_test.py
index 6fb282c44..80f954e2e 100644
--- a/source/framework/python/test/core/scalar_test.py
+++ b/source/framework/python/test/core/scalar_test.py
@@ -18,40 +18,14 @@ class ScalarTest(lue_test.TestCase):
     @classmethod
     @lue_test.framework_test_case
     def setUpClass(cls):
-        cls.signed_integral_types = [
-            # np.int8,
-            np.int32,
-            np.int64,
-        ]
-        cls.unsigned_integral_types = [
-            np.uint8,
-            np.uint32,
-            np.uint64,
-        ]
-        cls.integral_types = cls.signed_integral_types + cls.unsigned_integral_types
-        cls.floating_point_types = [
-            np.float32,
-            np.float64,
-        ]
-
-        cls.numeric_types = cls.integral_types + cls.floating_point_types
-
-        cls.value_by_type = {
-            np.uint8: np.uint8(8),
-            # np.int8: np.int8(-8),
-            np.uint32: np.uint32(32),
-            np.uint64: np.uint32(64),
-            np.int32: np.int64(-32),
-            np.int64: np.int64(-64),
-            np.float32: np.float32(3.2),
-            np.float64: np.float64(6.4),
-        }
-
-        cls.dtype_by_floating_point_type = {
-            type_: np.dtype(type_) for type_ in cls.floating_point_types
-        }
-
-        cls.dtype_by_type = {type_: np.dtype(type_) for type_ in cls.numeric_types}
+        cls.signed_integral_types = lue_test.signed_integral_types
+        cls.unsigned_integral_types = lue_test.unsigned_integral_types
+        cls.integral_types = lue_test.integral_types
+        cls.floating_point_types = lue_test.floating_point_types
+        cls.numeric_types = lue_test.numeric_types
+        cls.value_by_type = lue_test.value_by_type
+        cls.dtype_by_floating_point_type = lue_test.dtype_by_floating_point_type
+        cls.dtype_by_type = lue_test.dtype_by_type
 
         cls.scalar_by_dtype = {
             cls.dtype_by_type[type_]: lfr.create_scalar(
diff --git a/source/framework/python/test/lue_test/__init__.py b/source/framework/python/test/lue_test/__init__.py
index f91d798b1..4350bb4e4 100644
--- a/source/framework/python/test/lue_test/__init__.py
+++ b/source/framework/python/test/lue_test/__init__.py
@@ -1,2 +1,3 @@
 from .test_case import *
+from .type import *
 from .util import *
diff --git a/source/framework/python/test/lue_test/operation_test.py b/source/framework/python/test/lue_test/operation_test.py
new file mode 100644
index 000000000..44adf5537
--- /dev/null
+++ b/source/framework/python/test/lue_test/operation_test.py
@@ -0,0 +1,47 @@
+import numpy as np
+
+import lue.framework as lfr
+import lue_test
+
+
+def setUpModule():
+    lue_test.start_hpx_runtime()
+
+
+def tearDownModule():
+    lue_test.stop_hpx_runtime()
+
+
+class OperationTest(lue_test.TestCase):
+    @classmethod
+    @lue_test.framework_test_case
+    def setUpClass(cls):
+        cls.boolean_types = lue_test.boolean_types
+        cls.unsigned_integral_types = lue_test.unsigned_integral_types
+        cls.signed_integral_types = lue_test.signed_integral_types
+        cls.integral_types = lue_test.integral_types
+        cls.floating_point_types = lue_test.floating_point_types
+        cls.numeric_types = lue_test.numeric_types
+        cls.value = lue_test.value_by_type
+
+        cls.array_shape = (60, 40)
+        cls.partition_shape = (10, 10)
+
+        cls.array = {
+            type_: lfr.create_array(
+                cls.array_shape,
+                type_,
+                fill_value=value,
+                partition_shape=cls.partition_shape,
+            )
+            for type_, value in cls.value.items()
+        }
+
+        # cls.scalar = {type_: lfr.maximum(array) for type_, array in cls.array.items()}
+
+        cls.dtype_by_type = lue_test.dtype_by_type
+
+        cls.scalar = {
+            type_: lfr.create_scalar(cls.dtype_by_type[type_], cls.value[type_])
+            for type_ in cls.numeric_types
+        }
diff --git a/source/framework/python/test/lue_test/type.py b/source/framework/python/test/lue_test/type.py
new file mode 100644
index 000000000..298f52be1
--- /dev/null
+++ b/source/framework/python/test/lue_test/type.py
@@ -0,0 +1,44 @@
+import numpy as np
+
+
+boolean_types = [
+    np.uint8,
+]
+
+signed_integral_types = [
+    # np.int8,
+    np.int32,
+    np.int64,
+]
+
+unsigned_integral_types = [
+    np.uint8,
+    np.uint32,
+    np.uint64,
+]
+
+integral_types = signed_integral_types + unsigned_integral_types
+
+floating_point_types = [
+    np.float32,
+    np.float64,
+]
+
+numeric_types = integral_types + floating_point_types
+
+value_by_type = {
+    np.uint8: np.uint8(8),
+    # np.int8: np.int8(-8),
+    np.uint32: np.uint32(32),
+    np.uint64: np.uint64(64),
+    np.int32: np.int32(-32),
+    np.int64: np.int64(-64),
+    np.float32: np.float32(3.2),
+    np.float64: np.float64(6.4),
+}
+
+dtype_by_floating_point_type = {
+    type_: np.dtype(type_) for type_ in floating_point_types
+}
+
+dtype_by_type = {type_: np.dtype(type_) for type_ in numeric_types}