LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
mtrace_var.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2026, QORE Lab, Imperial College London
3 * All rights reserved.
4 */
5#ifndef LINE_API_TRACE_MTRACE_VAR_H
6#define LINE_API_TRACE_MTRACE_VAR_H
7
8/**
9 * @file
10 * @ingroup api_trace
11 * Per-class variance of a marked trace.
12 *
13 * Port of `mtrace_var` in python/line_solver/api/trace/trace_analysis.py.
14 * PYTHON-ONLY: no MATLAB or JAR twin. The unmarked twin is `trace_var.h`.
15 *
16 * IT IS THE POPULATION VARIANCE, `E[X^2] - E[X]^2`, not the sample one: the
17 * reference divides by the class count, not by count minus one. That matters
18 * when a class is short, and the two differ by the factor n/(n-1).
19 *
20 * A CLASS WITH ONE OR NO SAMPLE GETS NaN, NOT ZERO. A single observation has no
21 * dispersion to report, and zero would be indistinguishable from a class whose
22 * samples happen to be identical -- which is a real and different finding. The
23 * reference returns NaN and so does this; a caller aggregating these must test.
24 *
25 * ARITHMETIC: field.
26 */
27
28#include <cstddef>
29#include <limits>
30#include <vector>
31
32#include "line/num/number.h"
33#include "line/util/error.h"
34
35namespace line {
36namespace trace {
37
38/**
39 * @brief Per-class variance of a marked trace.
40 *
41 * @param tv the trace values
42 * @param ntypes number of classes
43 * @param types 0-based class label of each value
44 * @return (ntypes) per-class variance, NaN where a class has under two
45 */
46template <class T>
47std::vector<T> mtrace_var(const std::vector<T>& tv, std::size_t ntypes,
48 const std::vector<int>& types) {
49 if (tv.size() != types.size())
50 throw InputError("mtrace_var: the trace and its labels must agree in length");
51 const T zero = num_traits<T>::from_int(0);
52 const T nan = num_traits<T>::from_double(std::numeric_limits<double>::quiet_NaN());
53
54 std::vector<T> out(ntypes, nan);
55 for (std::size_t c = 0; c < ntypes; ++c) {
56 std::size_t cnt = 0;
57 T s1 = zero, s2 = zero;
58 for (std::size_t i = 0; i < tv.size(); ++i) {
59 if (types[i] != static_cast<int>(c)) continue;
60 ++cnt;
61 s1 += tv[i];
62 s2 += tv[i] * tv[i];
63 }
64 if (cnt <= 1) continue; // no dispersion to report; NaN, not zero
65 const T nd = num_traits<T>::from_int(static_cast<long>(cnt));
66 const T e1 = T(s1 / nd), e2 = T(s2 / nd);
67 out[c] = T(e2 - e1 * e1);
68 }
69 return out;
70}
71
72} // namespace trace
73} // namespace line
74
75#endif // LINE_API_TRACE_MTRACE_VAR_H
InputError(const std::string &what)
Definition error.h:39
The exception types the port throws.
std::vector< T > mtrace_var(const std::vector< T > &tv, std::size_t ntypes, const std::vector< int > &types)
Per-class variance of a marked trace.
Definition mtrace_var.h:47
Number-type abstraction for the templated API port.