Cover remaining HHT field policy boundary oracles

This commit is contained in:
KOKO\Mimi
2026-10-19 02:24:40 +09:00
parent ad06d7ad6c
commit 0e392a7364
@@ -228,5 +228,98 @@ TEST(HhtFieldConvergence, RemainingThresholdsHaveAdjacentRepresentableBoundaries
EXPECT_EQ(r.field_pass,x<=2);
}
}
TEST(HhtFieldConvergence, CurrentIncludedEligibilityBoundaryPreservesPendingNonzeroHistory) {
Histories h{}; h[0]={199999,1,199999,1};
// 199999+1 rounds exactly to 200000; current-included mean is 100000.
// Its epsilon threshold is exactly 1, while the old-base threshold is 1.99999.
for (double b:{std::nextafter(1.,0.),1.,std::nextafter(1.,INFINITY)}) {
auto f=Normal(); f[0].flux={{b,0}};
const auto r=Evaluate(f,h,1,2); ASSERT_TRUE(r.status.IsOk());
EXPECT_EQ(*r.fields[0].spatial_flux,b);
EXPECT_EQ(*r.fields[0].time_average_flux,b>1?100000:199999);
EXPECT_EQ(r.pending[0].nonzero_sum,b>1?200000:199999);
EXPECT_EQ(r.pending[0].nonzero_count,b>1?2U:1U);
EXPECT_EQ(h[0].nonzero_sum,199999);
EXPECT_EQ(h[0].nonzero_count,1U);
}
auto f=Normal(); f[0].flux={{1.5,0}};
const auto r=Evaluate(f,h,1,2); ASSERT_TRUE(r.status.IsOk());
EXPECT_EQ(*r.fields[0].time_average_flux,100000.25);
EXPECT_EQ(r.pending[0].nonzero_sum,200000.5);
EXPECT_EQ(r.pending[0].nonzero_count,2U);
}
TEST(HhtFieldConvergence, ConversionSpatialPrerequisiteHasAdjacentBoundaries) {
Histories h{}; h[0]={1023,1023,1023,1023}; h[1]={4,1,4,1};
// Adding any adjacent-to-one b to 1023 rounds to 1024: raw force stays 1.
// Peer raw moment stays 4 and L=1 makes the candidate force scale exactly 4.
for (double b:{std::nextafter(1.,0.),1.,std::nextafter(1.,INFINITY)}) {
auto f=Normal(); f[0].flux={{b,0}}; f[1]=f[0]; f[1].flux={{4,0}};
const auto r=Evaluate(f,h,1,1); ASSERT_TRUE(r.status.IsOk());
EXPECT_EQ(*r.fields[0].spatial_flux,b);
EXPECT_EQ(*r.fields[0].time_average_flux,1);
EXPECT_EQ(*r.fields[1].time_average_flux,4);
EXPECT_EQ(*r.fields[0].residual_scale,b<=1?4:1);
EXPECT_EQ(r.pending[0].nonzero_sum,1024);
EXPECT_EQ(r.pending[0].nonzero_count,1024U);
EXPECT_EQ(r.pending[1].nonzero_sum,8);
EXPECT_EQ(r.pending[1].nonzero_count,2U);
EXPECT_EQ(h[0].nonzero_sum,1023);
EXPECT_EQ(h[0].nonzero_count,1023U);
EXPECT_EQ(h[1].nonzero_sum,4);
}
}
TEST(HhtFieldConvergence, ConversionRawVersusConvertedScaleHasAdjacentBoundaries) {
Histories h{}; h[0]={1,1,1,1}; h[1]=h[0];
// Zero samples preserve both raw means at 1. Only L changes convF=1/L.
for (double length:{std::nextafter(1.,0.),1.,std::nextafter(1.,INFINITY)}) {
auto f=Normal(); f[0].flux={{0,0}}; f[1]=f[0];
const auto r=Evaluate(f,h,1,length); ASSERT_TRUE(r.status.IsOk());
EXPECT_EQ(*r.fields[0].time_average_flux,1);
EXPECT_EQ(*r.fields[1].time_average_flux,1);
// Reciprocating the adjacent value below 1 rounds to the adjacent value above 1.
EXPECT_EQ(*r.fields[0].residual_scale,
length<1?std::nextafter(1.,INFINITY):1);
for (std::size_t a=0; a<2; ++a) {
EXPECT_EQ(r.pending[a].nonzero_sum,1);
EXPECT_EQ(r.pending[a].nonzero_count,1U);
EXPECT_EQ(h[a].nonzero_sum,1);
EXPECT_EQ(h[a].nonzero_count,1U);
}
}
}
TEST(HhtFieldConvergence, ZeroFluxClassificationTestsSpatialFluxBoundary) {
// A peer raw mean of 1 converts the small force field to a fixed scale of 1.
// Vary bbar, not rho, across epsilon*scale; rho=.1 prevents the linear exemption.
for (double b:{std::nextafter(1e-5,0.),1e-5,std::nextafter(1e-5,INFINITY)}) {
auto f=Normal(); f[0].flux={{b,0}}; f[0].residual=.1;
f[1]=f[0]; f[1].flux={{1,0}};
const auto r=Evaluate(f,{},1,1); ASSERT_TRUE(r.status.IsOk());
EXPECT_EQ(*r.fields[0].spatial_flux,b);
EXPECT_EQ(*r.fields[0].residual_scale,1);
EXPECT_EQ(r.fields[0].branch,b<=1e-5?Branch::kZeroFlux:Branch::kNormal);
}
}
TEST(HhtFieldConvergence, EstimatedCorrectionAdjacentBoundariesDriveNormalCorrectionPass) {
for (double estimate:{std::nextafter(.01,0.),.01,std::nextafter(.01,INFINITY)}) {
auto f=Normal(); f[0].flux={{400,0}}; f[0].residual=1;
// Prior residual minimum is 4; power-of-two scaling preserves adjacent bits.
// The actual correction exceeds .01 in all three cases, isolating the estimate.
f[0].correction=4*estimate; f[0].previous_residual=4; f[0].older_residual=8;
const auto r=Evaluate(f,{},2,2); ASSERT_TRUE(r.status.IsOk());
EXPECT_EQ(r.fields[0].branch,Branch::kNormal);
ASSERT_GT(*f[0].correction,.01);
EXPECT_EQ(*r.fields[0].estimated_correction,estimate);
EXPECT_EQ(*r.fields[0].correction_pass,estimate<=.01);
EXPECT_EQ(r.field_pass,estimate<=.01);
}
}
TEST(HhtFieldConvergence, PopulationReactivationThresholdImmediatelyAboveUsesFilteredPopulation) {
auto f=Normal(); Histories h{}; h[0]={0,0,100,1};
const double maximum=std::nextafter(10.,INFINITY);
f[0].flux={{0,0},{.001,0},{maximum,0}};
const auto r=Evaluate(f,h,1,2); ASSERT_TRUE(r.status.IsOk());
EXPECT_EQ(*r.fields[0].maximum_flux,maximum);
EXPECT_EQ(*r.fields[0].spatial_flux,(10.000000000000002+.001)/2);
}
} // namespace
} // namespace fesa::hht_field_convergence