diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-10-14 21:17:30 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-10-14 21:17:30 -0700 |
| commit | 55eea3b045c86c78eb8d9cc862122d260352a631 (patch) | |
| tree | a8e234fa3a68c1c62233f047b2b1647be2e091dd /src/value.zig | |
| parent | 8b882747813878a40b63572636a6e86a59a8581e (diff) | |
| download | zig-55eea3b045c86c78eb8d9cc862122d260352a631.tar.gz zig-55eea3b045c86c78eb8d9cc862122d260352a631.zip | |
stage2: implement `@minimum` and `@maximum`, including vectors
* std.os: take advantage of `@minimum`. It's probably time to
deprecate `std.min` and `std.max`.
* New AIR instructions: min and max
* Introduce SIMD vector support to stage2
* Add `@Type` support for vectors
* Sema: add `checkSimdBinOp` which can be re-used for other arithmatic
operators that want to support vectors.
* Implement coercion from vectors to arrays.
- In backends this is handled with bitcast for vector to array,
however maybe we want to reduce the amount of branching by
introducing an explicit AIR instruction for it in the future.
* LLVM backend: implement lowering vector types
* Sema: Implement `slice.ptr` at comptime
* Value: improve `numberMin` and `numberMax` to support floats in
addition to integers, and make them behave properly in the presence
of NaN.
Diffstat (limited to 'src/value.zig')
| -rw-r--r-- | src/value.zig | 91 |
1 files changed, 37 insertions, 54 deletions
diff --git a/src/value.zig b/src/value.zig index f5477baf21..704e667ac0 100644 --- a/src/value.zig +++ b/src/value.zig @@ -1626,6 +1626,14 @@ pub const Value = extern union { }; } + pub fn slicePtr(val: Value) Value { + return switch (val.tag()) { + .slice => val.castTag(.slice).?.data.ptr, + .decl_ref, .decl_ref_mut => val, + else => unreachable, + }; + } + pub fn sliceLen(val: Value) u64 { return switch (val.tag()) { .slice => val.castTag(.slice).?.data.len.toUnsignedInt(), @@ -2042,63 +2050,27 @@ pub const Value = extern union { } /// Supports both floats and ints; handles undefined. - pub fn numberMax(lhs: Value, rhs: Value, arena: *Allocator) !Value { - if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); - - // TODO is this a performance issue? maybe we should try the operation without - // resorting to BigInt first. - var lhs_space: Value.BigIntSpace = undefined; - var rhs_space: Value.BigIntSpace = undefined; - const lhs_bigint = lhs.toBigInt(&lhs_space); - const rhs_bigint = rhs.toBigInt(&rhs_space); - const limbs = try arena.alloc( - std.math.big.Limb, - std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len), - ); - var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; - - switch (lhs_bigint.order(rhs_bigint)) { - .lt => result_bigint.copy(rhs_bigint), - .gt, .eq => result_bigint.copy(lhs_bigint), - } - - const result_limbs = result_bigint.limbs[0..result_bigint.len]; - - if (result_bigint.positive) { - return Value.Tag.int_big_positive.create(arena, result_limbs); - } else { - return Value.Tag.int_big_negative.create(arena, result_limbs); - } + pub fn numberMax(lhs: Value, rhs: Value) !Value { + if (lhs.isUndef() or rhs.isUndef()) return undef; + if (lhs.isNan()) return rhs; + if (rhs.isNan()) return lhs; + + return switch (order(lhs, rhs)) { + .lt => rhs, + .gt, .eq => lhs, + }; } /// Supports both floats and ints; handles undefined. - pub fn numberMin(lhs: Value, rhs: Value, arena: *Allocator) !Value { - if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); - - // TODO is this a performance issue? maybe we should try the operation without - // resorting to BigInt first. - var lhs_space: Value.BigIntSpace = undefined; - var rhs_space: Value.BigIntSpace = undefined; - const lhs_bigint = lhs.toBigInt(&lhs_space); - const rhs_bigint = rhs.toBigInt(&rhs_space); - const limbs = try arena.alloc( - std.math.big.Limb, - std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len), - ); - var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; - - switch (lhs_bigint.order(rhs_bigint)) { - .lt => result_bigint.copy(lhs_bigint), - .gt, .eq => result_bigint.copy(rhs_bigint), - } - - const result_limbs = result_bigint.limbs[0..result_bigint.len]; - - if (result_bigint.positive) { - return Value.Tag.int_big_positive.create(arena, result_limbs); - } else { - return Value.Tag.int_big_negative.create(arena, result_limbs); - } + pub fn numberMin(lhs: Value, rhs: Value) !Value { + if (lhs.isUndef() or rhs.isUndef()) return undef; + if (lhs.isNan()) return rhs; + if (rhs.isNan()) return lhs; + + return switch (order(lhs, rhs)) { + .lt => lhs, + .gt, .eq => rhs, + }; } /// operands must be integers; handles undefined. @@ -2327,6 +2299,17 @@ pub const Value = extern union { } } + /// Returns true if the value is a floating point type and is NaN. Returns false otherwise. + pub fn isNan(val: Value) bool { + return switch (val.tag()) { + .float_16 => std.math.isNan(val.castTag(.float_16).?.data), + .float_32 => std.math.isNan(val.castTag(.float_32).?.data), + .float_64 => std.math.isNan(val.castTag(.float_64).?.data), + .float_128 => std.math.isNan(val.castTag(.float_128).?.data), + else => false, + }; + } + pub fn floatRem(lhs: Value, rhs: Value, allocator: *Allocator) !Value { _ = lhs; _ = rhs; |
