diff options
| author | Robin Voetter <robin@voetter.nl> | 2021-12-18 04:42:13 +0100 |
|---|---|---|
| committer | Robin Voetter <robin@voetter.nl> | 2021-12-21 01:41:51 +0100 |
| commit | f3d635b6683ba4a53f82ae8087b1cf78552abac5 (patch) | |
| tree | bd038a7404df4e79170915e07528694768f44f7c /src/value.zig | |
| parent | 28bcd7dbdda7fb2c2fe80dbdb5981479a04e973a (diff) | |
| download | zig-f3d635b6683ba4a53f82ae8087b1cf78552abac5.tar.gz zig-f3d635b6683ba4a53f82ae8087b1cf78552abac5.zip | |
stage2: @addWithOverflow
Diffstat (limited to 'src/value.zig')
| -rw-r--r-- | src/value.zig | 79 |
1 files changed, 57 insertions, 22 deletions
diff --git a/src/value.zig b/src/value.zig index e3d315b6e4..085883f7af 100644 --- a/src/value.zig +++ b/src/value.zig @@ -1969,20 +1969,18 @@ pub const Value = extern union { return @divFloor(@floatToInt(std.math.big.Limb, std.math.log2(w_value)), @typeInfo(std.math.big.Limb).Int.bits) + 1; } - /// Supports both floats and ints; handles undefined. - pub fn numberAddWrap( + pub const OverflowArithmeticResult = struct { + overflowed: bool, + wrapped_result: Value, + }; + + pub fn intAddWithOverflow( lhs: Value, rhs: Value, ty: Type, arena: Allocator, target: Target, - ) !Value { - if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); - - if (ty.isAnyFloat()) { - return floatAdd(lhs, rhs, ty, arena); - } - + ) !OverflowArithmeticResult { const info = ty.intInfo(target); var lhs_space: Value.BigIntSpace = undefined; @@ -1994,8 +1992,30 @@ pub const Value = extern union { std.math.big.int.calcTwosCompLimbCount(info.bits), ); var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; - result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); - return fromBigInt(arena, result_bigint.toConst()); + const overflowed = result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); + const result = try fromBigInt(arena, result_bigint.toConst()); + return OverflowArithmeticResult{ + .overflowed = overflowed, + .wrapped_result = result, + }; + } + + /// Supports both floats and ints; handles undefined. + pub fn numberAddWrap( + lhs: Value, + rhs: Value, + ty: Type, + arena: Allocator, + target: Target, + ) !Value { + if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); + + if (ty.isAnyFloat()) { + return floatAdd(lhs, rhs, ty, arena); + } + + const overflow_result = try intAddWithOverflow(lhs, rhs, ty, arena, target); + return overflow_result.wrapped_result; } fn fromBigInt(arena: Allocator, big_int: BigIntConst) !Value { @@ -2040,20 +2060,13 @@ pub const Value = extern union { return fromBigInt(arena, result_bigint.toConst()); } - /// Supports both floats and ints; handles undefined. - pub fn numberSubWrap( + pub fn intSubWithOverflow( lhs: Value, rhs: Value, ty: Type, arena: Allocator, target: Target, - ) !Value { - if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); - - if (ty.isAnyFloat()) { - return floatSub(lhs, rhs, ty, arena); - } - + ) !OverflowArithmeticResult { const info = ty.intInfo(target); var lhs_space: Value.BigIntSpace = undefined; @@ -2065,8 +2078,30 @@ pub const Value = extern union { std.math.big.int.calcTwosCompLimbCount(info.bits), ); var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; - result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); - return fromBigInt(arena, result_bigint.toConst()); + const overflowed = result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); + const wrapped_result = try fromBigInt(arena, result_bigint.toConst()); + return OverflowArithmeticResult{ + .overflowed = overflowed, + .wrapped_result = wrapped_result, + }; + } + + /// Supports both floats and ints; handles undefined. + pub fn numberSubWrap( + lhs: Value, + rhs: Value, + ty: Type, + arena: Allocator, + target: Target, + ) !Value { + if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); + + if (ty.isAnyFloat()) { + return floatSub(lhs, rhs, ty, arena); + } + + const overflow_result = try intSubWithOverflow(lhs, rhs, ty, arena, target); + return overflow_result.wrapped_result; } /// Supports integers only; asserts neither operand is undefined. |
