Fix remaining float comparison bugs in `RamSearchEngine`

This commit is contained in:
YoshiRulz 2024-05-31 13:00:21 +10:00
parent b279a6bdb0
commit 46584cee10
No known key found for this signature in database
GPG Key ID: C4DE31C245353FB7
1 changed files with 66 additions and 22 deletions

View File

@ -202,7 +202,10 @@ namespace BizHawk.Client.Common.RamSearchEngine
public ComparisonOperator Operator { get; set; } public ComparisonOperator Operator { get; set; }
// zero 07-sep-2014 - this isn't ideal. but don't bother changing it (to a long, for instance) until it can support floats. maybe store it as a double here. /// <remarks>
/// zero 07-sep-2014 - this isn't ideal. but don't bother changing it (to a long, for instance) until it can support floats. maybe store it as a double here.<br/>
/// it already supported floats by way of reinterpret-cast, it just wasn't implemented correctly on this side --yoshi
/// </remarks>
public int? DifferentBy { get; set; } public int? DifferentBy { get; set; }
public void Update() public void Update()
@ -389,19 +392,34 @@ namespace BizHawk.Client.Common.RamSearchEngine
case ComparisonOperator.Equal: case ComparisonOperator.Equal:
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)).HawkFloatEquality(ReinterpretAsF32(w.Previous))); return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)).HawkFloatEquality(ReinterpretAsF32(w.Previous)));
case ComparisonOperator.NotEqual: case ComparisonOperator.NotEqual:
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) != SignExtendAsNeeded(w.Previous)); return watchList.Where(w => !ReinterpretAsF32(GetValue(w.Address)).HawkFloatEquality(ReinterpretAsF32(w.Previous)));
case ComparisonOperator.GreaterThan: case ComparisonOperator.GreaterThan:
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) > ReinterpretAsF32(w.Previous)); return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) > ReinterpretAsF32(w.Previous));
case ComparisonOperator.GreaterThanEqual: case ComparisonOperator.GreaterThanEqual:
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) >= ReinterpretAsF32(w.Previous)); return watchList.Where(w =>
{
var val = ReinterpretAsF32(GetValue(w.Address));
var prev = ReinterpretAsF32(w.Previous);
return val > prev || val.HawkFloatEquality(prev);
});
case ComparisonOperator.LessThan: case ComparisonOperator.LessThan:
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) < ReinterpretAsF32(w.Previous)); return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) < ReinterpretAsF32(w.Previous));
case ComparisonOperator.LessThanEqual: case ComparisonOperator.LessThanEqual:
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) <= ReinterpretAsF32(w.Previous)); return watchList.Where(w =>
{
var val = ReinterpretAsF32(GetValue(w.Address));
var prev = ReinterpretAsF32(w.Previous);
return val < prev || val.HawkFloatEquality(prev);
});
case ComparisonOperator.DifferentBy: case ComparisonOperator.DifferentBy:
if (DifferentBy is not int differentBy) throw new InvalidOperationException(); if (DifferentBy is not int differentBy) throw new InvalidOperationException();
return watchList.Where(w => (ReinterpretAsF32(GetValue(w.Address)) + differentBy).HawkFloatEquality(ReinterpretAsF32(w.Previous)) var differentByF = ReinterpretAsF32(differentBy);
|| (ReinterpretAsF32(GetValue(w.Address)) - differentBy).HawkFloatEquality(ReinterpretAsF32(w.Previous))); return watchList.Where(w =>
{
var val = ReinterpretAsF32(GetValue(w.Address));
var prev = ReinterpretAsF32(w.Previous);
return (val + differentByF).HawkFloatEquality(prev) || (val - differentByF).HawkFloatEquality(prev);
});
} }
} }
@ -431,25 +449,38 @@ namespace BizHawk.Client.Common.RamSearchEngine
|| SignExtendAsNeeded(GetValue(w.Address)) - differentBy == compareValue); || SignExtendAsNeeded(GetValue(w.Address)) - differentBy == compareValue);
} }
} }
var compareValueF = ReinterpretAsF32(compareValue);
switch (Operator) switch (Operator)
{ {
default: default:
case ComparisonOperator.Equal: case ComparisonOperator.Equal:
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)).HawkFloatEquality(ReinterpretAsF32(compareValue))); return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)).HawkFloatEquality(compareValueF));
case ComparisonOperator.NotEqual: case ComparisonOperator.NotEqual:
return watchList.Where(w => !ReinterpretAsF32(GetValue(w.Address)).HawkFloatEquality(ReinterpretAsF32(compareValue))); return watchList.Where(w => !ReinterpretAsF32(GetValue(w.Address)).HawkFloatEquality(compareValueF));
case ComparisonOperator.GreaterThan: case ComparisonOperator.GreaterThan:
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) > ReinterpretAsF32(compareValue)); return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) > compareValueF);
case ComparisonOperator.GreaterThanEqual: case ComparisonOperator.GreaterThanEqual:
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) >= ReinterpretAsF32(compareValue)); return watchList.Where(w =>
{
var val = ReinterpretAsF32(GetValue(w.Address));
return val > compareValueF || val.HawkFloatEquality(compareValueF);
});
case ComparisonOperator.LessThan: case ComparisonOperator.LessThan:
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) < ReinterpretAsF32(compareValue)); return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) < compareValueF);
case ComparisonOperator.LessThanEqual: case ComparisonOperator.LessThanEqual:
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) <= ReinterpretAsF32(compareValue)); return watchList.Where(w =>
{
var val = ReinterpretAsF32(GetValue(w.Address));
return val < compareValueF || val.HawkFloatEquality(compareValueF);
});
case ComparisonOperator.DifferentBy: case ComparisonOperator.DifferentBy:
if (DifferentBy is not int differentBy) throw new InvalidOperationException(); if (DifferentBy is not int differentBy) throw new InvalidOperationException();
return watchList.Where(w => (ReinterpretAsF32(GetValue(w.Address)) + differentBy).HawkFloatEquality(compareValue) var differentByF = ReinterpretAsF32(differentBy);
|| (ReinterpretAsF32(GetValue(w.Address)) - differentBy).HawkFloatEquality(compareValue)); return watchList.Where(w =>
{
var val = ReinterpretAsF32(GetValue(w.Address));
return (val + differentByF).HawkFloatEquality(compareValueF) || (val - differentByF).HawkFloatEquality(compareValueF);
});
} }
} }
@ -544,25 +575,38 @@ namespace BizHawk.Client.Common.RamSearchEngine
|| SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) - differentBy == compareValue); || SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) - differentBy == compareValue);
} }
} }
var compareValueF = ReinterpretAsF32(compareValue);
switch (Operator) switch (Operator)
{ {
default: default:
case ComparisonOperator.Equal: case ComparisonOperator.Equal:
return watchList.Where(w => (ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous)).HawkFloatEquality(compareValue)); return watchList.Where(w => (ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous)).HawkFloatEquality(compareValueF));
case ComparisonOperator.NotEqual: case ComparisonOperator.NotEqual:
return watchList.Where(w => !(ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous)).HawkFloatEquality(compareValue)); return watchList.Where(w => !(ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous)).HawkFloatEquality(compareValueF));
case ComparisonOperator.GreaterThan: case ComparisonOperator.GreaterThan:
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous) > compareValue); return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous) > compareValueF);
case ComparisonOperator.GreaterThanEqual: case ComparisonOperator.GreaterThanEqual:
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous) >= compareValue); return watchList.Where(w =>
{
var diff = ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous);
return diff > compareValueF || diff.HawkFloatEquality(compareValueF);
});
case ComparisonOperator.LessThan: case ComparisonOperator.LessThan:
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous) < compareValue); return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous) < compareValueF);
case ComparisonOperator.LessThanEqual: case ComparisonOperator.LessThanEqual:
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous) <= compareValue); return watchList.Where(w =>
{
var diff = ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous);
return diff < compareValueF || diff.HawkFloatEquality(compareValueF);
});
case ComparisonOperator.DifferentBy: case ComparisonOperator.DifferentBy:
if (DifferentBy is not int differentBy) throw new InvalidOperationException(); if (DifferentBy is not int differentBy) throw new InvalidOperationException();
return watchList.Where(w => (ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous) + differentBy).HawkFloatEquality(compareValue) var differentByF = ReinterpretAsF32(differentBy);
|| (ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous) - differentBy).HawkFloatEquality(w.Previous)); return watchList.Where(w =>
{
var diff = ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous);
return (diff + differentByF).HawkFloatEquality(compareValueF) || (diff - differentByF).HawkFloatEquality(compareValueF);
});
} }
} }