Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use case: compose and decompose integers #526

Closed
andrewrk opened this issue Oct 3, 2017 · 3 comments
Closed

use case: compose and decompose integers #526

andrewrk opened this issue Oct 3, 2017 · 3 comments
Labels
enhancement Solving this issue will likely involve adding new logic or components to the codebase.
Milestone

Comments

@andrewrk
Copy link
Member

andrewrk commented Oct 3, 2017

Would have been useful for #375 parse and print floats

This almost works. It's blocked only by needing the @field builtin (#383) and having to work around #280.

I think it's a demonstration of a valid use case of using var and var args for arguments, although
I might change it so that composeInt takes a struct in the same way that decomposeInt does, then it wouldn't use var args.

fn composeInt(comptime signed: bool, smaller_ints: ...) -> {
    var total_bits = 0;
    for (args) |arg| {
        total_bits += @typeOf(arg).bit_count;
    }
    @IntType(signed, total_bits)
}
{
    var result: this.ReturnType = 0;

    comptime var prev_bit_count = 0;
    inline for (smaller_ints) |small_int| {
        result = (result << prev_bit_count) | small_int;
        prev_bit_count = @typeOf(small_int).bit_count;
    }

    return result;
}

fn decomposeInt(bigger_int: var, comptime ResultStruct: type) -> ResultStruct {
    const field_count = @memberCount(ResultStruct);
    if (field_count == 0)
        return ResultStruct {};

    var result: ResultStruct = undefined;
    var working_value = bigger_int;

    comptime var i = field_count - 1;
    inline while (true) {
        @field(result, i) = @truncate(@typeOf(@field(result, i)), working_value);
        if (i == 0)
            break;
        working_value >>= @typeOf(@field(result, i)).bit_count;
        i -= 1;
    }
}

test "compose and decompose integers" {
    const float = @bitCast(f32, composeInt(false, u1(true), u8(0x82), u23(0x4570a4)));
    assert(float == -12.34);

    const decomposed = decomposeInt(@bitCast(u32, float), struct {
        sign_bit: bool,
        mantissa: u8,
        significand: u23,
    });

    assert(decomposed.sign_bit);
    assert(decomposed.mantissa == 0x82);
    assert(decomposed.significand == 0x4570a4);
}

If I did it with a struct instead of var args:

const UnpackedFloat = struct {
    sign: bool,
    mantissa: u8,
    significand: u23,
};

test "compose and decompose integers" {
    const float = @bitCast(f32, composeInt(false, UnpackedFloat, UnpackedFloat {
        .sign = true,
        .mantissa = 0x82,
        .significand = 0x4570a4,
    });
    assert(float == -12.34);

    const decomposed = decomposeInt(@bitCast(u32, float), UnpackedFloat);

    assert(decomposed.sign_bit);
    assert(decomposed.mantissa == 0x82);
    assert(decomposed.significand == 0x4570a4);
}

At this point though, isn't just using a packed struct better?

const Float = packed struct {
    sign: bool,
    mantissa: u8,
    significand: u23,
};

test "using a packed struct" {
    const float = @bitCast(f32, Float {
        .sign = true,
        .mantissa = 0x82,
        .significand = 0x4570a4,
    });
    assert(float == -12.34);

    const decomposed = @bitCast(Float, f32);

    assert(decomposed.sign_bit);
    assert(decomposed.mantissa == 0x82);
    assert(decomposed.significand == 0x4570a4);
}

This is clearly the best option. I'm still going to file this issue though as a point of reference.

@andrewrk andrewrk added the enhancement Solving this issue will likely involve adding new logic or components to the codebase. label Oct 3, 2017
@andrewrk andrewrk added this to the 0.2.0 milestone Oct 3, 2017
@andrewrk andrewrk closed this as completed Oct 3, 2017
@Perelandric
Copy link

Just noticed that this issue was opened and closed at the same date and time. Was that intentional?

@andrewrk
Copy link
Member Author

Yes. Does it seem like there is something unresolved?

@Perelandric
Copy link

No, just making sure. I misunderstood.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Solving this issue will likely involve adding new logic or components to the codebase.
Projects
None yet
Development

No branches or pull requests

2 participants