- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
// https://github.com/dotnet/runtime/issues/117233#issuecomment-3028066225
// Issue: Math.Pow relies directly on the OS pow implementation
// Location: [src/coreclr/classlibnative/float/floatdouble.cpp lines 232‑236] and [src/coreclr/classlibnative/float/floatsingle.cpp lines 207‑211]
// COMDouble::Pow and COMSingle::Pow simply call pow/powf from the C runtime. On Windows 11 Insider Preview (build 27881.1000),
// these functions can return incorrect results (e.g., Math.Pow(-1, 2) giving -1). The JIT also uses these functions for constant folding, causing
// wrong constants to be embedded at compile time.
// Suggested Fix: Introduce a managed fallback in COMDouble::Pow/COMSingle::Pow that handles negative bases with integral exponents, bypassing the faulty system call.
//A simple approach:
FCIMPL2_VV(double, COMDouble::Pow, double x, double y)
{
FCALL_CONTRACT;
if ((x < 0.0) && (y == floor(y)))
{
double absResult = pow(-x, y);
return fmod(fabs(y), 2.0) == 1.0 ? -absResult : absResult;
}
return pow(x, y);
}
// Suggested Implementation:
// Add the following code to src/coreclr/classlibnative/float/floatdouble.cpp below line 234 before the return pow:
if ((x < 0.0) && (y == floor(y)))
{
double result = pow(-x, y);
if (fmod(fabs(y), 2.0) != 0.0)
{
result = -result;
}
return result;
}
// Add the following code to src/coreclr/classlibnative/float/floatsingle.cpp below line 209 before the return powf:
if ((x < 0.0f) && (y == floorf(y)))
{
float result = powf(-x, y);
if (fmodf(fabsf(y), 2.0f) != 0.0f)
{
result = -result;
}
return result;
}
// Add the following code to src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/Math.cs below line 1124:
[Fact]
public static void Pow_NegativeBaseEvenExponent_ReturnsPositive()
{
Assert.Equal(1.0, Math.Pow(-1, 2));
Assert.Equal(16.0, Math.Pow(-2, 4));
}