January 13, 2015 Re: reinterpret array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dominikus Dittes Scherkl Attachments: | On Tue, 13 Jan 2015 20:00:56 +0000 Dominikus Dittes Scherkl via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote: p.s. i don't intend to stop you from doing what you want to do, in no way. i was just trying to show you some things that you can accidentally missed. sorry if it looks like "stop it, we already have one and nobody should need more of that!" |
January 13, 2015 Re: reinterpret array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dominikus Dittes Scherkl | On 01/13/15 21:52, Dominikus Dittes Scherkl via Digitalmars-d-learn wrote:
> On Tuesday, 13 January 2015 at 20:11:45 UTC, anonymous wrote:
>> On Tuesday, 13 January 2015 at 20:00:57 UTC, Dominikus Dittes Scherkl wrote:
>>> So if I have a function that allowes to do this:
>>>
>>> uint a;
>>> a.bit[16] = true;
>>> writeln(a); // 65536
>>>
>>> Is it also already available?
>>
>> a |= 1 << 16;
>
> Of course you can calculate it, but the
> syntax looks quite different if you want to do
> a.bit[22] = false:
>
> a &= ~(1<<16);
>
> Or if you want to test a bit:
>
> if(a.bit[16])
>
> instead of
>
> if(a & (1<<16))
>
> much more convenient for arrays:
>
> ulong[100] a;
>
> a.bit[3000] = true;
>
> doing this directly with shifts is lousy (and error prone)
>
> But ok. I see, it's not really awesome :-/
It's neat, but the real problems with it are:
1) obfuscation - it hides those trivial bit ops behind layers of
functions and operator overloads, which everyone reading the
code must then figure out;
2) safety - `a.bit` could potentially outlive `a`; D does not
handle object lifetimes, so there's no 100% safe way to prevent
such bugs.
Hence you probably don't actually want to use this.
struct Bits(E, size_t UB=1) {
E* e;
bool opIndexAssign(bool v, size_t idx) {
auto o = idx/(E.sizeof*8);
idx %= E.sizeof*8;
if (o>=UB)
assert (0);
if (v)
e[o] |= 1L<<idx;
else
e[o] &= ~(1L<<idx);
return v;
}
bool opIndex(size_t idx) {
auto o = idx/(E.sizeof*8);
idx %= E.sizeof*8;
if (o>=UB)
assert (0);
return !!(e[o] & 1L<<idx);
}
}
auto bit(E)(ref E e) @property {
static if (is(E:A[L], A, size_t L))
return Bits!(typeof(e[0]), L)(e.ptr);
else
return Bits!E(&e);
}
artur
|
January 14, 2015 Re: reinterpret array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Artur Skawina | On Tuesday, 13 January 2015 at 23:36:51 UTC, Artur Skawina via Digitalmars-d-learn wrote: > It's neat, but the real problems with it are: > 1) obfuscation - it hides those trivial bit ops behind layers of > functions and operator overloads, which everyone reading the > code must then figure out; Ok, but this is the case with any function - and this modulo stuff is easy but not so trivial that a function is not justified. > 2) safety - `a.bit` could potentially outlive `a`; D does not > handle object lifetimes, so there's no 100% safe way to prevent > such bugs. This can be addressed with the newer proposed mechanisms and a little more information-hiding (generator function): > > Hence you probably don't actually want to use this. > [...] I had something pretty close to that in mind: @property inout bit(T)(inout ref T a) pure @safe @nogc nothrow if(isUnsigned!T || (isArray!T && isUnsigned!T[0])) { struct BitArray(T) { private: enum s = std.bitop.bsr(T.sizeof)+2; enum m = (1<<s)-1; inout T* r; size_t len; public: this(inout T* p, size_t d) { r = p; len = d<<s; } bool opIndex(size_t idx) const // get bit { return (idx < len) ? (r[idx>>s]>>(idx & m))&1u : false; } static if(isMutable!T) { void opIndexAssign(bool b, size_t idx) // set or clear bit { if(idx < len) { if(b) r[idx>>s] |= 1u<<(idx & m); else r[idx>>s] &= ~(cast(T)1<<(idx & m)); } } } } static if(isUnsigned!T) return BitArray(&a, 1); else return BitArray(&a[0], a.length); } |
Copyright © 1999-2021 by the D Language Foundation