LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
fj_char_max_blom.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_FJ_CHAR_MAX_BLOM_H
6#define LINE_API_FJ_CHAR_MAX_BLOM_H
7
8/**
9 * @file
10 * @ingroup api_fj
11 * Blom-corrected plotting position for the characteristic maximum.
12 *
13 * Templated port of matlab/src/api/fj/fj_char_max_blom.m.
14 *
15 * m_K = F^-1( (K - alpha) / (K - alpha - beta + 1) )
16 *
17 * which for alpha = beta = 0 falls back on the naive K/(K+1). The survey quotes
18 * alpha = 0.4886 and beta = 0.3140, which are the defaults. For the standard
19 * normal the position is bracketed without any inversion, for K >= 5, by
20 *
21 * sqrt(2 ln K - ln ln K - 3) < m_K < sqrt(2 ln K - ln ln K).
22 */
23
24#include <cmath>
25#include <functional>
26#include <limits>
27
29#include "line/num/number.h"
30#include "line/util/error.h"
31
32namespace line {
33namespace fj {
34
35/** [mK, lo, hi] of fj_char_max_blom; lo and hi are NaN below K = 5. */
36template <class T>
43
44/**
45 * @brief Blom-corrected plotting position for the characteristic maximum.
46 *
47 * @param Finv quantile function; an empty target selects the standard normal
48 * @param K number of i.i.d. copies, K >= 1
49 * @param alpha Blom numerator offset
50 * @param beta Blom denominator offset
51 * @return the corrected position and, for the normal, its bracket
52 */
53template <class T>
55 const std::function<T(const T&)>& Finv =
56 std::function<T(const T&)>(),
57 const T& alpha = num_traits<T>::from_double(0.4886),
58 const T& beta = num_traits<T>::from_double(0.3140)) {
59 detail::require_positive_K(K, "fj_char_max_blom");
60 const T zero = num_traits<T>::from_int(0), one = num_traits<T>::from_int(1);
61 const T Kt = num_traits<T>::from_int(static_cast<long>(K));
62 const T den = Kt - alpha - beta + one;
63 if (!(den > zero))
64 throw NumericError("fj_char_max_blom: the Blom offsets leave a non-positive denominator");
65 const T q = (Kt - alpha) / den;
66 if (!(q > zero) || !(q < one))
67 throw NumericError("fj_char_max_blom: the plotting position fell outside (0,1)");
68
70 if (Finv) {
71 out.mK = Finv(q);
72 } else {
73 // Standard normal quantile through the inverse error function
74 const double qd = num_traits<T>::to_double(q);
75 out.mK = num_traits<T>::from_double(detail::normal_quantile(qd));
76 }
77
80 out.bracket_available = false;
81 if (K >= 5) {
82 const double z = 2.0 * std::log(static_cast<double>(K)) -
83 std::log(std::log(static_cast<double>(K)));
84 if (z > 3.0) {
85 out.lo = num_traits<T>::from_double(std::sqrt(z - 3.0));
86 out.hi = num_traits<T>::from_double(std::sqrt(z));
87 out.bracket_available = true;
88 }
89 }
90 return out;
91}
92
93} // namespace fj
94} // namespace line
95
96#endif // LINE_API_FJ_CHAR_MAX_BLOM_H
NumericError(const std::string &what)
Definition error.h:45
The exception types the port throws.
Shared return types and arithmetic helpers for the templated fork-join port.
FJCharMaxBlomResult< T > fj_char_max_blom(unsigned K, const std::function< T(const T &)> &Finv=std::function< T(const T &)>(), const T &alpha=num_traits< T >::from_double(0.4886), const T &beta=num_traits< T >::from_double(0.3140))
Blom-corrected plotting position for the characteristic maximum.
Number-type abstraction for the templated API port.
[mK, lo, hi] of fj_char_max_blom; lo and hi are NaN below K = 5.