Skip to content

BigInt multiplication of 0 by integral (non-BigInt) type creates "-0" (negative zero) #10565

@dlangBugzillaToGithub

Description

@dlangBugzillaToGithub

conorobrien4god reported this on 2024-11-05T23:16:58Z

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

Description

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 (

if (y == 0)
), which in turn is propagated to the non-mutating opAssign method (
r.opOpAssign!(op)(y);
); 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);
  }
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions