Skip to content

Commit 2da2123

Browse files
authored
Make mir parse testing consider lower bound more flexibly (libmir#480)
* Make mir parse testing consider lower bound more flexibly * Put parse code under CRuntime_Microsoft version block, clear up variable naming
1 parent 9bcd21d commit 2da2123

File tree

1 file changed

+40
-1
lines changed

1 file changed

+40
-1
lines changed

source/mir/parse.d

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,46 @@ version(mir_bignum_test)
209209
else
210210
{
211211
str.fromString!float.should == str._stdc_parse!float;
212-
str.fromString!double.should == str._stdc_parse!double;
212+
auto mirStrValue = str.fromString!double;
213+
auto crtStrValue = str._stdc_parse!double;
214+
215+
version(CRuntime_Microsoft) {
216+
// Some Windows CRTs clamp extreme underflow to min-subnormal instead of 0.
217+
// Accept both behaviors *only* at the very bottom of the subnormal range.
218+
bool equalOrTinyUnderflow(double a, double b)
219+
{
220+
import core.stdc.math: fpclassify, FP_SUBNORMAL;
221+
import mir.math.common: fabs;
222+
import mir.math.ieee: signbit;
223+
import std.math.operations: nextafter;
224+
225+
if (a == b) return true;
226+
if (signbit(a) != signbit(b)) return false;
227+
228+
enum double minSub = nextafter(0.0, 1.0); // smallest positive subnormal
229+
230+
const aa = fabs(a);
231+
const bb = fabs(b);
232+
233+
// 0 <-> min-subnormal (or similar one-ULP-at-zero behavior)
234+
if (aa == 0.0 && bb > 0.0)
235+
return fpclassify(b) == FP_SUBNORMAL && bb <= minSub;
236+
if (bb == 0.0 && aa > 0.0)
237+
return fpclassify(a) == FP_SUBNORMAL && aa <= minSub;
238+
239+
// If both are subnormal, permit differences only if both are at the very bottom.
240+
if (fpclassify(a) == FP_SUBNORMAL && fpclassify(b) == FP_SUBNORMAL)
241+
return aa <= minSub && bb <= minSub;
242+
243+
return false;
244+
}
245+
if (!equalOrTinyUnderflow(mirStrValue, crtStrValue)) {
246+
mirStrValue.should == crtStrValue;
247+
}
248+
} else {
249+
mirStrValue.should == crtStrValue;
250+
}
251+
213252
version (Windows) // No precise real parsing on windows
214253
{
215254
}

0 commit comments

Comments
 (0)