summaryrefslogtreecommitdiff
path: root/exercises/115_packed2.zig
blob: 2a772d7dd038d3d418c0617cb6b680142276b2ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//
// We've already learned about switch statements in exercises 030, 031 and 111.
// They also work with packed containers:

const S = packed struct(u2) {
    a: bool,
    b: i1,
};

// Try to make it compile without adding an `else` prong!

comptime {
    const s: S = .{ .a = true, .b = -1 };
    switch (s) {
        .{ .a = true, .b = -1 } => {}, // ok!
        .{ .a = true, .b = ??? },
        .{ .a = ???, .b = 0 },
        .{ .a = ???, .b = ??? },
        => @compileError("We don't want to end up here!"),
    }
}

// As we can see, switching on packed structs is pretty straightforward.
// When switching on packed unions however, we'll realize that a packed
// union never keeps track of its active tag, not even in debug mode! This
// means that packed unions compare solely by their bit pattern (again, just
// like integers).

const U = packed union(u2) {
    a: u2,
    b: i2,
};

// Find and remove the duplicate case!

comptime {
    const u: U = .{ .a = 3 };
    switch (u) {
        .{ .a = 3 } => {}, // ok!
        .{ .a = 2 },
        .{ .b = 1 },
        .{ .b = -1 },
        .{ .a = 0 },
        => @compileError("We don't want to end up here!"),
    }
}

// Since packed unions don't have the concept of an active tag, it's always legal
// to access any of their fields. This can be useful to view the same data from
// different perspectives seamlessly.
//
// Try to make the float below negative:

// IEEE 754 binary16 floating-point format
const Float = packed union(u16) {
    value: f16,
    bits: packed struct(u16) {
        significand: u10,
        exponent: u5,
        sign: u1,
    },
};

pub fn main() void {
    // Reminder: if the sign bit of a float is set, the number is negative!

    var number: Float = .{ .value = 2.34 };
    number.bits.??? = ???;
    if (number.value != -2.34) {
        std.debug.print("Make it negative!\n", .{});
    }
}

// This concludes our introduction to packed containers. The next time you need
// control over individual bits, keep them in mind as a potent alternative!
//

const std = @import("std");