Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
dlangBugzillaToGithub opened this issue Nov 5, 2024 · 0 comments

Comments

@dlangBugzillaToGithub
Copy link

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 (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);
  }
}
@thewilsonator thewilsonator added std.bigint and removed OS:Windows Issues Specific to Windows Arch:x86 Issues specific to x86 P1 labels Dec 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants