Audit finding
- ID:
AUD-023
- Status: Verified defect cluster
- Severity: Medium
- Confidence: High
- Audited revision:
2f479320d805a1f9f35ebe4afaaeeded48913a94
Problem
Three public constructors accept values that immediately become divisors:
RecursiveLeastSquares(forgettingFactor=0) produces NaN covariance after one update.
GoertzelAlgorithm(blockLength=0) performs four divisions by zero and reports ready before any sample.
AlphaBetaFilter(..., Ts=0) stores an infinite velocity gain.
Sources:
|
RecursiveLeastSquares<T, Features>::RecursiveLeastSquares(T forgettingFactor) |
|
: covariance(DesignMatrix::Identity()) |
|
, lambda(forgettingFactor) |
|
, lambdaInverse(T(1) / lambda) |
|
{ |
|
} |
|
|
|
template<typename T, std::size_t Features> |
|
RecursiveLeastSquares<T, Features>::RecursiveLeastSquares(T initialCovariance, T forgettingFactor) |
|
: covariance(DesignMatrix::Identity() * initialCovariance) |
|
, lambda(forgettingFactor) |
|
, lambdaInverse(T(1) / lambda) |
|
{ |
|
} |
|
|
|
template<typename T, std::size_t Features> |
|
|
|
template<typename T> |
|
GoertzelAlgorithm<T>::GoertzelAlgorithm(std::size_t k, std::size_t blockLength) |
|
: coeff{ T{ 2 } * math::Cos(T{ 2 } * std::numbers::pi_v<T> * static_cast<T>(k) / static_cast<T>(blockLength)) } |
|
, cosine{ math::Cos(T{ 2 } * std::numbers::pi_v<T> * static_cast<T>(k) / static_cast<T>(blockLength)) } |
|
, sine{ math::Sin(T{ 2 } * std::numbers::pi_v<T> * static_cast<T>(k) / static_cast<T>(blockLength)) } |
|
, blockSize{ blockLength } |
|
{} |
|
|
|
template<typename T> |
|
GoertzelAlgorithm<T>::GoertzelAlgorithm(T targetHz, T sampleHz, std::size_t blockLength) |
|
: GoertzelAlgorithm( |
|
static_cast<std::size_t>(targetHz / sampleHz * static_cast<T>(blockLength) + T{ 0.5 }), |
|
blockLength) |
|
AlphaBetaFilter<T, Order>::AlphaBetaFilter(T alpha, T beta, T Ts) |
|
requires(Order == 2) |
|
: samplePeriod{ Ts } |
|
, gainAlpha{ alpha } |
|
, gainBeta{ beta } |
|
, betaOverTs{ beta / Ts } |
|
{} |
|
|
|
template<typename T, std::size_t Order> |
|
AlphaBetaFilter<T, Order>::AlphaBetaFilter(T alpha, T beta, T gamma, T Ts) |
|
requires(Order == 3) |
|
: samplePeriod{ Ts } |
|
, gainAlpha{ alpha } |
|
, gainBeta{ beta } |
|
, gainGamma{ gamma } |
|
, betaOverTs{ beta / Ts } |
|
, twoGammaOverTs2{ T{ 2 } * gamma / (Ts * Ts) } |
|
{} |
|
|
|
template<typename T, std::size_t Order> |
Acceptance criteria
Audit finding
AUD-0232f479320d805a1f9f35ebe4afaaeeded48913a94Problem
Three public constructors accept values that immediately become divisors:
RecursiveLeastSquares(forgettingFactor=0)produces NaN covariance after one update.GoertzelAlgorithm(blockLength=0)performs four divisions by zero and reports ready before any sample.AlphaBetaFilter(..., Ts=0)stores an infinite velocity gain.Sources:
numerical-toolbox-cpp/numerical/estimators/online/RecursiveLeastSquares.hpp
Lines 52 to 67 in 2f47932
numerical-toolbox-cpp/numerical/analysis/GoertzelAlgorithm.hpp
Lines 42 to 55 in 2f47932
numerical-toolbox-cpp/numerical/filters/active/AlphaBetaFilter.hpp
Lines 56 to 75 in 2f47932
Acceptance criteria
TEST_Ffailure case per constructor.