Examples
Practical examples demonstrating accumux capabilities.
Example 1: Complete Statistics Program
#include "accumux/accumulators/kbn_sum.hpp"
#include "accumux/accumulators/welford.hpp"
#include "accumux/accumulators/minmax.hpp"
#include "accumux/core/composition.hpp"
#include <iostream>
#include <vector>
using namespace accumux;
int main() {
// Create comprehensive statistics accumulator
auto stats = kbn_sum<double>() +
welford_accumulator<double>() +
minmax_accumulator<double>();
// Sample data
std::vector<double> data = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};
// Single-pass processing
for (double x : data) {
stats += x;
}
// Extract results
auto sum = stats.get_first().eval();
auto welford = stats.get_second();
auto minmax = welford.get_second();
std::cout << "=== Statistics ===" << std::endl;
std::cout << "Sum: " << sum << std::endl;
std::cout << "Mean: " << welford.mean() << std::endl;
std::cout << "Variance: " << welford.sample_variance() << std::endl;
std::cout << "Std Dev: " << welford.sample_std_dev() << std::endl;
std::cout << "Min: " << minmax.min() << std::endl;
std::cout << "Max: " << minmax.max() << std::endl;
std::cout << "Count: " << welford.count() << std::endl;
return 0;
}
Output:
=== Statistics ===
Sum: 55
Mean: 5.5
Variance: 9.16667
Std Dev: 3.02765
Min: 1
Max: 10
Count: 10
Example 2: Financial Analysis
Track multiple metrics for financial data streams.
#include "accumux/accumulators/kbn_sum.hpp"
#include "accumux/accumulators/welford.hpp"
#include "accumux/accumulators/minmax.hpp"
#include "accumux/core/composition.hpp"
#include <iostream>
#include <vector>
using namespace accumux;
int main() {
auto financial_stats = kbn_sum<double>() +
welford_accumulator<double>() +
minmax_accumulator<double>();
// Daily returns (as percentages)
std::vector<double> returns = {0.05, -0.02, 0.03, 0.01, -0.01, 0.04,
-0.03, 0.02, 0.01, -0.02};
for (double ret : returns) {
financial_stats += ret;
}
// Extract metrics
auto total_return = financial_stats.get_first().eval();
auto welford = financial_stats.get_second();
auto minmax = welford.get_second();
std::cout << "=== Portfolio Analysis ===" << std::endl;
std::cout << "Total Return: " << (total_return * 100) << "%" << std::endl;
std::cout << "Mean Return: " << (welford.mean() * 100) << "%" << std::endl;
std::cout << "Volatility: " << (welford.sample_std_dev() * 100) << "%" << std::endl;
std::cout << "Worst Day: " << (minmax.min() * 100) << "%" << std::endl;
std::cout << "Best Day: " << (minmax.max() * 100) << "%" << std::endl;
std::cout << "Trading Days: " << welford.count() << std::endl;
// Sharpe-like ratio (simplified)
double risk_free_rate = 0.001; // 0.1% per day
double sharpe = (welford.mean() - risk_free_rate) / welford.sample_std_dev();
std::cout << "Sharpe Ratio: " << sharpe << std::endl;
return 0;
}
Example 3: Numerical Stability Comparison
Demonstrate the importance of stable summation.
#include "accumux/accumulators/kbn_sum.hpp"
#include <iostream>
#include <cmath>
using namespace accumux;
int main() {
const size_t N = 1000000;
// Create data that exposes numerical instability
// Sum of 1/n for n = 1 to N
double naive_sum = 0.0;
kbn_sum<double> stable_sum;
for (size_t i = 1; i <= N; ++i) {
double value = 1.0 / static_cast<double>(i);
naive_sum += value;
stable_sum += value;
}
// Reference value (computed with higher precision)
// Euler-Mascheroni constant approximation
double reference = std::log(N) + 0.5772156649;
std::cout << "Harmonic sum (n=1 to " << N << "):" << std::endl;
std::cout << "Naive sum: " << naive_sum << std::endl;
std::cout << "KBN sum: " << stable_sum.eval() << std::endl;
std::cout << "Reference: " << reference << std::endl;
std::cout << std::endl;
std::cout << "Naive error: " << std::abs(naive_sum - reference) << std::endl;
std::cout << "KBN error: " << std::abs(stable_sum.eval() - reference) << std::endl;
return 0;
}
Example 4: Parallel Processing
Process data in parallel and combine results.
#include "accumux/accumulators/kbn_sum.hpp"
#include "accumux/accumulators/welford.hpp"
#include "accumux/core/composition.hpp"
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
using namespace accumux;
int main() {
// Generate large dataset
const size_t N = 1000000;
std::vector<double> data(N);
for (size_t i = 0; i < N; ++i) {
data[i] = static_cast<double>(i + 1);
}
// Process in 4 chunks
const size_t num_threads = 4;
const size_t chunk_size = N / num_threads;
using StatsType = decltype(kbn_sum<double>() + welford_accumulator<double>());
std::vector<StatsType> thread_stats(num_threads);
std::vector<std::thread> threads;
for (size_t t = 0; t < num_threads; ++t) {
threads.emplace_back([&, t]() {
size_t start = t * chunk_size;
size_t end = (t == num_threads - 1) ? N : (t + 1) * chunk_size;
thread_stats[t] = kbn_sum<double>() + welford_accumulator<double>();
for (size_t i = start; i < end; ++i) {
thread_stats[t] += data[i];
}
});
}
for (auto& t : threads) {
t.join();
}
// Combine all thread results
auto combined = thread_stats[0];
for (size_t t = 1; t < num_threads; ++t) {
combined += thread_stats[t];
}
std::cout << "Parallel processing of " << N << " elements:" << std::endl;
std::cout << "Sum: " << combined.get_first().eval() << std::endl;
std::cout << "Mean: " << combined.get_second().mean() << std::endl;
// Verify: sum of 1 to N = N*(N+1)/2
double expected_sum = N * (N + 1.0) / 2.0;
std::cout << "Expected sum: " << expected_sum << std::endl;
return 0;
}
Example 5: Scientific Data Analysis
Analyze sensor data with real-time anomaly detection.
#include "accumux/accumulators/welford.hpp"
#include "accumux/accumulators/minmax.hpp"
#include "accumux/core/composition.hpp"
#include <iostream>
#include <vector>
#include <random>
using namespace accumux;
int main() {
// Simulate sensor readings with occasional anomalies
std::mt19937 gen(42);
std::normal_distribution<> normal(100.0, 5.0); // Normal readings
std::uniform_real_distribution<> uniform(0.0, 1.0);
auto sensor_stats = welford_accumulator<double>() + minmax_accumulator<double>();
std::cout << "=== Real-Time Sensor Analysis ===" << std::endl;
for (int i = 0; i < 100; ++i) {
double reading;
if (uniform(gen) < 0.05) {
// 5% chance of anomaly
reading = normal(gen) + (uniform(gen) > 0.5 ? 50.0 : -50.0);
} else {
reading = normal(gen);
}
sensor_stats += reading;
// Check for anomalies after warm-up period
auto stats = sensor_stats.get_first();
if (stats.count() > 10) {
double z_score = std::abs(reading - stats.mean()) / stats.sample_std_dev();
if (z_score > 3.0) {
std::cout << "ANOMALY at reading " << i
<< ": value=" << reading
<< ", z-score=" << z_score << std::endl;
}
}
}
auto final_stats = sensor_stats.get_first();
auto minmax = sensor_stats.get_second();
std::cout << std::endl << "=== Final Statistics ===" << std::endl;
std::cout << "Readings: " << final_stats.count() << std::endl;
std::cout << "Mean: " << final_stats.mean() << std::endl;
std::cout << "Std Dev: " << final_stats.sample_std_dev() << std::endl;
std::cout << "Range: [" << minmax.min() << ", " << minmax.max() << "]" << std::endl;
return 0;
}
Example 6: Custom Accumulator
Create a custom accumulator that satisfies the Accumulator concept.
#include "accumux/core/concept.hpp"
#include "accumux/core/composition.hpp"
#include <iostream>
using namespace accumux;
// Custom accumulator for computing sum of squares
template<typename T>
class sum_of_squares {
public:
using value_type = T;
sum_of_squares() : sum_sq_(0) {}
sum_of_squares& operator+=(T value) {
sum_sq_ += value * value;
return *this;
}
sum_of_squares& operator+=(const sum_of_squares& other) {
sum_sq_ += other.sum_sq_;
return *this;
}
T eval() const { return sum_sq_; }
private:
T sum_sq_;
};
// Verify it satisfies the Accumulator concept
static_assert(Accumulator<sum_of_squares<double>>,
"sum_of_squares must satisfy Accumulator concept");
int main() {
// Use custom accumulator in composition
auto stats = kbn_sum<double>() + sum_of_squares<double>();
std::vector<double> data = {1.0, 2.0, 3.0, 4.0, 5.0};
for (double x : data) {
stats += x;
}
double sum = stats.get_first().eval();
double sum_sq = stats.get_second().eval();
std::cout << "Sum: " << sum << std::endl; // 15
std::cout << "Sum of squares: " << sum_sq << std::endl; // 55
// Compute variance using sum and sum of squares
double n = 5.0;
double mean = sum / n;
double variance = (sum_sq / n) - (mean * mean);
std::cout << "Variance (from sums): " << variance << std::endl;
return 0;
}
More Examples
For additional examples including:
- Benchmark comparisons
- Integration with other libraries
- Complex multi-stage pipelines
See the examples directory on GitHub.