authorgravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2019-04-09 17:44:49+12:00
committergravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2019-04-11 19:36:35+12:00
log78af62a19a87904193c59f46ac554330ba872564
treeaf89875455723e0ec9bd2d3f1159b85258054d30
parent87d8ecda462688c597c726b1da5dbd5f8478e0fc

Pack big.Int sign and length fields

This effectively takes one-bit from the length field and uses it as the sign bit. It reduces the size of an Int from 40 bits to 32 bits on a 64-bit arch. This also reduces std.Rational from 80 bits to 64 bits.

3 files changed, 203 insertions(+), 185 deletions(-)

src-self-hosted/value.zig+4-4
...@@ -538,21 +538,21 @@ pub const Value = struct {...@@ -538,21 +538,21 @@ pub const Value = struct {
538 switch (self.base.typ.id) {538 switch (self.base.typ.id) {
539 Type.Id.Int => {539 Type.Id.Int => {
540 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);540 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
541 if (self.big_int.len == 0) {541 if (self.big_int.len() == 0) {
542 return llvm.ConstNull(type_ref);542 return llvm.ConstNull(type_ref);
543 }543 }
544 const unsigned_val = if (self.big_int.len == 1) blk: {544 const unsigned_val = if (self.big_int.len() == 1) blk: {
545 break :blk llvm.ConstInt(type_ref, self.big_int.limbs[0], @boolToInt(false));545 break :blk llvm.ConstInt(type_ref, self.big_int.limbs[0], @boolToInt(false));
546 } else if (@sizeOf(std.math.big.Limb) == @sizeOf(u64)) blk: {546 } else if (@sizeOf(std.math.big.Limb) == @sizeOf(u64)) blk: {
547 break :blk llvm.ConstIntOfArbitraryPrecision(547 break :blk llvm.ConstIntOfArbitraryPrecision(
548 type_ref,548 type_ref,
549 @intCast(c_uint, self.big_int.len),549 @intCast(c_uint, self.big_int.len()),
550 @ptrCast([*]u64, self.big_int.limbs.ptr),550 @ptrCast([*]u64, self.big_int.limbs.ptr),
551 );551 );
552 } else {552 } else {
553 @compileError("std.math.Big.Int.Limb size does not match LLVM");553 @compileError("std.math.Big.Int.Limb size does not match LLVM");
554 };554 };
555 return if (self.big_int.positive) unsigned_val else llvm.ConstNeg(unsigned_val);555 return if (self.big_int.isPositive()) unsigned_val else llvm.ConstNeg(unsigned_val);
556 },556 },
557 Type.Id.ComptimeInt => unreachable,557 Type.Id.ComptimeInt => unreachable,
558 else => unreachable,558 else => unreachable,
std/math/big/int.zig+179-162
...@@ -22,13 +22,18 @@ comptime {...@@ -22,13 +22,18 @@ comptime {
22}22}
2323
24pub const Int = struct {24pub const Int = struct {
25 const sign_bit: usize = 1 << (usize.bit_count - 1);
26
25 allocator: ?*Allocator,27 allocator: ?*Allocator,
26 positive: bool,
27 // - little-endian ordered28 // - little-endian ordered
28 // - len >= 1 always29 // - len >= 1 always
29 // - zero value -> len == 1 with limbs[0] == 030 // - zero value -> len == 1 with limbs[0] == 0
30 limbs: []Limb,31 limbs: []Limb,
31 len: usize,32 // High bit is the sign bit. 1 is negative, 0 positive.
33 // Remaining bits indicate the number of used limbs.
34 //
35 // If Zig gets smarter about packing data, this can be rewritten as a u1 and usize - 1 field.
36 metadata: usize,
3237
33 const default_capacity = 4;38 const default_capacity = 4;
3439
...@@ -45,26 +50,45 @@ pub const Int = struct {...@@ -45,26 +50,45 @@ pub const Int = struct {
45 pub fn initCapacity(allocator: *Allocator, capacity: usize) !Int {50 pub fn initCapacity(allocator: *Allocator, capacity: usize) !Int {
46 return Int{51 return Int{
47 .allocator = allocator,52 .allocator = allocator,
48 .positive = true,53 .metadata = 1,
49 .limbs = block: {54 .limbs = block: {
50 var limbs = try allocator.alloc(Limb, math.max(default_capacity, capacity));55 var limbs = try allocator.alloc(Limb, math.max(default_capacity, capacity));
51 limbs[0] = 0;56 limbs[0] = 0;
52 break :block limbs;57 break :block limbs;
53 },58 },
54 .len = 1,
55 };59 };
56 }60 }
5761
62 pub fn len(self: Int) usize {
63 return self.metadata & ~sign_bit;
64 }
65
66 pub fn isPositive(self: Int) bool {
67 return self.metadata & sign_bit == 0;
68 }
69
70 pub fn setSign(self: *Int, positive: bool) void {
71 if (positive) {
72 self.metadata &= ~sign_bit;
73 } else {
74 self.metadata |= sign_bit;
75 }
76 }
77
78 pub fn setLen(self: *Int, new_len: usize) void {
79 self.metadata &= sign_bit;
80 self.metadata |= new_len;
81 }
82
58 // Initialize an Int directly from a fixed set of limb values. This is considered read-only83 // Initialize an Int directly from a fixed set of limb values. This is considered read-only
59 // and cannot be used as a receiver argument to any functions. If this tries to allocate84 // and cannot be used as a receiver argument to any functions. If this tries to allocate
60 // at any point a panic will occur due to the null allocator.85 // at any point a panic will occur due to the null allocator.
61 pub fn initFixed(limbs: []const Limb) Int {86 pub fn initFixed(limbs: []const Limb) Int {
62 var self = Int{87 var self = Int{
63 .allocator = null,88 .allocator = null,
64 .positive = true,89 .metadata = limbs.len,
65 // Cast away the const, invalid use to pass as a pointer argument.90 // Cast away the const, invalid use to pass as a pointer argument.
66 .limbs = @intToPtr([*]Limb, @ptrToInt(limbs.ptr))[0..limbs.len],91 .limbs = @intToPtr([*]Limb, @ptrToInt(limbs.ptr))[0..limbs.len],
67 .len = limbs.len,
68 };92 };
6993
70 self.normalize(limbs.len);94 self.normalize(limbs.len);
...@@ -96,13 +120,12 @@ pub const Int = struct {...@@ -96,13 +120,12 @@ pub const Int = struct {
96 other.assertWritable();120 other.assertWritable();
97 return Int{121 return Int{
98 .allocator = other.allocator,122 .allocator = other.allocator,
99 .positive = other.positive,123 .metadata = other.metadata,
100 .limbs = block: {124 .limbs = block: {
101 var limbs = try other.allocator.?.alloc(Limb, other.len);125 var limbs = try other.allocator.?.alloc(Limb, other.len());
102 mem.copy(Limb, limbs[0..], other.limbs[0..other.len]);126 mem.copy(Limb, limbs[0..], other.limbs[0..other.len()]);
103 break :block limbs;127 break :block limbs;
104 },128 },
105 .len = other.len,
106 };129 };
107 }130 }
108131
...@@ -112,10 +135,9 @@ pub const Int = struct {...@@ -112,10 +135,9 @@ pub const Int = struct {
112 return;135 return;
113 }136 }
114137
115 self.positive = other.positive;138 try self.ensureCapacity(other.len());
116 try self.ensureCapacity(other.len);139 mem.copy(Limb, self.limbs[0..], other.limbs[0..other.len()]);
117 mem.copy(Limb, self.limbs[0..], other.limbs[0..other.len]);140 self.metadata = other.metadata;
118 self.len = other.len;
119 }141 }
120142
121 pub fn swap(self: *Int, other: *Int) void {143 pub fn swap(self: *Int, other: *Int) void {
...@@ -131,11 +153,11 @@ pub const Int = struct {...@@ -131,11 +153,11 @@ pub const Int = struct {
131 }153 }
132154
133 pub fn negate(self: *Int) void {155 pub fn negate(self: *Int) void {
134 self.positive = !self.positive;156 self.metadata ^= sign_bit;
135 }157 }
136158
137 pub fn abs(self: *Int) void {159 pub fn abs(self: *Int) void {
138 self.positive = true;160 self.metadata &= ~sign_bit;
139 }161 }
140162
141 pub fn isOdd(self: Int) bool {163 pub fn isOdd(self: Int) bool {
...@@ -148,7 +170,7 @@ pub const Int = struct {...@@ -148,7 +170,7 @@ pub const Int = struct {
148170
149 // Returns the number of bits required to represent the absolute value of self.171 // Returns the number of bits required to represent the absolute value of self.
150 fn bitCountAbs(self: Int) usize {172 fn bitCountAbs(self: Int) usize {
151 return (self.len - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len - 1]));173 return (self.len() - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len() - 1]));
152 }174 }
153175
154 // Returns the number of bits required to represent the integer in twos-complement form.176 // Returns the number of bits required to represent the integer in twos-complement form.
...@@ -164,11 +186,11 @@ pub const Int = struct {...@@ -164,11 +186,11 @@ pub const Int = struct {
164186
165 // If the entire value has only one bit set (e.g. 0b100000000) then the negation in twos187 // If the entire value has only one bit set (e.g. 0b100000000) then the negation in twos
166 // complement requires one less bit.188 // complement requires one less bit.
167 if (!self.positive) block: {189 if (!self.isPositive()) block: {
168 bits += 1;190 bits += 1;
169191
170 if (@popCount(self.limbs[self.len - 1]) == 1) {192 if (@popCount(self.limbs[self.len() - 1]) == 1) {
171 for (self.limbs[0 .. self.len - 1]) |limb| {193 for (self.limbs[0 .. self.len() - 1]) |limb| {
172 if (@popCount(limb) != 0) {194 if (@popCount(limb) != 0) {
173 break :block;195 break :block;
174 }196 }
...@@ -185,11 +207,11 @@ pub const Int = struct {...@@ -185,11 +207,11 @@ pub const Int = struct {
185 if (self.eqZero()) {207 if (self.eqZero()) {
186 return true;208 return true;
187 }209 }
188 if (!is_signed and !self.positive) {210 if (!is_signed and !self.isPositive()) {
189 return false;211 return false;
190 }212 }
191213
192 const req_bits = self.bitCountTwosComp() + @boolToInt(self.positive and is_signed);214 const req_bits = self.bitCountTwosComp() + @boolToInt(self.isPositive() and is_signed);
193 return bit_count >= req_bits;215 return bit_count >= req_bits;
194 }216 }
195217
...@@ -201,7 +223,7 @@ pub const Int = struct {...@@ -201,7 +223,7 @@ pub const Int = struct {
201 // the minus sign. This is used for determining the number of characters needed to print the223 // the minus sign. This is used for determining the number of characters needed to print the
202 // value. It is inexact and will exceed the given value by 1-2 digits.224 // value. It is inexact and will exceed the given value by 1-2 digits.
203 pub fn sizeInBase(self: Int, base: usize) usize {225 pub fn sizeInBase(self: Int, base: usize) usize {
204 const bit_count = usize(@boolToInt(!self.positive)) + self.bitCountAbs();226 const bit_count = usize(@boolToInt(!self.isPositive())) + self.bitCountAbs();
205 return (bit_count / math.log2(base)) + 1;227 return (bit_count / math.log2(base)) + 1;
206 }228 }
207229
...@@ -214,19 +236,19 @@ pub const Int = struct {...@@ -214,19 +236,19 @@ pub const Int = struct {
214 const UT = if (T.is_signed) @IntType(false, T.bit_count - 1) else T;236 const UT = if (T.is_signed) @IntType(false, T.bit_count - 1) else T;
215237
216 try self.ensureCapacity(@sizeOf(UT) / @sizeOf(Limb));238 try self.ensureCapacity(@sizeOf(UT) / @sizeOf(Limb));
217 self.positive = value >= 0;239 self.metadata = 0;
218 self.len = 0;240 self.setSign(value >= 0);
219241
220 var w_value: UT = if (value < 0) @intCast(UT, -value) else @intCast(UT, value);242 var w_value: UT = if (value < 0) @intCast(UT, -value) else @intCast(UT, value);
221243
222 if (info.bits <= Limb.bit_count) {244 if (info.bits <= Limb.bit_count) {
223 self.limbs[0] = Limb(w_value);245 self.limbs[0] = Limb(w_value);
224 self.len = 1;246 self.metadata += 1;
225 } else {247 } else {
226 var i: usize = 0;248 var i: usize = 0;
227 while (w_value != 0) : (i += 1) {249 while (w_value != 0) : (i += 1) {
228 self.limbs[i] = @truncate(Limb, w_value);250 self.limbs[i] = @truncate(Limb, w_value);
229 self.len += 1;251 self.metadata += 1;
230252
231 // TODO: shift == 64 at compile-time fails. Fails on u128 limbs.253 // TODO: shift == 64 at compile-time fails. Fails on u128 limbs.
232 w_value >>= Limb.bit_count / 2;254 w_value >>= Limb.bit_count / 2;
...@@ -240,8 +262,8 @@ pub const Int = struct {...@@ -240,8 +262,8 @@ pub const Int = struct {
240 const req_limbs = @divFloor(math.log2(w_value), Limb.bit_count) + 1;262 const req_limbs = @divFloor(math.log2(w_value), Limb.bit_count) + 1;
241 try self.ensureCapacity(req_limbs);263 try self.ensureCapacity(req_limbs);
242264
243 self.positive = value >= 0;265 self.metadata = req_limbs;
244 self.len = req_limbs;266 self.setSign(value >= 0);
245267
246 if (w_value <= maxInt(Limb)) {268 if (w_value <= maxInt(Limb)) {
247 self.limbs[0] = w_value;269 self.limbs[0] = w_value;
...@@ -282,17 +304,17 @@ pub const Int = struct {...@@ -282,17 +304,17 @@ pub const Int = struct {
282 if (@sizeOf(UT) <= @sizeOf(Limb)) {304 if (@sizeOf(UT) <= @sizeOf(Limb)) {
283 r = @intCast(UT, self.limbs[0]);305 r = @intCast(UT, self.limbs[0]);
284 } else {306 } else {
285 for (self.limbs[0..self.len]) |_, ri| {307 for (self.limbs[0..self.len()]) |_, ri| {
286 const limb = self.limbs[self.len - ri - 1];308 const limb = self.limbs[self.len() - ri - 1];
287 r <<= Limb.bit_count;309 r <<= Limb.bit_count;
288 r |= limb;310 r |= limb;
289 }311 }
290 }312 }
291313
292 if (!T.is_signed) {314 if (!T.is_signed) {
293 return if (self.positive) @intCast(T, r) else error.NegativeIntoUnsigned;315 return if (self.isPositive()) @intCast(T, r) else error.NegativeIntoUnsigned;
294 } else {316 } else {
295 if (self.positive) {317 if (self.isPositive()) {
296 return @intCast(T, r);318 return @intCast(T, r);
297 } else {319 } else {
298 if (math.cast(T, r)) |ok| {320 if (math.cast(T, r)) |ok| {
...@@ -355,7 +377,7 @@ pub const Int = struct {...@@ -355,7 +377,7 @@ pub const Int = struct {
355 try self.mul(self.*, ap_base);377 try self.mul(self.*, ap_base);
356 try self.add(self.*, ap_d);378 try self.add(self.*, ap_d);
357 }379 }
358 self.positive = positive;380 self.setSign(positive);
359 }381 }
360382
361 /// TODO make this call format instead of the other way around383 /// TODO make this call format instead of the other way around
...@@ -377,7 +399,7 @@ pub const Int = struct {...@@ -377,7 +399,7 @@ pub const Int = struct {
377 if (base & (base - 1) == 0) {399 if (base & (base - 1) == 0) {
378 const base_shift = math.log2_int(Limb, base);400 const base_shift = math.log2_int(Limb, base);
379401
380 for (self.limbs[0..self.len]) |limb| {402 for (self.limbs[0..self.len()]) |limb| {
381 var shift: usize = 0;403 var shift: usize = 0;
382 while (shift < Limb.bit_count) : (shift += base_shift) {404 while (shift < Limb.bit_count) : (shift += base_shift) {
383 const r = @intCast(u8, (limb >> @intCast(Log2Limb, shift)) & Limb(base - 1));405 const r = @intCast(u8, (limb >> @intCast(Log2Limb, shift)) & Limb(base - 1));
...@@ -404,11 +426,11 @@ pub const Int = struct {...@@ -404,11 +426,11 @@ pub const Int = struct {
404 }426 }
405427
406 var q = try self.clone();428 var q = try self.clone();
407 q.positive = true;429 q.abs();
408 var r = try Int.init(allocator);430 var r = try Int.init(allocator);
409 var b = try Int.initSet(allocator, limb_base);431 var b = try Int.initSet(allocator, limb_base);
410432
411 while (q.len >= 2) {433 while (q.len() >= 2) {
412 try Int.divTrunc(&q, &r, q, b);434 try Int.divTrunc(&q, &r, q, b);
413435
414 var r_word = r.limbs[0];436 var r_word = r.limbs[0];
...@@ -421,7 +443,7 @@ pub const Int = struct {...@@ -421,7 +443,7 @@ pub const Int = struct {
421 }443 }
422444
423 {445 {
424 debug.assert(q.len == 1);446 debug.assert(q.len() == 1);
425447
426 var r_word = q.limbs[0];448 var r_word = q.limbs[0];
427 while (r_word != 0) {449 while (r_word != 0) {
...@@ -432,7 +454,7 @@ pub const Int = struct {...@@ -432,7 +454,7 @@ pub const Int = struct {
432 }454 }
433 }455 }
434456
435 if (!self.positive) {457 if (!self.isPositive()) {
436 try digits.append('-');458 try digits.append('-');
437 }459 }
438460
...@@ -460,14 +482,14 @@ pub const Int = struct {...@@ -460,14 +482,14 @@ pub const Int = struct {
460482
461 // returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.483 // returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
462 pub fn cmpAbs(a: Int, b: Int) i8 {484 pub fn cmpAbs(a: Int, b: Int) i8 {
463 if (a.len < b.len) {485 if (a.len() < b.len()) {
464 return -1;486 return -1;
465 }487 }
466 if (a.len > b.len) {488 if (a.len() > b.len()) {
467 return 1;489 return 1;
468 }490 }
469491
470 var i: usize = a.len - 1;492 var i: usize = a.len() - 1;
471 while (i != 0) : (i -= 1) {493 while (i != 0) : (i -= 1) {
472 if (a.limbs[i] != b.limbs[i]) {494 if (a.limbs[i] != b.limbs[i]) {
473 break;495 break;
...@@ -485,17 +507,17 @@ pub const Int = struct {...@@ -485,17 +507,17 @@ pub const Int = struct {
485507
486 // returns -1, 0, 1 if a < b, a == b or a > b respectively.508 // returns -1, 0, 1 if a < b, a == b or a > b respectively.
487 pub fn cmp(a: Int, b: Int) i8 {509 pub fn cmp(a: Int, b: Int) i8 {
488 if (a.positive != b.positive) {510 if (a.isPositive() != b.isPositive()) {
489 return if (a.positive) i8(1) else -1;511 return if (a.isPositive()) i8(1) else -1;
490 } else {512 } else {
491 const r = cmpAbs(a, b);513 const r = cmpAbs(a, b);
492 return if (a.positive) r else -r;514 return if (a.isPositive()) r else -r;
493 }515 }
494 }516 }
495517
496 // if a == 0518 // if a == 0
497 pub fn eqZero(a: Int) bool {519 pub fn eqZero(a: Int) bool {
498 return a.len == 1 and a.limbs[0] == 0;520 return a.len() == 1 and a.limbs[0] == 0;
499 }521 }
500522
501 // if |a| == |b|523 // if |a| == |b|
...@@ -525,16 +547,15 @@ pub const Int = struct {...@@ -525,16 +547,15 @@ pub const Int = struct {
525 }547 }
526548
527 // Handle zero549 // Handle zero
528 r.len = if (j != 0) j else 1;550 r.setLen(if (j != 0) j else 1);
529 }551 }
530552
531 // Cannot be used as a result argument to any function.553 // Cannot be used as a result argument to any function.
532 fn readOnlyPositive(a: Int) Int {554 fn readOnlyPositive(a: Int) Int {
533 return Int{555 return Int{
534 .allocator = null,556 .allocator = null,
535 .positive = true,557 .metadata = a.len(),
536 .limbs = a.limbs,558 .limbs = a.limbs,
537 .len = a.len,
538 };559 };
539 }560 }
540561
...@@ -549,8 +570,8 @@ pub const Int = struct {...@@ -549,8 +570,8 @@ pub const Int = struct {
549 return;570 return;
550 }571 }
551572
552 if (a.positive != b.positive) {573 if (a.isPositive() != b.isPositive()) {
553 if (a.positive) {574 if (a.isPositive()) {
554 // (a) + (-b) => a - b575 // (a) + (-b) => a - b
555 try r.sub(a, readOnlyPositive(b));576 try r.sub(a, readOnlyPositive(b));
556 } else {577 } else {
...@@ -558,17 +579,17 @@ pub const Int = struct {...@@ -558,17 +579,17 @@ pub const Int = struct {
558 try r.sub(b, readOnlyPositive(a));579 try r.sub(b, readOnlyPositive(a));
559 }580 }
560 } else {581 } else {
561 if (a.len >= b.len) {582 if (a.len() >= b.len()) {
562 try r.ensureCapacity(a.len + 1);583 try r.ensureCapacity(a.len() + 1);
563 lladd(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);584 lladd(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
564 r.normalize(a.len + 1);585 r.normalize(a.len() + 1);
565 } else {586 } else {
566 try r.ensureCapacity(b.len + 1);587 try r.ensureCapacity(b.len() + 1);
567 lladd(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);588 lladd(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
568 r.normalize(b.len + 1);589 r.normalize(b.len() + 1);
569 }590 }
570591
571 r.positive = a.positive;592 r.setSign(a.isPositive());
572 }593 }
573 }594 }
574595
...@@ -599,41 +620,41 @@ pub const Int = struct {...@@ -599,41 +620,41 @@ pub const Int = struct {
599 // r = a - b620 // r = a - b
600 pub fn sub(r: *Int, a: Int, b: Int) !void {621 pub fn sub(r: *Int, a: Int, b: Int) !void {
601 r.assertWritable();622 r.assertWritable();
602 if (a.positive != b.positive) {623 if (a.isPositive() != b.isPositive()) {
603 if (a.positive) {624 if (a.isPositive()) {
604 // (a) - (-b) => a + b625 // (a) - (-b) => a + b
605 try r.add(a, readOnlyPositive(b));626 try r.add(a, readOnlyPositive(b));
606 } else {627 } else {
607 // (-a) - (b) => -(a + b)628 // (-a) - (b) => -(a + b)
608 try r.add(readOnlyPositive(a), b);629 try r.add(readOnlyPositive(a), b);
609 r.positive = false;630 r.setSign(false);
610 }631 }
611 } else {632 } else {
612 if (a.positive) {633 if (a.isPositive()) {
613 // (a) - (b) => a - b634 // (a) - (b) => a - b
614 if (a.cmp(b) >= 0) {635 if (a.cmp(b) >= 0) {
615 try r.ensureCapacity(a.len + 1);636 try r.ensureCapacity(a.len() + 1);
616 llsub(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);637 llsub(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
617 r.normalize(a.len);638 r.normalize(a.len());
618 r.positive = true;639 r.setSign(true);
619 } else {640 } else {
620 try r.ensureCapacity(b.len + 1);641 try r.ensureCapacity(b.len() + 1);
621 llsub(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);642 llsub(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
622 r.normalize(b.len);643 r.normalize(b.len());
623 r.positive = false;644 r.setSign(false);
624 }645 }
625 } else {646 } else {
626 // (-a) - (-b) => -(a - b)647 // (-a) - (-b) => -(a - b)
627 if (a.cmp(b) < 0) {648 if (a.cmp(b) < 0) {
628 try r.ensureCapacity(a.len + 1);649 try r.ensureCapacity(a.len() + 1);
629 llsub(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);650 llsub(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
630 r.normalize(a.len);651 r.normalize(a.len());
631 r.positive = false;652 r.setSign(false);
632 } else {653 } else {
633 try r.ensureCapacity(b.len + 1);654 try r.ensureCapacity(b.len() + 1);
634 llsub(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);655 llsub(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
635 r.normalize(b.len);656 r.normalize(b.len());
636 r.positive = true;657 r.setSign(true);
637 }658 }
638 }659 }
639 }660 }
...@@ -674,7 +695,7 @@ pub const Int = struct {...@@ -674,7 +695,7 @@ pub const Int = struct {
674695
675 var sr: Int = undefined;696 var sr: Int = undefined;
676 if (aliased) {697 if (aliased) {
677 sr = try Int.initCapacity(rma.allocator.?, a.len + b.len);698 sr = try Int.initCapacity(rma.allocator.?, a.len() + b.len());
678 r = &sr;699 r = &sr;
679 aliased = true;700 aliased = true;
680 }701 }
...@@ -683,16 +704,16 @@ pub const Int = struct {...@@ -683,16 +704,16 @@ pub const Int = struct {
683 r.deinit();704 r.deinit();
684 };705 };
685706
686 try r.ensureCapacity(a.len + b.len);707 try r.ensureCapacity(a.len() + b.len());
687708
688 if (a.len >= b.len) {709 if (a.len() >= b.len()) {
689 llmul(r.limbs, a.limbs[0..a.len], b.limbs[0..b.len]);710 llmul(r.limbs, a.limbs[0..a.len()], b.limbs[0..b.len()]);
690 } else {711 } else {
691 llmul(r.limbs, b.limbs[0..b.len], a.limbs[0..a.len]);712 llmul(r.limbs, b.limbs[0..b.len()], a.limbs[0..a.len()]);
692 }713 }
693714
694 r.positive = a.positive == b.positive;715 r.normalize(a.len() + b.len());
695 r.normalize(a.len + b.len);716 r.setSign(a.isPositive() == b.isPositive());
696 }717 }
697718
698 // a + b * c + *carry, sets carry to the overflow bits719 // a + b * c + *carry, sets carry to the overflow bits
...@@ -742,17 +763,17 @@ pub const Int = struct {...@@ -742,17 +763,17 @@ pub const Int = struct {
742 try div(q, r, a, b);763 try div(q, r, a, b);
743764
744 // Trunc -> Floor.765 // Trunc -> Floor.
745 if (!q.positive) {766 if (!q.isPositive()) {
746 const one = Int.initFixed(([]Limb{1})[0..]);767 const one = Int.initFixed(([]Limb{1})[0..]);
747 try q.sub(q.*, one);768 try q.sub(q.*, one);
748 try r.add(q.*, one);769 try r.add(q.*, one);
749 }770 }
750 r.positive = b.positive;771 r.setSign(b.isPositive());
751 }772 }
752773
753 pub fn divTrunc(q: *Int, r: *Int, a: Int, b: Int) !void {774 pub fn divTrunc(q: *Int, r: *Int, a: Int, b: Int) !void {
754 try div(q, r, a, b);775 try div(q, r, a, b);
755 r.positive = a.positive;776 r.setSign(a.isPositive());
756 }777 }
757778
758 // Truncates by default.779 // Truncates by default.
...@@ -770,10 +791,9 @@ pub const Int = struct {...@@ -770,10 +791,9 @@ pub const Int = struct {
770 if (a.cmpAbs(b) < 0) {791 if (a.cmpAbs(b) < 0) {
771 // quo may alias a so handle rem first792 // quo may alias a so handle rem first
772 try rem.copy(a);793 try rem.copy(a);
773 rem.positive = a.positive == b.positive;794 rem.setSign(a.isPositive() == b.isPositive());
774795
775 quo.positive = true;796 quo.metadata = 1;
776 quo.len = 1;
777 quo.limbs[0] = 0;797 quo.limbs[0] = 0;
778 return;798 return;
779 }799 }
...@@ -782,14 +802,14 @@ pub const Int = struct {...@@ -782,14 +802,14 @@ pub const Int = struct {
782 // algorithms.802 // algorithms.
783 const a_zero_limb_count = blk: {803 const a_zero_limb_count = blk: {
784 var i: usize = 0;804 var i: usize = 0;
785 while (i < a.len) : (i += 1) {805 while (i < a.len()) : (i += 1) {
786 if (a.limbs[i] != 0) break;806 if (a.limbs[i] != 0) break;
787 }807 }
788 break :blk i;808 break :blk i;
789 };809 };
790 const b_zero_limb_count = blk: {810 const b_zero_limb_count = blk: {
791 var i: usize = 0;811 var i: usize = 0;
792 while (i < b.len) : (i += 1) {812 while (i < b.len()) : (i += 1) {
793 if (b.limbs[i] != 0) break;813 if (b.limbs[i] != 0) break;
794 }814 }
795 break :blk i;815 break :blk i;
...@@ -797,39 +817,37 @@ pub const Int = struct {...@@ -797,39 +817,37 @@ pub const Int = struct {
797817
798 const ab_zero_limb_count = std.math.min(a_zero_limb_count, b_zero_limb_count);818 const ab_zero_limb_count = std.math.min(a_zero_limb_count, b_zero_limb_count);
799819
800 if (b.len - ab_zero_limb_count == 1) {820 if (b.len() - ab_zero_limb_count == 1) {
801 try quo.ensureCapacity(a.len);821 try quo.ensureCapacity(a.len());
802822
803 lldiv1(quo.limbs[0..], &rem.limbs[0], a.limbs[ab_zero_limb_count..a.len], b.limbs[b.len - 1]);823 lldiv1(quo.limbs[0..], &rem.limbs[0], a.limbs[ab_zero_limb_count..a.len()], b.limbs[b.len() - 1]);
804 quo.normalize(a.len - ab_zero_limb_count);824 quo.normalize(a.len() - ab_zero_limb_count);
805 quo.positive = a.positive == b.positive;825 quo.setSign(a.isPositive() == b.isPositive());
806826
807 rem.len = 1;827 rem.metadata = 1;
808 rem.positive = true;
809 } else {828 } else {
810 // x and y are modified during division829 // x and y are modified during division
811 var x = try Int.initCapacity(quo.allocator.?, a.len);830 var x = try Int.initCapacity(quo.allocator.?, a.len());
812 defer x.deinit();831 defer x.deinit();
813 try x.copy(a);832 try x.copy(a);
814833
815 var y = try Int.initCapacity(quo.allocator.?, b.len);834 var y = try Int.initCapacity(quo.allocator.?, b.len());
816 defer y.deinit();835 defer y.deinit();
817 try y.copy(b);836 try y.copy(b);
818837
819 // x may grow one limb during normalization838 // x may grow one limb during normalization
820 try quo.ensureCapacity(a.len + y.len);839 try quo.ensureCapacity(a.len() + y.len());
821840
822 // Shrink x, y such that the trailing zero limbs shared between are removed.841 // Shrink x, y such that the trailing zero limbs shared between are removed.
823 if (ab_zero_limb_count != 0) {842 if (ab_zero_limb_count != 0) {
824 std.mem.copy(Limb, x.limbs[0..], x.limbs[ab_zero_limb_count..]);843 std.mem.copy(Limb, x.limbs[0..], x.limbs[ab_zero_limb_count..]);
825 std.mem.copy(Limb, y.limbs[0..], y.limbs[ab_zero_limb_count..]);844 std.mem.copy(Limb, y.limbs[0..], y.limbs[ab_zero_limb_count..]);
826 x.len -= ab_zero_limb_count;845 x.metadata -= ab_zero_limb_count;
827 y.len -= ab_zero_limb_count;846 y.metadata -= ab_zero_limb_count;
828 }847 }
829848
830 try divN(quo.allocator.?, quo, rem, &x, &y);849 try divN(quo.allocator.?, quo, rem, &x, &y);
831850 quo.setSign(a.isPositive() == b.isPositive());
832 quo.positive = a.positive == b.positive;
833 }851 }
834852
835 if (ab_zero_limb_count != 0) {853 if (ab_zero_limb_count != 0) {
...@@ -868,28 +886,28 @@ pub const Int = struct {...@@ -868,28 +886,28 @@ pub const Int = struct {
868 //886 //
869 // x = qy + r where 0 <= r < y887 // x = qy + r where 0 <= r < y
870 fn divN(allocator: *Allocator, q: *Int, r: *Int, x: *Int, y: *Int) !void {888 fn divN(allocator: *Allocator, q: *Int, r: *Int, x: *Int, y: *Int) !void {
871 debug.assert(y.len >= 2);889 debug.assert(y.len() >= 2);
872 debug.assert(x.len >= y.len);890 debug.assert(x.len() >= y.len());
873 debug.assert(q.limbs.len >= x.len + y.len - 1);891 debug.assert(q.limbs.len >= x.len() + y.len() - 1);
874 debug.assert(default_capacity >= 3); // see 3.2892 debug.assert(default_capacity >= 3); // see 3.2
875893
876 var tmp = try Int.init(allocator);894 var tmp = try Int.init(allocator);
877 defer tmp.deinit();895 defer tmp.deinit();
878896
879 // Normalize so y > Limb.bit_count / 2 (i.e. leading bit is set) and even897 // Normalize so y > Limb.bit_count / 2 (i.e. leading bit is set) and even
880 var norm_shift = @clz(y.limbs[y.len - 1]);898 var norm_shift = @clz(y.limbs[y.len() - 1]);
881 if (norm_shift == 0 and y.isOdd()) {899 if (norm_shift == 0 and y.isOdd()) {
882 norm_shift = Limb.bit_count;900 norm_shift = Limb.bit_count;
883 }901 }
884 try x.shiftLeft(x.*, norm_shift);902 try x.shiftLeft(x.*, norm_shift);
885 try y.shiftLeft(y.*, norm_shift);903 try y.shiftLeft(y.*, norm_shift);
886904
887 const n = x.len - 1;905 const n = x.len() - 1;
888 const t = y.len - 1;906 const t = y.len() - 1;
889907
890 // 1.908 // 1.
891 q.len = n - t + 1;909 q.metadata = n - t + 1;
892 mem.set(Limb, q.limbs[0..q.len], 0);910 mem.set(Limb, q.limbs[0..q.len()], 0);
893911
894 // 2.912 // 2.
895 try tmp.shiftLeft(y.*, Limb.bit_count * (n - t));913 try tmp.shiftLeft(y.*, Limb.bit_count * (n - t));
...@@ -937,7 +955,7 @@ pub const Int = struct {...@@ -937,7 +955,7 @@ pub const Int = struct {
937 try tmp.shiftLeft(tmp, Limb.bit_count * (i - t - 1));955 try tmp.shiftLeft(tmp, Limb.bit_count * (i - t - 1));
938 try x.sub(x.*, tmp);956 try x.sub(x.*, tmp);
939957
940 if (!x.positive) {958 if (!x.isPositive()) {
941 try tmp.shiftLeft(y.*, Limb.bit_count * (i - t - 1));959 try tmp.shiftLeft(y.*, Limb.bit_count * (i - t - 1));
942 try x.add(x.*, tmp);960 try x.add(x.*, tmp);
943 q.limbs[i - t - 1] -= 1;961 q.limbs[i - t - 1] -= 1;
...@@ -945,20 +963,20 @@ pub const Int = struct {...@@ -945,20 +963,20 @@ pub const Int = struct {
945 }963 }
946964
947 // Denormalize965 // Denormalize
948 q.normalize(q.len);966 q.normalize(q.len());
949967
950 try r.shiftRight(x.*, norm_shift);968 try r.shiftRight(x.*, norm_shift);
951 r.normalize(r.len);969 r.normalize(r.len());
952 }970 }
953971
954 // r = a << shift, in other words, r = a * 2^shift972 // r = a << shift, in other words, r = a * 2^shift
955 pub fn shiftLeft(r: *Int, a: Int, shift: usize) !void {973 pub fn shiftLeft(r: *Int, a: Int, shift: usize) !void {
956 r.assertWritable();974 r.assertWritable();
957975
958 try r.ensureCapacity(a.len + (shift / Limb.bit_count) + 1);976 try r.ensureCapacity(a.len() + (shift / Limb.bit_count) + 1);
959 llshl(r.limbs[0..], a.limbs[0..a.len], shift);977 llshl(r.limbs[0..], a.limbs[0..a.len()], shift);
960 r.normalize(a.len + (shift / Limb.bit_count) + 1);978 r.normalize(a.len() + (shift / Limb.bit_count) + 1);
961 r.positive = a.positive;979 r.setSign(a.isPositive());
962 }980 }
963981
964 fn llshl(r: []Limb, a: []const Limb, shift: usize) void {982 fn llshl(r: []Limb, a: []const Limb, shift: usize) void {
...@@ -988,17 +1006,16 @@ pub const Int = struct {...@@ -988,17 +1006,16 @@ pub const Int = struct {
988 pub fn shiftRight(r: *Int, a: Int, shift: usize) !void {1006 pub fn shiftRight(r: *Int, a: Int, shift: usize) !void {
989 r.assertWritable();1007 r.assertWritable();
9901008
991 if (a.len <= shift / Limb.bit_count) {1009 if (a.len() <= shift / Limb.bit_count) {
992 r.len = 1;1010 r.metadata = 1;
993 r.limbs[0] = 0;1011 r.limbs[0] = 0;
994 r.positive = true;
995 return;1012 return;
996 }1013 }
9971014
998 try r.ensureCapacity(a.len - (shift / Limb.bit_count));1015 try r.ensureCapacity(a.len() - (shift / Limb.bit_count));
999 const r_len = llshr(r.limbs[0..], a.limbs[0..a.len], shift);1016 const r_len = llshr(r.limbs[0..], a.limbs[0..a.len()], shift);
1000 r.len = a.len - (shift / Limb.bit_count);1017 r.metadata = a.len() - (shift / Limb.bit_count);
1001 r.positive = a.positive;1018 r.setSign(a.isPositive());
1002 }1019 }
10031020
1004 fn llshr(r: []Limb, a: []const Limb, shift: usize) void {1021 fn llshr(r: []Limb, a: []const Limb, shift: usize) void {
...@@ -1025,14 +1042,14 @@ pub const Int = struct {...@@ -1025,14 +1042,14 @@ pub const Int = struct {
1025 pub fn bitOr(r: *Int, a: Int, b: Int) !void {1042 pub fn bitOr(r: *Int, a: Int, b: Int) !void {
1026 r.assertWritable();1043 r.assertWritable();
10271044
1028 if (a.len > b.len) {1045 if (a.len() > b.len()) {
1029 try r.ensureCapacity(a.len);1046 try r.ensureCapacity(a.len());
1030 llor(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);1047 llor(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
1031 r.len = a.len;1048 r.setLen(a.len());
1032 } else {1049 } else {
1033 try r.ensureCapacity(b.len);1050 try r.ensureCapacity(b.len());
1034 llor(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);1051 llor(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
1035 r.len = b.len;1052 r.setLen(b.len());
1036 }1053 }
1037 }1054 }
10381055
...@@ -1054,14 +1071,14 @@ pub const Int = struct {...@@ -1054,14 +1071,14 @@ pub const Int = struct {
1054 pub fn bitAnd(r: *Int, a: Int, b: Int) !void {1071 pub fn bitAnd(r: *Int, a: Int, b: Int) !void {
1055 r.assertWritable();1072 r.assertWritable();
10561073
1057 if (a.len > b.len) {1074 if (a.len() > b.len()) {
1058 try r.ensureCapacity(b.len);1075 try r.ensureCapacity(b.len());
1059 lland(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);1076 lland(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
1060 r.normalize(b.len);1077 r.normalize(b.len());
1061 } else {1078 } else {
1062 try r.ensureCapacity(a.len);1079 try r.ensureCapacity(a.len());
1063 lland(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);1080 lland(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
1064 r.normalize(a.len);1081 r.normalize(a.len());
1065 }1082 }
1066 }1083 }
10671084
...@@ -1080,14 +1097,14 @@ pub const Int = struct {...@@ -1080,14 +1097,14 @@ pub const Int = struct {
1080 pub fn bitXor(r: *Int, a: Int, b: Int) !void {1097 pub fn bitXor(r: *Int, a: Int, b: Int) !void {
1081 r.assertWritable();1098 r.assertWritable();
10821099
1083 if (a.len > b.len) {1100 if (a.len() > b.len()) {
1084 try r.ensureCapacity(a.len);1101 try r.ensureCapacity(a.len());
1085 llxor(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);1102 llxor(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
1086 r.normalize(a.len);1103 r.normalize(a.len());
1087 } else {1104 } else {
1088 try r.ensureCapacity(b.len);1105 try r.ensureCapacity(b.len());
1089 llxor(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);1106 llxor(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
1090 r.normalize(b.len);1107 r.normalize(b.len());
1091 }1108 }
1092 }1109 }
10931110
...@@ -1134,14 +1151,14 @@ test "big.int comptime_int set negative" {...@@ -1134,14 +1151,14 @@ test "big.int comptime_int set negative" {
1134 var a = try Int.initSet(al, -10);1151 var a = try Int.initSet(al, -10);
11351152
1136 testing.expect(a.limbs[0] == 10);1153 testing.expect(a.limbs[0] == 10);
1137 testing.expect(a.positive == false);1154 testing.expect(a.isPositive() == false);
1138}1155}
11391156
1140test "big.int int set unaligned small" {1157test "big.int int set unaligned small" {
1141 var a = try Int.initSet(al, u7(45));1158 var a = try Int.initSet(al, u7(45));
11421159
1143 testing.expect(a.limbs[0] == 45);1160 testing.expect(a.limbs[0] == 45);
1144 testing.expect(a.positive == true);1161 testing.expect(a.isPositive() == true);
1145}1162}
11461163
1147test "big.int comptime_int to" {1164test "big.int comptime_int to" {
...@@ -1171,22 +1188,22 @@ test "big.int normalize" {...@@ -1171,22 +1188,22 @@ test "big.int normalize" {
1171 a.limbs[2] = 3;1188 a.limbs[2] = 3;
1172 a.limbs[3] = 0;1189 a.limbs[3] = 0;
1173 a.normalize(4);1190 a.normalize(4);
1174 testing.expect(a.len == 3);1191 testing.expect(a.len() == 3);
11751192
1176 a.limbs[0] = 1;1193 a.limbs[0] = 1;
1177 a.limbs[1] = 2;1194 a.limbs[1] = 2;
1178 a.limbs[2] = 3;1195 a.limbs[2] = 3;
1179 a.normalize(3);1196 a.normalize(3);
1180 testing.expect(a.len == 3);1197 testing.expect(a.len() == 3);
11811198
1182 a.limbs[0] = 0;1199 a.limbs[0] = 0;
1183 a.limbs[1] = 0;1200 a.limbs[1] = 0;
1184 a.normalize(2);1201 a.normalize(2);
1185 testing.expect(a.len == 1);1202 testing.expect(a.len() == 1);
11861203
1187 a.limbs[0] = 0;1204 a.limbs[0] = 0;
1188 a.normalize(1);1205 a.normalize(1);
1189 testing.expect(a.len == 1);1206 testing.expect(a.len() == 1);
1190}1207}
11911208
1192test "big.int normalize multi" {1209test "big.int normalize multi" {
...@@ -1198,24 +1215,24 @@ test "big.int normalize multi" {...@@ -1198,24 +1215,24 @@ test "big.int normalize multi" {
1198 a.limbs[2] = 0;1215 a.limbs[2] = 0;
1199 a.limbs[3] = 0;1216 a.limbs[3] = 0;
1200 a.normalize(4);1217 a.normalize(4);
1201 testing.expect(a.len == 2);1218 testing.expect(a.len() == 2);
12021219
1203 a.limbs[0] = 1;1220 a.limbs[0] = 1;
1204 a.limbs[1] = 2;1221 a.limbs[1] = 2;
1205 a.limbs[2] = 3;1222 a.limbs[2] = 3;
1206 a.normalize(3);1223 a.normalize(3);
1207 testing.expect(a.len == 3);1224 testing.expect(a.len() == 3);
12081225
1209 a.limbs[0] = 0;1226 a.limbs[0] = 0;
1210 a.limbs[1] = 0;1227 a.limbs[1] = 0;
1211 a.limbs[2] = 0;1228 a.limbs[2] = 0;
1212 a.limbs[3] = 0;1229 a.limbs[3] = 0;
1213 a.normalize(4);1230 a.normalize(4);
1214 testing.expect(a.len == 1);1231 testing.expect(a.len() == 1);
12151232
1216 a.limbs[0] = 0;1233 a.limbs[0] = 0;
1217 a.normalize(1);1234 a.normalize(1);
1218 testing.expect(a.len == 1);1235 testing.expect(a.len() == 1);
1219}1236}
12201237
1221test "big.int parity" {1238test "big.int parity" {
...@@ -1250,7 +1267,7 @@ test "big.int bitcount + sizeInBase" {...@@ -1250,7 +1267,7 @@ test "big.int bitcount + sizeInBase" {
1250 try a.shiftLeft(a, 5000);1267 try a.shiftLeft(a, 5000);
1251 testing.expect(a.bitCountAbs() == 5032);1268 testing.expect(a.bitCountAbs() == 5032);
1252 testing.expect(a.sizeInBase(2) >= 5032);1269 testing.expect(a.sizeInBase(2) >= 5032);
1253 a.positive = false;1270 a.setSign(false);
12541271
1255 testing.expect(a.bitCountAbs() == 5032);1272 testing.expect(a.bitCountAbs() == 5032);
1256 testing.expect(a.sizeInBase(2) >= 5033);1273 testing.expect(a.sizeInBase(2) >= 5033);
std/math/big/rational.zig+20-19
...@@ -15,7 +15,7 @@ const DoubleLimb = bn.DoubleLimb;...@@ -15,7 +15,7 @@ const DoubleLimb = bn.DoubleLimb;
15const Int = bn.Int;15const Int = bn.Int;
1616
17pub const Rational = struct {17pub const Rational = struct {
18 // sign of Rational is a.positive, b.positive is ignored18 // Sign of Rational is sign of p. Sign of q is ignored
19 p: Int,19 p: Int,
20 q: Int,20 q: Int,
2121
...@@ -152,7 +152,7 @@ pub const Rational = struct {...@@ -152,7 +152,7 @@ pub const Rational = struct {
152 }152 }
153153
154 try self.p.set(mantissa);154 try self.p.set(mantissa);
155 self.p.positive = f >= 0;155 self.p.setSign(f >= 0);
156156
157 try self.q.set(1);157 try self.q.set(1);
158 if (shift >= 0) {158 if (shift >= 0) {
...@@ -211,7 +211,7 @@ pub const Rational = struct {...@@ -211,7 +211,7 @@ pub const Rational = struct {
211 try Int.divTrunc(&q, &r, a2, b2);211 try Int.divTrunc(&q, &r, a2, b2);
212212
213 var mantissa = extractLowBits(q, BitReprType);213 var mantissa = extractLowBits(q, BitReprType);
214 var have_rem = r.len > 0;214 var have_rem = r.len() > 0;
215215
216 // 3. q didn't fit in msize2 bits, redo division b2 << 1216 // 3. q didn't fit in msize2 bits, redo division b2 << 1
217 if (mantissa >> msize2 == 1) {217 if (mantissa >> msize2 == 1) {
...@@ -256,15 +256,16 @@ pub const Rational = struct {...@@ -256,15 +256,16 @@ pub const Rational = struct {
256 exact = false;256 exact = false;
257 }257 }
258258
259 return if (self.p.positive) f else -f;259 return if (self.p.isPositive()) f else -f;
260 }260 }
261261
262 pub fn setRatio(self: *Rational, p: var, q: var) !void {262 pub fn setRatio(self: *Rational, p: var, q: var) !void {
263 try self.p.set(p);263 try self.p.set(p);
264 try self.q.set(q);264 try self.q.set(q);
265265
266 self.p.positive = (@boolToInt(self.p.positive) ^ @boolToInt(self.q.positive)) == 0;266 self.p.setSign(@boolToInt(self.p.isPositive()) ^ @boolToInt(self.q.isPositive()) == 0);
267 self.q.positive = true;267 self.q.setSign(true);
268
268 try self.reduce();269 try self.reduce();
269270
270 if (self.q.eqZero()) {271 if (self.q.eqZero()) {
...@@ -281,8 +282,9 @@ pub const Rational = struct {...@@ -281,8 +282,9 @@ pub const Rational = struct {
281 try self.p.copy(a);282 try self.p.copy(a);
282 try self.q.copy(b);283 try self.q.copy(b);
283284
284 self.p.positive = (@boolToInt(self.p.positive) ^ @boolToInt(self.q.positive)) == 0;285 self.p.setSign(@boolToInt(self.p.isPositive()) ^ @boolToInt(self.q.isPositive()) == 0);
285 self.q.positive = true;286 self.q.setSign(true);
287
286 try self.reduce();288 try self.reduce();
287 }289 }
288290
...@@ -403,11 +405,10 @@ pub const Rational = struct {...@@ -403,11 +405,10 @@ pub const Rational = struct {
403 var a = try Int.init(r.p.allocator.?);405 var a = try Int.init(r.p.allocator.?);
404 defer a.deinit();406 defer a.deinit();
405407
406 const sign = r.p.positive;408 const sign = r.p.isPositive();
407
408 r.p.abs();409 r.p.abs();
409 try gcd(&a, r.p, r.q);410 try gcd(&a, r.p, r.q);
410 r.p.positive = sign;411 r.p.setSign(sign);
411412
412 const one = Int.initFixed(([]Limb{1})[0..]);413 const one = Int.initFixed(([]Limb{1})[0..]);
413 if (a.cmp(one) != 0) {414 if (a.cmp(one) != 0) {
...@@ -431,7 +432,7 @@ fn gcd(rma: *Int, x: Int, y: Int) !void {...@@ -431,7 +432,7 @@ fn gcd(rma: *Int, x: Int, y: Int) !void {
431432
432 var sr: Int = undefined;433 var sr: Int = undefined;
433 if (aliased) {434 if (aliased) {
434 sr = try Int.initCapacity(rma.allocator.?, math.max(x.len, y.len));435 sr = try Int.initCapacity(rma.allocator.?, math.max(x.len(), y.len()));
435 r = &sr;436 r = &sr;
436 aliased = true;437 aliased = true;
437 }438 }
...@@ -452,7 +453,7 @@ fn FixedIntFromSignedDoubleLimb(A: SignedDoubleLimb, storage: []Limb) Int {...@@ -452,7 +453,7 @@ fn FixedIntFromSignedDoubleLimb(A: SignedDoubleLimb, storage: []Limb) Int {
452 storage[0] = @truncate(Limb, Au);453 storage[0] = @truncate(Limb, Au);
453 storage[1] = @truncate(Limb, Au >> Limb.bit_count);454 storage[1] = @truncate(Limb, Au >> Limb.bit_count);
454 var Ap = Int.initFixed(storage[0..2]);455 var Ap = Int.initFixed(storage[0..2]);
455 Ap.positive = A_is_positive;456 Ap.setSign(A_is_positive);
456 return Ap;457 return Ap;
457}458}
458459
...@@ -472,12 +473,12 @@ fn gcdLehmer(r: *Int, xa: Int, ya: Int) !void {...@@ -472,12 +473,12 @@ fn gcdLehmer(r: *Int, xa: Int, ya: Int) !void {
472 var T = try Int.init(r.allocator.?);473 var T = try Int.init(r.allocator.?);
473 defer T.deinit();474 defer T.deinit();
474475
475 while (y.len > 1) {476 while (y.len() > 1) {
476 debug.assert(x.positive and y.positive);477 debug.assert(x.isPositive() and y.isPositive());
477 debug.assert(x.len >= y.len);478 debug.assert(x.len() >= y.len());
478479
479 var xh: SignedDoubleLimb = x.limbs[x.len - 1];480 var xh: SignedDoubleLimb = x.limbs[x.len() - 1];
480 var yh: SignedDoubleLimb = if (x.len > y.len) 0 else y.limbs[x.len - 1];481 var yh: SignedDoubleLimb = if (x.len() > y.len()) 0 else y.limbs[x.len() - 1];
481482
482 var A: SignedDoubleLimb = 1;483 var A: SignedDoubleLimb = 1;
483 var B: SignedDoubleLimb = 0;484 var B: SignedDoubleLimb = 0;
...@@ -506,7 +507,7 @@ fn gcdLehmer(r: *Int, xa: Int, ya: Int) !void {...@@ -506,7 +507,7 @@ fn gcdLehmer(r: *Int, xa: Int, ya: Int) !void {
506 if (B == 0) {507 if (B == 0) {
507 // T = x % y, r is unused508 // T = x % y, r is unused
508 try Int.divTrunc(r, &T, x, y);509 try Int.divTrunc(r, &T, x, y);
509 debug.assert(T.positive);510 debug.assert(T.isPositive());
510511
511 x.swap(&y);512 x.swap(&y);
512 y.swap(&T);513 y.swap(&T);