Comment #0 by conorobrien4god — 2024-11-05T23:16:58Z
Overview:
When multiplying a BigInt `0` by a negative, basic type (e.g. `-1` and `cast(byte)(-1)`), the resulting BigInt is `-0` (negative zero), which creates unexpected behavior.
It is likely a logical error in the `isIntegral!y` variant of the mutating `opOpAssign` method (https://github.com/dlang/phobos/blob/9771a247f540ad0f16822bbffbb1724e218915ba/std/bigint.d#L268), which in turn is propagated to the non-mutating `opAssign` method (https://github.com/dlang/phobos/blob/9771a247f540ad0f16822bbffbb1724e218915ba/std/bigint.d#L524); I imagine the linked conditional in `opOpAssign` should read something like `if(y == 0 || data == 0UL)` to prevent the sign being erroneously set for multiplication from `0`, but I am not sure what the best modification should be.
The appearance of `-0` (negative zero) appears to be a mistake, as evidenced by the resolved and fixed https://issues.dlang.org/show_bug.cgi?id=22771.
Steps to Reproduce:
Tested in the latest version of D (DMD64 D Compiler v2.109.1) and on https://run.dlang.io/
MWE demonstrating the bug, and when it occurs:
import std.stdio : writeln;
import std.bigint;
void main() {
BigInt a = BigInt("0"); // 0
BigInt b = BigInt("-0"); // 0
BigInt c = BigInt("0") * -1; // -0
BigInt d = BigInt("0") * -42; // -0
BigInt e = BigInt("0"); e *= -1; // -0
BigInt f = BigInt(c); // -0
BigInt g = BigInt("0") * cast(byte) -1; // -0
BigInt h = BigInt("0"); h *= BigInt("-1"); // 0
BigInt i = BigInt("0"); i -= 2 * i; // 0
BigInt j = BigInt("0"); j = -j; // 0
BigInt[] test = [a,b,c,d,e,f,g,h,i,j];
foreach(idx, t; test) {
char id = "abcdefghij"[idx];
writeln("`", id, "` = ", t);
writeln(" Is `", id, "` negative? ", t < 0);
writeln(" Is `", id, "` zero? ", t == 0);
}
}
Comment #1 by robert.schadek — 2024-12-01T16:43:09Z