diff --git a/include/fmpi_reduce.h b/include/fmpi_reduce.h
index 353f33836bd6c1cd4b04dca525aa54fe551f7daf..3c034bb655c1570e4e6a4698f87eddd38ca98942 100644
--- a/include/fmpi_reduce.h
+++ b/include/fmpi_reduce.h
@@ -4,6 +4,8 @@
  * @license{
  * BSD Zero Clause License
  *
+ * Copyright (c) 2022 by Raphael Bach
+ *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted.
  *
@@ -24,11 +26,8 @@
 /*==============================================================================
     INCLUDE
 ==============================================================================*/
-// C Standard Library
-// External
 // Internal
-#include "fmpi_ctx.h"
-#include "internal/fmpi_reduce_internal.h"
+#include "internal/generic/fmpi_reduce_generic.h"
 /*==============================================================================
     PUBLIC FUNCTION
 ==============================================================================*/
@@ -48,10 +47,22 @@
  * - \p{ctx} must be a valid pointer allocated with fmpi_init().
  * - \p{array} must not be `NULL`.
  */
-#define fmpi_local_reduce_prod(ctx, array, length)                       \
+#define fmpi_local_reduce_prod(ctx, array, length) \
     FMPI_GENERIC_FUNC(array, local_reduce_prod, FMPI_REDUCE_PROD_TYPES)(ctx, array, length)
-
-#define fmpi_reduce_prod(ctx, array)                                     \
+/*------------------------------------------------------------------------------
+    fmpi_reduce_prod()
+------------------------------------------------------------------------------*/
+/**
+ * TODO
+ *
+ * @param ctx : TODO
+ * @param array : TODO
+ *
+ * @example{
+ *  TODO
+ * }
+ */
+#define fmpi_reduce_prod(ctx, array) \
     FMPI_GENERIC_FUNC(array, reduce_prod, FMPI_REDUCE_PROD_TYPES)(ctx, array)
 /*==============================================================================
     GUARD
diff --git a/include/internal/fmpi_reduce_internal.h b/include/internal/generic/fmpi_reduce_generic.h
similarity index 74%
rename from include/internal/fmpi_reduce_internal.h
rename to include/internal/generic/fmpi_reduce_generic.h
index 968c10694fcda7a06035b1c2864a5c5545f41212..4372a1d69acbdeeb485d3abf8d662f633471ddd3 100644
--- a/include/internal/fmpi_reduce_internal.h
+++ b/include/internal/generic/fmpi_reduce_generic.h
@@ -4,6 +4,8 @@
  * @license{
  * BSD Zero Clause License
  *
+ * Copyright (c) 2022 by Raphael Bach
+ *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted.
  *
@@ -24,27 +26,25 @@
 /*==============================================================================
     INCLUDE
 ==============================================================================*/
+// C Standard Library
+#include <stddef.h> // size_t
 // Internal
-#include "fmpi_ctx.h"
 #include "fmpi_generic.h"
 /*==============================================================================
     MACRO
 ==============================================================================*/
-#define FMPI_REDUCE_PROD_TYPES                                           \
-    FMPI_TYPE_REAL
+struct fmpi_ctx;
 
-#define FMPI_PROTO_LOCAL_REDUCE_PROD(T)                                  \
-    T fmpi_local_reduce_prod_##T(struct fmpi_ctx * const ctx, T * const array, int length)
+#define FMPI_REDUCE_PROD_TYPES \
+    FMPI_TYPE_REAL
 
-#define FMPI_PROTO_REDUCE_PROD(T)                                        \
-    T fmpi_reduce_prod_##T(struct fmpi_ctx * const ctx, T * const array)
+#define FMPI_REDUCE_DECLARATION(T) \
+T fmpi_local_reduce_prod_##T( \
+    const struct fmpi_ctx * ctx, const T * array, size_t length \
+); \
+T fmpi_reduce_prod_##T(const struct fmpi_ctx * ctx, const T * array)
 
-FMPI_DECLARE_FUNC(
-    FMPI_PROTO_LOCAL_REDUCE_PROD, FMPI_REDUCE_PROD_TYPES
-);
-FMPI_DECLARE_FUNC(
-    FMPI_PROTO_REDUCE_PROD, FMPI_REDUCE_PROD_TYPES
-);
+FMPI_DECLARE_FUNCS(FMPI_REDUCE_DECLARATION, FMPI_REDUCE_PROD_TYPES);
 /*==============================================================================
     GUARD
 ==============================================================================*/
diff --git a/src/fmpi_reduce.c b/src/fmpi_reduce.c
index 2eca439ea6f894d900430c677b544cbfd3e62582..8df16a460de154a41887e083f49949fbe51ffb44 100644
--- a/src/fmpi_reduce.c
+++ b/src/fmpi_reduce.c
@@ -4,6 +4,8 @@
  * @license{
  * BSD Zero Clause License
  *
+ * Copyright (c) 2022 by Raphael Bach
+ *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted.
  *
@@ -26,40 +28,39 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 // Internal
-#include "fmpi_futhark.h"
-#include "fmpi_mpi.h"
-#include "internal/fmpi_fut.h"
-#include "internal/fmpi_generic.h"
+#include "internal/fmpi_ctx.h"
+#include "internal/fmpi_futhark.h"
+#include "internal/fmpi_futhark_entry.h"
+#include "internal/fmpi_mpi.h"
+#include "internal/generic/fmpi_generic.h"
 /*==============================================================================
     STRUCT
 ==============================================================================*/
 /*==============================================================================
     PUBLIC FUNCTION
 ==============================================================================*/
-#define FMPI_DEFINE_LOCAL_REDUCE_PROD(T)                                 \
-FMPI_PROTO_LOCAL_REDUCE_PROD(T)                                          \
-{                                                                              \
-    assert(ctx != NULL);                                                       \
-    assert(array != NULL);                                                     \
-                                                                               \
-    struct futhark_##T##_1d * xs = fmpi_new_##T##_1d(ctx, array, length);\
-    T result = FMPI_DEFAULT_VALUE_##T;                                   \
-    futhark_entry_reduce_prod_##T(ctx->futhark, &result, xs);        \
-    fmpi_futhark_abort_on_error(ctx, CPL_STRINGIFY(futhark_entry_reduce_prod_##T())); \
-    fmpi_futhark_sync(ctx);                                     \
-    fmpi_free_##T##_1d(ctx, xs);                                   \
+#define FMPI_REDUCE_DEFINITION(T) \
+T fmpi_local_reduce_prod_##T( \
+    const struct fmpi_ctx * const ctx, const T * const array, const size_t length \
+){ \
+    assert(ctx != NULL); \
+    assert(array != NULL); \
+    struct futhark_##T##_1d * data = fmpi_futhark_new_1d_##T(ctx, array, length);\
+    T result = FMPI_TYPE_DEFAULT_##T; \
+    const int err = futhark_entry_reduce_prod_##T(ctx->fut->ctx, &result, data); \
+    if(err != 0) { \
+        fmpi_futhark_check_error(ctx->fut, CPL_STRINGIFY(futhark_entry_reduce_prod_##T)); \
+    } \
+    fmpi_futhark_sync(ctx->fut); \
+    fmpi_futhark_free_1d_##T(ctx, data); \
     return result; \
-}
-
-#define FMPI_DEFINE_REDUCE_PROD(T)                                       \
-FMPI_PROTO_REDUCE_PROD(T) \
+}\
+T fmpi_reduce_prod_##T(const struct fmpi_ctx * const ctx, const T * const array) \
 { \
     assert(ctx != NULL); \
     assert(array != NULL); \
- \
-    T result = FMPI_DEFAULT_VALUE_##T; \
+    T result = FMPI_TYPE_DEFAULT_##T; \
     /*! @cast MPI uses `int` for `size`. */ \
     /* Casting `int` to `size_t` should be safe if the value isn't negative. */ \
     /* This is asserted in`fmpi_init()`.*/ \
@@ -67,17 +68,15 @@ FMPI_PROTO_REDUCE_PROD(T) \
     if(fact_global == NULL) { \
         fprintf(stderr, "malloc(fact_global) failed!\n"); \
     } \
-    int err_id = MPI_Gather(array, 1, FMPI_MPI_DATATYPE_##T, fact_global, 1, FMPI_MPI_DATATYPE_##T, ctx->mpi->root, MPI_COMM_WORLD); \
-    if(fmpi_mpi_has_error(ctx->mpi, err_id, "MPI_Gather()")) { \
+    int err_id = MPI_Gather(array, 1, FMPI_TYPE_MPI_##T, fact_global, 1, FMPI_TYPE_MPI_##T, ctx->mpi->root, MPI_COMM_WORLD); \
+    if(fmpi_mpi_check_error(ctx->mpi, err_id, "MPI_Gather()") == true) { \
         free(fact_global); \
-        fmpi_abort(ctx); \
     } \
     if(fmpi_mpi_is_root(ctx->mpi)) { \
-        result = fmpi_local_reduce_prod_##T(ctx, fact_global, ctx->mpi->size); \
+        result = fmpi_local_reduce_prod_##T(ctx, fact_global, (size_t)ctx->mpi->size); \
     } \
     free(fact_global); \
     return result; \
 }
 
-FMPI_DEFINE_FUNC(FMPI_DEFINE_LOCAL_REDUCE_PROD, FMPI_REDUCE_PROD_TYPES)
-FMPI_DEFINE_FUNC(FMPI_DEFINE_REDUCE_PROD, FMPI_REDUCE_PROD_TYPES)
+FMPI_DEFINE_FUNCS(FMPI_REDUCE_DEFINITION, FMPI_REDUCE_PROD_TYPES)