- 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));
}
https://learn.microsoft.com/uk-ua/dotnet/api/system.numerics.complex.pow?view=net-10.0
Только вот какого хрена там первый аргумент комплесный, второй это обычный дабл? У меня в Си у "cpow" оба аргумента комплексные:
Именно поэтому я за Си
Это как? Встроенный в язык тип что ли?
Там и Imaginary есть
Т. е. на уровне языка I не зашкварена, есть просто суффикс для литералов: 1.23i. Значит, никакой необходимости в #define I нету.
Это авгиевы конюшни.
Слово "макрос" пишется с большой буквы
Так вот с комплексными что-то похожее: они позволяют некоторые задачи решать единой формулой без ветвления.
// these functions can return incorrect results
.net: write once, test everywhere. Сука.
Это как если бы оператор "+" у двух четрехбайтовых целых зависел от версии либси
А ты над библиотекой смеёшься...
К слову, в первая партия 80386 оказалась бракованной: на ней целочисленное деление 32-битных чисел (в смысле не когда 32 бита в DX+AX, а когда делитель 32-битный) иногда давало неправильный результат. Эту партию процессоров промаркировали: «Только для 16-битных приложений!» Вторая партия была уже исправленной.
А в «Пентиуме» ничего исправлять не стали, поэтому в библиотеках пришлось городить «fdiv workaround».
1. Если знаменатель показателя степени чётный, посылал нахуй, ибо результат в этом случае должен быть чисто мнимым, а я писал для вещественных чисел.
2. Если знаменатель показателя степени нечётный, то знак результата выбирал в зависимости от чётности числителя показателя степени.
При положительном основании, естественно, проблем нет.
То есть я доопределил операцию возведения в степень до предсказуемого результата, выбрав при дробном показателе самый очевидный корень.