Skip to content

Commit 0b4461d

Browse files
Fix tautological big_int tests.
1 parent f1b536c commit 0b4461d

File tree

5 files changed

+68
-37
lines changed

5 files changed

+68
-37
lines changed

lib/std/math/big/int.zig

+23-5
Original file line numberDiff line numberDiff line change
@@ -1176,15 +1176,26 @@ pub const Mutable = struct {
11761176
/// `a.limbs.len - (shift / (@sizeOf(Limb) * 8))`.
11771177
pub fn shiftRight(r: *Mutable, a: Const, shift: usize) void {
11781178
if (a.limbs.len <= shift / limb_bits) {
1179-
r.len = 1;
1180-
r.positive = true;
1181-
r.limbs[0] = 0;
1179+
// Shifting negative numbers converges to -1 instead of 0
1180+
if (a.positive) {
1181+
r.len = 1;
1182+
r.positive = true;
1183+
r.limbs[0] = 0;
1184+
} else {
1185+
r.len = 1;
1186+
r.positive = false;
1187+
r.limbs[0] = 1;
1188+
}
11821189
return;
11831190
}
11841191

11851192
llshr(r.limbs[0..], a.limbs[0..a.limbs.len], shift);
11861193
r.normalize(a.limbs.len - (shift / limb_bits));
11871194
r.positive = a.positive;
1195+
// Shifting negative numbers converges to -1 instead of 0
1196+
if (!r.positive and r.len == 1 and r.limbs[0] == 0) {
1197+
r.limbs[0] = 1;
1198+
}
11881199
}
11891200

11901201
/// r = ~a under 2s complement wrapping semantics.
@@ -2974,8 +2985,15 @@ pub const Managed = struct {
29742985
/// r and a may alias.
29752986
pub fn shiftRight(r: *Managed, a: *const Managed, shift: usize) !void {
29762987
if (a.len() <= shift / limb_bits) {
2977-
r.metadata = 1;
2978-
r.limbs[0] = 0;
2988+
// Shifting negative numbers converges to -1 instead of 0
2989+
if (a.isPositive()) {
2990+
r.metadata = 1;
2991+
r.limbs[0] = 0;
2992+
} else {
2993+
r.metadata = 1;
2994+
r.setSign(false);
2995+
r.limbs[0] = 1;
2996+
}
29792997
return;
29802998
}
29812999

lib/std/math/big/int_test.zig

+33-30
Original file line numberDiff line numberDiff line change
@@ -516,8 +516,8 @@ test "big.int add multi-single" {
516516
}
517517

518518
test "big.int add multi-multi" {
519-
const op1 = 0xefefefef7f7f7f7f;
520-
const op2 = 0xfefefefe9f9f9f9f;
519+
var op1: u128 = 0xefefefef7f7f7f7f;
520+
var op2: u128 = 0xfefefefe9f9f9f9f;
521521
var a = try Managed.initSet(testing.allocator, op1);
522522
defer a.deinit();
523523
var b = try Managed.initSet(testing.allocator, op2);
@@ -830,8 +830,8 @@ test "big.int sub multi-single" {
830830
}
831831

832832
test "big.int sub multi-multi" {
833-
const op1 = 0xefefefefefefefefefefefef;
834-
const op2 = 0xabababababababababababab;
833+
var op1: u128 = 0xefefefefefefefefefefefef;
834+
var op2: u128 = 0xabababababababababababab;
835835

836836
var a = try Managed.initSet(testing.allocator, op1);
837837
defer a.deinit();
@@ -914,8 +914,8 @@ test "big.int mul multi-single" {
914914
}
915915

916916
test "big.int mul multi-multi" {
917-
const op1 = 0x998888efefefefefefefef;
918-
const op2 = 0x333000abababababababab;
917+
var op1: u256 = 0x998888efefefefefefefef;
918+
var op2: u256 = 0x333000abababababababab;
919919
var a = try Managed.initSet(testing.allocator, op1);
920920
defer a.deinit();
921921
var b = try Managed.initSet(testing.allocator, op2);
@@ -1033,8 +1033,8 @@ test "big.int mulWrap single-single signed" {
10331033
}
10341034

10351035
test "big.int mulWrap multi-multi unsigned" {
1036-
const op1 = 0x998888efefefefefefefef;
1037-
const op2 = 0x333000abababababababab;
1036+
var op1: u256 = 0x998888efefefefefefefef;
1037+
var op2: u256 = 0x333000abababababababab;
10381038
var a = try Managed.initSet(testing.allocator, op1);
10391039
defer a.deinit();
10401040
var b = try Managed.initSet(testing.allocator, op2);
@@ -1044,7 +1044,7 @@ test "big.int mulWrap multi-multi unsigned" {
10441044
defer c.deinit();
10451045
try c.mulWrap(&a, &b, .unsigned, 65);
10461046

1047-
try testing.expect((try c.to(u128)) == (op1 * op2) & ((1 << 65) - 1));
1047+
try testing.expect((try c.to(u256)) == (op1 * op2) & ((1 << 65) - 1));
10481048
}
10491049

10501050
test "big.int mulWrap multi-multi signed" {
@@ -1150,8 +1150,8 @@ test "big.int div single-single with rem" {
11501150
}
11511151

11521152
test "big.int div multi-single no rem" {
1153-
const op1 = 0xffffeeeeddddcccc;
1154-
const op2 = 34;
1153+
var op1: u128 = 0xffffeeeeddddcccc;
1154+
var op2: u128 = 34;
11551155

11561156
var a = try Managed.initSet(testing.allocator, op1);
11571157
defer a.deinit();
@@ -1169,8 +1169,8 @@ test "big.int div multi-single no rem" {
11691169
}
11701170

11711171
test "big.int div multi-single with rem" {
1172-
const op1 = 0xffffeeeeddddcccf;
1173-
const op2 = 34;
1172+
var op1: u128 = 0xffffeeeeddddcccf;
1173+
var op2: u128 = 34;
11741174

11751175
var a = try Managed.initSet(testing.allocator, op1);
11761176
defer a.deinit();
@@ -1188,8 +1188,8 @@ test "big.int div multi-single with rem" {
11881188
}
11891189

11901190
test "big.int div multi>2-single" {
1191-
const op1 = 0xfefefefefefefefefefefefefefefefe;
1192-
const op2 = 0xefab8;
1191+
var op1: u128 = 0xfefefefefefefefefefefefefefefefe;
1192+
var op2: u128 = 0xefab8;
11931193

11941194
var a = try Managed.initSet(testing.allocator, op1);
11951195
defer a.deinit();
@@ -1981,22 +1981,22 @@ test "big.int shift-right negative" {
19811981
var arg = try Managed.initSet(testing.allocator, -20);
19821982
defer arg.deinit();
19831983
try a.shiftRight(&arg, 2);
1984-
try testing.expect((try a.to(i32)) == -20 >> 2);
1984+
try testing.expect((try a.to(i32)) == -5); // -20 >> 2 == -5
19851985

19861986
var arg2 = try Managed.initSet(testing.allocator, -5);
19871987
defer arg2.deinit();
19881988
try a.shiftRight(&arg2, 10);
1989-
try testing.expect((try a.to(i32)) == -5 >> 10);
1989+
try testing.expect((try a.to(i32)) == -1); // -5 >> 10 == -1
19901990
}
19911991

1992-
test "big.int shift-left negative" {
1992+
test "big.int shift-right negative" {
19931993
var a = try Managed.init(testing.allocator);
19941994
defer a.deinit();
19951995

19961996
var arg = try Managed.initSet(testing.allocator, -10);
19971997
defer arg.deinit();
19981998
try a.shiftRight(&arg, 1232);
1999-
try testing.expect((try a.to(i32)) == -10 >> 1232);
1999+
try testing.expect((try a.to(i32)) == -1); // -10 >> 1232 == -1
20002000
}
20012001

20022002
test "big.int sat shift-left simple unsigned" {
@@ -2064,34 +2064,35 @@ test "big.int sat shift-left signed simple positive" {
20642064
}
20652065

20662066
test "big.int sat shift-left signed multi positive" {
2067-
const x = 1;
2067+
var x: SignedDoubleLimb = 1;
20682068
const shift = @bitSizeOf(SignedDoubleLimb) - 1;
20692069

20702070
var a = try Managed.initSet(testing.allocator, x);
20712071
defer a.deinit();
20722072
try a.shiftLeftSat(&a, shift, .signed, @bitSizeOf(SignedDoubleLimb));
20732073

2074-
try testing.expect((try a.to(SignedDoubleLimb)) == @as(SignedDoubleLimb, x) <<| shift);
2074+
try testing.expect((try a.to(SignedDoubleLimb)) == x <<| shift);
20752075
}
20762076

20772077
test "big.int sat shift-left signed multi negative" {
2078-
const x = -1;
2078+
var x: SignedDoubleLimb = -1;
20792079
const shift = @bitSizeOf(SignedDoubleLimb) - 1;
20802080

20812081
var a = try Managed.initSet(testing.allocator, x);
20822082
defer a.deinit();
20832083
try a.shiftLeftSat(&a, shift, .signed, @bitSizeOf(SignedDoubleLimb));
20842084

2085-
try testing.expect((try a.to(SignedDoubleLimb)) == @as(SignedDoubleLimb, x) <<| shift);
2085+
try testing.expect((try a.to(SignedDoubleLimb)) == x <<| shift);
20862086
}
20872087

20882088
test "big.int bitNotWrap unsigned simple" {
2089-
var a = try Managed.initSet(testing.allocator, 123);
2089+
var x: u10 = 123;
2090+
var a = try Managed.initSet(testing.allocator, x);
20902091
defer a.deinit();
20912092

20922093
try a.bitNotWrap(&a, .unsigned, 10);
20932094

2094-
try testing.expect((try a.to(u10)) == ~@as(u10, 123));
2095+
try testing.expect((try a.to(u10)) == ~x);
20952096
}
20962097

20972098
test "big.int bitNotWrap unsigned multi" {
@@ -2104,12 +2105,13 @@ test "big.int bitNotWrap unsigned multi" {
21042105
}
21052106

21062107
test "big.int bitNotWrap signed simple" {
2108+
var x: i11 = -456;
21072109
var a = try Managed.initSet(testing.allocator, -456);
21082110
defer a.deinit();
21092111

21102112
try a.bitNotWrap(&a, .signed, 11);
21112113

2112-
try testing.expect((try a.to(i11)) == ~@as(i11, -456));
2114+
try testing.expect((try a.to(i11)) == ~x);
21132115
}
21142116

21152117
test "big.int bitNotWrap signed multi" {
@@ -2232,14 +2234,16 @@ test "big.int bitwise xor simple" {
22322234
}
22332235

22342236
test "big.int bitwise xor multi-limb" {
2235-
var a = try Managed.initSet(testing.allocator, maxInt(Limb) + 1);
2237+
var x: DoubleLimb = maxInt(Limb) + 1;
2238+
var y: DoubleLimb = maxInt(Limb);
2239+
var a = try Managed.initSet(testing.allocator, x);
22362240
defer a.deinit();
2237-
var b = try Managed.initSet(testing.allocator, maxInt(Limb));
2241+
var b = try Managed.initSet(testing.allocator, y);
22382242
defer b.deinit();
22392243

22402244
try a.bitXor(&a, &b);
22412245

2242-
try testing.expect((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) ^ maxInt(Limb));
2246+
try testing.expect((try a.to(DoubleLimb)) == x ^ y);
22432247
}
22442248

22452249
test "big.int bitwise xor single negative simple" {
@@ -2327,7 +2331,6 @@ test "big.int bitwise or multi-limb" {
23272331

23282332
try a.bitOr(&a, &b);
23292333

2330-
// TODO: big.int.cpp or is wrong on multi-limb.
23312334
try testing.expect((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) + maxInt(Limb));
23322335
}
23332336

src/value.zig

+6-2
Original file line numberDiff line numberDiff line change
@@ -4194,8 +4194,12 @@ pub const Value = extern union {
41944194
const result_limbs = lhs_bigint.limbs.len -| (shift / (@sizeOf(std.math.big.Limb) * 8));
41954195
if (result_limbs == 0) {
41964196
// The shift is enough to remove all the bits from the number, which means the
4197-
// result is zero.
4198-
return Value.zero;
4197+
// result is 0 or -1 depending on the sign.
4198+
if (lhs_bigint.positive) {
4199+
return Value.zero;
4200+
} else {
4201+
return Value.negative_one;
4202+
}
41994203
}
42004204

42014205
const limbs = try allocator.alloc(

test/behavior.zig

+1
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ test {
125125
_ = @import("behavior/bugs/13159.zig");
126126
_ = @import("behavior/bugs/13164.zig");
127127
_ = @import("behavior/bugs/13171.zig");
128+
_ = @import("behavior/bugs/13209.zig");
128129
_ = @import("behavior/bugs/13285.zig");
129130
_ = @import("behavior/bugs/13435.zig");
130131
_ = @import("behavior/bugs/13664.zig");

test/behavior/bugs/13209.zig

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const std = @import("std");
2+
test {
3+
try std.testing.expect(-1 == @as(i8, -3) >> 2);
4+
try std.testing.expect(-1 == -3 >> 2000);
5+
}

0 commit comments

Comments
 (0)