aboutsummaryrefslogtreecommitdiff
path: root/lib/std/math.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-03-04 18:23:11 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-03-04 18:23:11 -0700
commitbccef441963434b452a623abbb9315fd92c1e255 (patch)
tree4c0ea89b8fa895b3d34749ec089e45438d79466b /lib/std/math.zig
parent0c06a1885fad9a9bb85342632a0b7c8a3a0733e9 (diff)
parent041212a41cfaf029dc3eb9740467b721c76f406c (diff)
downloadzig-bccef441963434b452a623abbb9315fd92c1e255.tar.gz
zig-bccef441963434b452a623abbb9315fd92c1e255.zip
Merge remote-tracking branch 'origin/master' into llvm12
Syncing with master branch because I want to re-run update_clang_options.zig in the llvm12 branch.
Diffstat (limited to 'lib/std/math.zig')
-rw-r--r--lib/std/math.zig56
1 files changed, 56 insertions, 0 deletions
diff --git a/lib/std/math.zig b/lib/std/math.zig
index 6e7c5c0915..d71cafe5ef 100644
--- a/lib/std/math.zig
+++ b/lib/std/math.zig
@@ -1330,3 +1330,59 @@ test "math.comptime" {
comptime const v = sin(@as(f32, 1)) + ln(@as(f32, 5));
testing.expect(v == sin(@as(f32, 1)) + ln(@as(f32, 5)));
}
+
+/// Returns a mask of all ones if value is true,
+/// and a mask of all zeroes if value is false.
+/// Compiles to one instruction for register sized integers.
+pub fn boolMask(comptime MaskInt: type, value: bool) callconv(.Inline) MaskInt {
+ if (@typeInfo(MaskInt) != .Int)
+ @compileError("boolMask requires an integer mask type.");
+
+ if (MaskInt == u0 or MaskInt == i0)
+ @compileError("boolMask cannot convert to u0 or i0, they are too small.");
+
+ // The u1 and i1 cases tend to overflow,
+ // so we special case them here.
+ if (MaskInt == u1) return @boolToInt(value);
+ if (MaskInt == i1) {
+ // The @as here is a workaround for #7950
+ return @bitCast(i1, @as(u1, @boolToInt(value)));
+ }
+
+ // At comptime, -% is disallowed on unsigned values.
+ // So we need to jump through some hoops in that case.
+ // This is a workaround for #7951
+ if (@typeInfo(@TypeOf(.{value})).Struct.fields[0].is_comptime) {
+ // Since it's comptime, we don't need this to generate nice code.
+ // We can just do a branch here.
+ return if (value) ~@as(MaskInt, 0) else 0;
+ }
+
+ return -%@intCast(MaskInt, @boolToInt(value));
+}
+
+test "boolMask" {
+ const runTest = struct {
+ fn runTest() void {
+ testing.expectEqual(@as(u1, 0), boolMask(u1, false));
+ testing.expectEqual(@as(u1, 1), boolMask(u1, true));
+
+ testing.expectEqual(@as(i1, 0), boolMask(i1, false));
+ testing.expectEqual(@as(i1, -1), boolMask(i1, true));
+
+ testing.expectEqual(@as(u13, 0), boolMask(u13, false));
+ testing.expectEqual(@as(u13, 0x1FFF), boolMask(u13, true));
+
+ testing.expectEqual(@as(i13, 0), boolMask(i13, false));
+ testing.expectEqual(@as(i13, -1), boolMask(i13, true));
+
+ testing.expectEqual(@as(u32, 0), boolMask(u32, false));
+ testing.expectEqual(@as(u32, 0xFFFF_FFFF), boolMask(u32, true));
+
+ testing.expectEqual(@as(i32, 0), boolMask(i32, false));
+ testing.expectEqual(@as(i32, -1), boolMask(i32, true));
+ }
+ }.runTest;
+ runTest();
+ comptime runTest();
+}