aboutsummaryrefslogtreecommitdiff
path: root/lib/std/math.zig
diff options
context:
space:
mode:
authorMartin Wickham <spexguy070@gmail.com>2021-02-04 23:04:49 -0600
committerAndrew Kelley <andrew@ziglang.org>2021-03-01 18:52:15 -0800
commit7613e51a57d2e2d0ae7d1101d059002f12b96c43 (patch)
tree9f0af291873f4698f56339a20989c82fcc96de5f /lib/std/math.zig
parent1f861ecc95a827fc979f3371901f1ae93dd2c283 (diff)
downloadzig-7613e51a57d2e2d0ae7d1101d059002f12b96c43.tar.gz
zig-7613e51a57d2e2d0ae7d1101d059002f12b96c43.zip
Add some bit set variants
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..940284b763 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 inline fn boolMask(comptime MaskInt: type, value: bool) 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();
+}