Reduce

The Fossil Algorithm Reduce module provides a deterministic, extensible reduction engine for aggregating arrays of typed data. It supports common operations such as sum, minimum, maximum, and count, as well as fully custom reducers supplied by the caller. The C API is string-driven and type-aware, enabling late-bound reductions across heterogeneous data while maintaining predictable memory usage and execution order. The C++ wrapper offers a thin, zero-overhead façade that preserves the flexibility of the C interface while integrating naturally with modern C++ codebases.

HEADER REFERENCE #

#ifndef FOSSIL_ALGORITHM_REDUCE_H
#define FOSSIL_ALGORITHM_REDUCE_H

#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

// ======================================================
// Fossil Algorithm Reduce — Reducer Signature
// ======================================================

/**
 * @brief Reducer function for custom reductions.
 *
 * @param accum   Pointer to accumulator (mutable)
 * @param element Pointer to input element
 * @param user    Optional user context
 */
typedef void (*fossil_algorithm_reduce_fn)(
    void *accum,
    const void *element,
    void *user
);

// ======================================================
// Fossil Algorithm Reduce — Exec Interface
// ======================================================

/**
 * @brief Executes a reduction over an array.
 *
 * Performs aggregation such as sum, min, max, count, or
 * user-defined reductions with deterministic execution.
 *
 * Example:
 * @code
 * int32_t values[] = {1,2,3,4};
 * int32_t result;
 * fossil_algorithm_reduce_exec(
 *     values, 4,
 *     "i32",
 *     "sum",
 *     "auto",
 *     0,
 *     &result,
 *     NULL,
 *     NULL
 * );
 * @endcode
 *
 * @param base        Pointer to input array
 * @param count       Number of elements
 * @param type_id     Data type identifier ("i32", "f64", etc.)
 * @param op_id       Reduction operation ("sum", "min", "max", "count", "custom")
 * @param lanes       Number of virtual lanes (0 = auto)
 * @param out_result  Pointer to output accumulator
 * @param reduce_fn   Custom reducer (required if op_id == "custom")
 * @param user        Optional user context
 *
 * @return int status:
 *   0  success
 *  -1  invalid input
 *  -2  unknown type
 *  -3  unknown operation
 */
int fossil_algorithm_reduce_exec(
    const void *base,
    size_t count,
    const char *type_id,
    const char *op_id,
    size_t lanes,
    void *out_result,
    fossil_algorithm_reduce_fn reduce_fn,
    void *user
);

// ======================================================
// Utilities
// ======================================================

/**
 * @brief Returns the byte size of a type based on its string identifier.
 */
size_t fossil_algorithm_reduce_type_sizeof(const char *type_id);

/**
 * @brief Checks whether the given type identifier is supported.
 */
bool fossil_algorithm_reduce_type_supported(const char *type_id);

#ifdef __cplusplus
}
#endif

// ======================================================
// C++ RAII Wrapper
// ======================================================

#ifdef __cplusplus
#include <string>

namespace fossil {

namespace algorithm {

class Reduce
{
public:
    static int exec(
        const void *base,
        size_t count,
        const std::string &type_id,
        void *out_result,
        const std::string &op_id = "auto",
        size_t lanes = 0,
        fossil_algorithm_reduce_fn fn = nullptr,
        void *user = nullptr
    ) {
        return fossil_algorithm_reduce_exec(
            base,
            count,
            type_id.c_str(),
            op_id.c_str(),
            lanes,
            out_result,
            fn,
            user
        );
    }

    static size_t type_sizeof(const std::string &type_id) {
        return fossil_algorithm_reduce_type_sizeof(type_id.c_str());
    }

    static bool type_supported(const std::string &type_id) {
        return fossil_algorithm_reduce_type_supported(type_id.c_str());
    }
};

} // namespace algorithm

} // namespace fossil
#endif

#endif /* FOSSIL_ALGORITHM_REDUCE_H */

SAMPLE CODE C #

#include "fossil/algorithm/reduce.h"
#include <stdio.h>

/* Custom reducer: sum only even integers */
void sum_even_i32(void *accum, const void *elem, void *user) {
    (void)user;
    int32_t *out = (int32_t *)accum;
    int32_t v = *(const int32_t *)elem;
    if ((v & 1) == 0)
        *out += v;
}

int main(void) {
    int32_t values[] = {1, 2, 3, 4, 5, 6};
    int32_t result = 0;

    /* Built-in sum */
    if (fossil_algorithm_reduce_exec(
            values,
            6,
            "i32",
            "sum",
            0,
            &result,
            NULL,
            NULL
        ) == 0) {
        printf("Sum: %d\n", result);
    }

    /* Custom reduction */
    result = 0;
    if (fossil_algorithm_reduce_exec(
            values,
            6,
            "i32",
            "custom",
            0,
            &result,
            sum_even_i32,
            NULL
        ) == 0) {
        printf("Sum of even values: %d\n", result);
    }

    return 0;
}

SAMPLE CODE C++ #

#include "fossil/algorithm/reduce.h"
#include <iostream>

using fossil::algorithm::Reduce;

void product_i64(void *accum, const void *elem, void *) {
    int64_t *out = static_cast<int64_t *>(accum);
    int64_t v = *static_cast<const int64_t *>(elem);
    *out *= v;
}

int main() {
    int64_t values[] = {1, 2, 3, 4};
    int64_t result = 0;

    /* Built-in max */
    Reduce::exec(
        values,
        4,
        "i64",
        &result,
        "max"
    );

    std::cout << "Max: " << result << "\n";

    /* Custom product */
    result = 1;
    Reduce::exec(
        values,
        4,
        "i64",
        &result,
        "custom",
        0,
        product_i64,
        nullptr
    );

    std::cout << "Product: " << result << "\n";

    return 0;
}

What are your feelings

Updated on February 7, 2026