September 11, 2023
https://issues.dlang.org/show_bug.cgi?id=24140

          Issue ID: 24140
           Summary: Int128.opBinary [+-*/%&|^] with negative long
                    arguments gives wrong answers
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P1
         Component: phobos
          Assignee: nobody@puremagic.com
          Reporter: n8sh.secondary@hotmail.com

The longs are converted to Int128 without sign extension. This is the same thing that was going on in https://issues.dlang.org/show_bug.cgi?id=24083.

---
void main()
{
    import std.int128 : Int128;
    import std.stdio : writeln;

    const zero = Int128(0L);
    const neg_one = Int128(-1L);
    const neg_two = Int128(-2L);
    // Correct result with unsigned arguments:
    assert(zero + ulong.max == ulong.max);
    assert(neg_two * 3UL == -6L);
    assert(neg_two / 2UL == -1L);
    assert(neg_two % 2UL == 0L);
    assert((neg_one & ulong.max) == ulong.max);
    assert((zero | ulong.max) == ulong.max);
    assert((zero ^ ulong.max) == ulong.max);
    // Incorrect result with unsigned arguments:
    writeln(zero + -1L == -1L); // "false"
    writeln(neg_two * -3L == 6L); // "false"
    writeln(neg_two / -2L == 1L); // "false"
    writeln(neg_two % -2L == 0L); // "false"
    writeln((neg_one & -1L) == -1L); // "false"
    writeln((zero | -1L) == -1L); // "false"
    writeln((zero ^ -1L) == -1L); // "false"
}
---

--