[Issue 24844] New: BigInt multiplication of 0 by integral (non-BigInt) type creates "-0" (negative zero)

d-bugmail at puremagic.com d-bugmail at puremagic.com
Tue Nov 5 23:16:58 UTC 2024


https://issues.dlang.org/show_bug.cgi?id=24844

          Issue ID: 24844
           Summary: BigInt multiplication of 0 by integral (non-BigInt)
                    type creates "-0" (negative zero)
           Product: D
           Version: D2
          Hardware: x86
                OS: Windows
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: phobos
          Assignee: nobody at puremagic.com
          Reporter: conorobrien4god at gmail.com

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);
  }
}

--


More information about the Digitalmars-d-bugs mailing list