@@ -56,26 +56,15 @@ pub use csv_io::*;
5656// CSV load/save functionality - only available in tests (polars is a dev-dependency)
5757#[ cfg( test) ]
5858mod csv_io {
59- /// Count decimal places in a numeric string (for precision-aware comparison)
60- pub fn decimal_places ( s : & str ) -> usize {
61- if let Some ( dot_pos) = s. find ( '.' ) {
62- s. len ( ) - dot_pos - 1
59+ /// Compare f64 to expected string with relative tolerance
60+ pub fn float_eq ( actual : f64 , expected_str : & str ) -> bool {
61+ let expected: f64 = expected_str. parse ( ) . expect ( "Failed to parse expected value" ) ;
62+ if expected == 0.0 {
63+ actual. abs ( ) < 1e-14
6364 } else {
64- 0
65+ ( ( actual - expected ) / expected ) . abs ( ) < 1e-12
6566 }
6667 }
67-
68- /// Round f64 to specified decimal places, return as string
69- pub fn round_to_string ( val : f64 , places : usize ) -> String {
70- format ! ( "{:.prec$}" , val, prec = places)
71- }
72-
73- /// Compare f64 to expected string, rounding actual to same precision as expected
74- pub fn precision_eq ( actual : f64 , expected_str : & str ) -> bool {
75- let places = decimal_places ( expected_str) ;
76- let rounded_actual = round_to_string ( actual, places) ;
77- rounded_actual == expected_str
78- }
7968 use std:: collections:: BTreeMap ;
8069 use std:: path:: Path ;
8170 use super :: * ;
@@ -231,18 +220,15 @@ mod csv_io {
231220 Ok ( ExpectedHistory { col_names, steps } )
232221 }
233222
234- /// Compare actual HistoryStep against expected, using precision from expected strings
223+ /// Compare actual HistoryStep against expected with relative tolerance
235224 pub fn check_step ( & self , step_idx : usize , actual : & HistoryStep ) -> Result < ( ) , String > {
236225 let expected = & self . steps [ step_idx] ;
237226
238227 // Check error
239- if !precision_eq ( actual. error , & expected. error ) {
228+ if !float_eq ( actual. error , & expected. error ) {
240229 return Err ( format ! (
241- "Step {} error mismatch:\n expected: {}\n actual: {} (rounded: {})" ,
242- step_idx,
243- expected. error,
244- actual. error,
245- round_to_string( actual. error, decimal_places( & expected. error) )
230+ "Step {} error mismatch:\n expected: {}\n actual: {}" ,
231+ step_idx, expected. error, actual. error
246232 ) ) ;
247233 }
248234
@@ -256,16 +242,11 @@ mod csv_io {
256242 }
257243
258244 for ( i, ( actual_val, expected_str) ) in actual_vals. iter ( ) . zip ( expected. shape_vals . iter ( ) ) . enumerate ( ) {
259- if !precision_eq ( * actual_val, expected_str) {
245+ if !float_eq ( * actual_val, expected_str) {
260246 let col_name = self . col_names . get ( i + 1 ) . map ( |s| s. as_str ( ) ) . unwrap_or ( "?" ) ;
261247 return Err ( format ! (
262- "Step {} column {} ({}) mismatch:\n expected: {}\n actual: {} (rounded: {})" ,
263- step_idx,
264- i,
265- col_name,
266- expected_str,
267- actual_val,
268- round_to_string( * actual_val, decimal_places( expected_str) )
248+ "Step {} column {} ({}) mismatch:\n expected: {}\n actual: {}" ,
249+ step_idx, i, col_name, expected_str, actual_val
269250 ) ) ;
270251 }
271252 }
0 commit comments