Thread overview
Manipulating Bits of Any Value Type
Jan 26, 2014
Nordlöw
Jan 26, 2014
Stanislav Blinov
Jan 26, 2014
Nordlöw
Jan 26, 2014
Stanislav Blinov
Jan 26, 2014
Stanislav Blinov
January 26, 2014
Has anybody cooked up some generic functions that extend `core.bitop` bitmanipulations to work on any value type?

Something like

    bool getBit(T)(in T a, int bitnum); // bt
    T setBit(T)(in T a, int bitnum); // bts
    auto ref setBitInPlace(T)(ref T a, int bitnum);

I know this is relatively easy to implement so that's why I'm curious to why its not already Phobos.

**Update:**

Here's my first try at this:

    /** Returns: $(D bitnum):th Bit Of $(D a).
        TODO: Why is this already in Phobos?
        TODO: Make this safe for integers
     */
    bool getBit(T, I)(in T a, I bitnum) @trusted pure nothrow if (isIntegral!I) {
        enum nBits = 8*T.sizeof;
        static      if (nBits ==  8) alias I = ubyte;
        else static if (nBits == 16) alias I = ushort;
        else static if (nBits == 32) alias I = uint;
        else static if (nBits == 64) alias I = ulong;
        immutable xi = (*(cast(I*)&a));
        immutable bitMask = ((cast(I)1 << bitnum));
        /* debug dln(eltIx, ",", bitnum, ",", xi, ",", bitMask); */
        return a & bitMask ? true : false;
    }
    alias bt = getBit;

My idea to make `getBit` work on all types that have value semantics. That's why I need the cast (I think). Is there a traits to check if a type has value semantics or not?

Also is there a trait to check if a type supports a specific operation such as bitwise and `&`? I could always use `__traits(compiles, ...)` but standardization is good.

To make it even better I guess I need an explicit overload for T's that support bit manipulations in order to make this variant @safe right? In my generic solution above I need the `cast` and that's @unsafe.

See also: https://stackoverflow.com/questions/21368664/manipulating-bits-of-any-value-type
January 26, 2014
On Sunday, 26 January 2014 at 20:56:29 UTC, Nordlöw wrote:

> My idea to make `getBit` work on all types that have value semantics.

All of them? Arbitrary structs too? floating point types? Static arrays? Might I ask... why do you need this sort of thing? :)

> That's why I need the cast (I think). Is there a traits to check if a type has value semantics or not?

The closest would be std.traits.hasIndirections.

> Also is there a trait to check if a type supports a specific operation such as bitwise and `&`? I could always use `__traits(compiles, ...)` but standardization is good.

No there isn't.
January 26, 2014
On Sunday, 26 January 2014 at 23:27:58 UTC, Stanislav Blinov wrote:
> On Sunday, 26 January 2014 at 20:56:29 UTC, Nordlöw wrote:
>
>> My idea to make `getBit` work on all types that have value semantics.
>
> All of them? Arbitrary structs too? floating point types? Static arrays? Might I ask... why do you need this sort of thing? :)

For bit-parallel run-length encoding for efficient serialization of sets of std.datetime:SysTime structures (16 bytes). I'm trying to differentially pack sets of SysTimes entries more efficiently because for a given directory containing files many of these files often share the majority of their bits. Meta-code:

foreach (n; 0..SysTime.sizeof)
  RLC all n-bits for all SysTimes

It is more an interesting experiment :)

>> That's why I need the cast (I think). Is there a traits to check if a type has value semantics or not?
>
> The closest would be std.traits.hasIndirections.

Does this work recursively on containing types?

>> Also is there a trait to check if a type supports a specific operation such as bitwise and `&`? I could always use `__traits(compiles, ...)` but standardization is good.
>
> No there isn't.

Thx.
January 26, 2014
On Sunday, 26 January 2014 at 23:37:40 UTC, Nordlöw wrote:

>> Might I ask... why do you need this sort of thing? :)
>
> For bit-parallel run-length encoding for efficient serialization of sets of std.datetime:SysTime structures (16 bytes).

SysTime's representation consists of a long and Rebindable!(immutable(TimeZone)). The latter is a struct containing a reference.

>> The closest would be std.traits.hasIndirections.
>
> Does this work recursively on containing types?

AFAIK no, it just checks immediate fields (if any).
January 26, 2014
On Sunday, 26 January 2014 at 23:54:02 UTC, Stanislav Blinov wrote:
> On Sunday, 26 January 2014 at 23:37:40 UTC, Nordlöw wrote:

>>> The closest would be std.traits.hasIndirections.
>>
>> Does this work recursively on containing types?
>
> AFAIK no, it just checks immediate fields (if any).

OTOH, it seems it does :)