Files
ResInsight/ApplicationLibCode/UnitTests/RigStatisticsTools-Test.cpp
T
Magne Sjaastad b02d95bf95 #14698 Add regression tests for NaN/Inf/overflow guard in parameter correlations
Add RimSummaryEnsemble-Test.cpp with tests verifying that:
- a realization whose calculated summary vector value is NaN or Inf
  at the selected timestep is excluded from the Pearson correlation
  result instead of corrupting it
- extremely large but finite parameter/result magnitudes, which
  overflow the sum-of-squares in RigStatisticsTools::pearsonCorrelation()
  and RigEnsembleParameter::stdDeviation(), do not surface a NaN/Inf
  correlation value and are not silently dropped from the result

Add RigStatisticsTools.OverflowProducesNan reproducing the pearsonCorrelation()
overflow directly.

Verified each new test fails without its corresponding production fix
and passes with it.
2026-09-09 10:47:54 +02:00

132 lines
4.5 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "gtest/gtest.h"
#include "RigStatisticsTools.h"
#include <QDebug>
#include <cmath>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RigStatisticsTools, NoCorrelation )
{
const int N = 1000;
std::vector<double> a, b;
a.reserve( N );
b.reserve( N );
for ( int i = 0; i < N; ++i )
{
a.push_back( (double)i );
}
for ( int i = 0; i < N; ++i )
{
b.push_back( (double)std::rand() );
}
double correlation = RigStatisticsTools::pearsonCorrelation( a, b );
EXPECT_LE( correlation, 0.25 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RigStatisticsTools, FullCorrelation )
{
const int N = 1000;
std::vector<double> a, b;
a.reserve( N );
b.reserve( N );
for ( int i = 0; i < N; ++i )
{
a.push_back( (double)i );
}
for ( int i = 0; i < N; ++i )
{
b.push_back( i * 2.0 + 1.0 );
}
double correlation = RigStatisticsTools::pearsonCorrelation( a, b );
EXPECT_NEAR( correlation, 1.0, 1.0e-2 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RigStatisticsTools, NegativeCorrelation )
{
const int N = 1000;
std::vector<double> a, b;
a.reserve( N );
b.reserve( N );
for ( int i = 0; i < N; ++i )
{
a.push_back( (double)i );
}
for ( int i = 0; i < N; ++i )
{
b.push_back( i * -2.0 + 1.0 );
}
double correlation = RigStatisticsTools::pearsonCorrelation( a, b );
EXPECT_NEAR( correlation, -1.0, 1.0e-2 );
}
//--------------------------------------------------------------------------------------------------
/// Extremely large but finite magnitudes can overflow the sum-of-squares to +Inf, and the final
/// Inf/Inf division then yields NaN even though every individual input value is finite. Callers of
/// pearsonCorrelation() (e.g. RimSummaryEnsemble::parameterCorrelations()) must guard against this.
//--------------------------------------------------------------------------------------------------
TEST( RigStatisticsTools, OverflowProducesNan )
{
std::vector<double> a = { 1.0e200, 2.0e200, 3.0e200 };
std::vector<double> b = { 1.0e200, 2.0e200, 3.0e200 };
double correlation = RigStatisticsTools::pearsonCorrelation( a, b );
EXPECT_TRUE( std::isnan( correlation ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RigStatisticsTools, MinValue )
{
const int N = 1000;
std::vector<double> a;
for ( int i = 10; i < N; ++i )
{
a.push_back( static_cast<double>( i ) );
}
double minValue = RigStatisticsTools::minimumValue( a );
EXPECT_EQ( minValue, 10.0 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RigStatisticsTools, MaxValue )
{
const int N = 1000;
std::vector<double> a;
for ( int i = 10; i < N; ++i )
{
a.push_back( static_cast<double>( i ) );
}
double maxValue = RigStatisticsTools::maximumValue( a );
EXPECT_EQ( maxValue, 999.0 );
}