Getting started

This page walks you through the basic usage of the library.

Installation and integration into a project

The library is written in C and consists of the header include/statistics.h and the implementation in src/statistics.c. Configuration is controlled via include/statistics_config.h.

Below are the recommended installation methods, similar to the PlatformIO Installation page: https://registry.platformio.org/libraries/rici4kubicek/Statistics/installation

  • PlatformIO (recommended)

    Add the dependency to your platformio.ini:

    [env:your_env]
    platform = ...
    board = ...
    framework = ...
    lib_deps =
        rici4kubicek/Statistics@^1.0.0
    

    Note: you can pin the version as needed. The latest version is listed on the library page in the PlatformIO registry.

  • PlatformIO (install directly from the registry via CLI)

    Run in the project root:

    pio lib install "rici4kubicek/Statistics"
    
  • CMake / manual integration (without PlatformIO)

    1. Add the source files to your build system:

      • Add src/statistics.c to your compilation.

      • Make sure the include directory is on the include path.

      Example for CMake:

      add_library(Statistics STATIC
          ${CMAKE_CURRENT_LIST_DIR}/src/statistics.c)
      target_include_directories(Statistics PUBLIC
          ${CMAKE_CURRENT_LIST_DIR}/include)
      
      # optional: your targets that use the library
      target_link_libraries(my_app PRIVATE Statistics)
      
    2. Adjust the configuration in include/statistics_config.h as needed (enabled data types, window sizes, etc.).

  • As a git submodule

    git submodule add https://github.com/rici4kubicek/statistics.git external/statistics
    

    Then add the source and include paths (see the CMake example above) to your build.

Quick usage example

The following example demonstrates working with the ring buffer of samples and computing statistics for uint16_t (adjust according to the enabled types in statistics_config.h):

#include <statistics.h>
#include <stdio.h>

int main(void) {
    Statistics stat;
    Statistics_Init(&stat, sizeof(uint16_t), 8); // window of 8 samples

    uint16_t samples[] = { 10, 12, 9, 13, 11, 12, 10, 14, 15, 9 };
    for (size_t i = 0; i < sizeof(samples)/sizeof(samples[0]); ++i) {
        Statistics_AddSample(&stat, &samples[i]);
    }

    if (Statistics_HaveEnoughSamples(&stat)) {
        int64_t mean = Statistics_Mean_U16(&stat);
        uint16_t minv = Statistics_Min_U16(&stat);
        uint16_t maxv = Statistics_Max_U16(&stat);
        int64_t var = Statistics_Variance_U16(&stat);
        int64_t sd = Statistics_Stdev_U16(&stat);

        // Use llabs for fractional part to handle negative values correctly
        printf("mean=%lld.%03lld min=%u max=%u var=%lld.%03lld sd=%lld.%03lld\n",
               (long long)(mean / 1000), llabs(mean % 1000),
               minv, maxv,
               (long long)(var / 1000), llabs(var % 1000),
               (long long)(sd / 1000), llabs(sd % 1000));
    }

    Statistics_Free(&stat);
    return 0;
}

Fixed-point arithmetic for integer types

To optimize performance on embedded systems without a Floating Point Unit (FPU), such as STM32F0 or Cortex-M0 processors, the library uses integer arithmetic exclusively for integer data types (U8, I8, U16, I16, U32, I32). The mean, variance, and standard deviation functions return int64_t values scaled by 1000 instead of float.

Converting fixed-point results:

  • To get the integer part: value / 1000

  • To get the fractional part: value % 1000

  • Example: A return value of 890250 represents 890.250

Benefits:

  • Much faster on CPUs without FPU (can be 10-100x faster)

  • No floating-point library dependencies

  • Good precision with 3 decimal places

  • Proper rounding maintains accuracy

  • Numerically stable using Welford’s online algorithm for variance

  • Overflow-safe incremental computation avoids squaring large values

Error handling:

Statistics_Mean_*, Statistics_Variance_*, and Statistics_Stdev_* return -1 (or 0 for mean with no samples) to indicate an error (e.g., insufficient samples, invalid statistics object).

Float type:

For float types (Statistics_*_F), all functions return float directly for maximum precision. This maintains compatibility with existing floating-point code while still benefiting from the optimized integer implementation for integer data types.

Notes

  • The path to the Doxygen XML is configured in docs/source/conf.py via breathe_projects and points to ../build/doxygen/xml (relative to docs/source).

  • The documentation theme is sphinx_rtd_theme.

Configuring supported types

The public API generates a set of functions (Mean, Min, Max, Variance, Stdev) for selected scalar types. Which types are enabled is controlled in include/statistics_config.h via the STATISTICS_*_ENABLED macros.

Further reading

  • API reference – detailed API reference including Doxygen groups and entities

  • docs/Doxyfile – Doxygen configuration

  • docs/source/conf.py – Sphinx and Breathe configuration