Re: reinterpret array
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]>>(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); }
Re: reinterpret array
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<=UB) assert (0); return !!(e[o] & 1L<
Re: reinterpret array
On Tue, 13 Jan 2015 20:00:56 + Dominikus Dittes Scherkl via Digitalmars-d-learn 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!" signature.asc Description: PGP signature
Re: reinterpret array
On Tuesday, 13 January 2015 at 20:52:15 UTC, Dominikus Dittes Scherkl wrote: 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 :-/ I didn't mean to put a stop to your idea just because we have bitwise operators. You're totally right: They're somewhat cumbersome and easy to get wrong. We also have std.bitmanip.BitArray which is what you're after, I think: import std.bitmanip: BitArray; BitArray ba; ba.length = 3001; ba[3000] = true;
Re: reinterpret array
anonymous: a |= 1 << 16; In D there's also the 2 ^^ x syntax available. Bye, bearophile
Re: reinterpret array
On Tue, 13 Jan 2015 20:52:13 + 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 not better than using something like this: a.bitSet(22); a.bitReset(30); if (a.bit(16)) { ... } you can easily do this with UFCS. you can even write some templates to convert it to bit operations in compile time. signature.asc Description: PGP signature
Re: reinterpret array
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 :-/
Re: reinterpret array
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;
Re: reinterpret array
On Tuesday, 13 January 2015 at 18:25:38 UTC, ketmar via Digitalmars-d-learn wrote: On Tue, 13 Jan 2015 17:09:31 + Dominikus Dittes Scherkl via Digitalmars-d-learn wrote: /// interpret an array of one type as an array of a different type. may i point you to this? import std.stdio; void main () { ubyte[] a = [42,0,0,0, 155,2,0,0]; auto b = cast(uint[])a; writeln(b); // "[42, 667]" } I see. So this function is completely superfluous :-/ Good to know. 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? Because I somewhat hate it that with D I can create great stuff, but it is not necessary because D already has something much cooler...
Re: reinterpret array
On Tue, 13 Jan 2015 17:09:31 + Dominikus Dittes Scherkl via Digitalmars-d-learn wrote: > /// interpret an array of one type as an array of a different > type. may i point you to this? import std.stdio; void main () { ubyte[] a = [42,0,0,0, 155,2,0,0]; auto b = cast(uint[])a; writeln(b); // "[42, 667]" } signature.asc Description: PGP signature
Re: reinterpret array
On Tuesday, 13 January 2015 at 17:12:42 UTC, Adam D. Ruppe wrote: On Tuesday, 13 January 2015 at 17:09:32 UTC, Dominikus Dittes Scherkl wrote: I assume taking a slice of a pointer uses the GC, so this cannot be @nogc, am I right? Nope, slicing never allocates, it just takes an address and length. If you append to a slice or increase the length though, the GC might reallocate it. Cool. So I can make the above even @nogc ? Great.
Re: reinterpret array
On Tuesday, 13 January 2015 at 17:09:32 UTC, Dominikus Dittes Scherkl wrote: I assume taking a slice of a pointer uses the GC, so this cannot be @nogc, am I right? Nope, slicing never allocates, it just takes an address and length. If you append to a slice or increase the length though, the GC might reallocate it.
reinterpret array
Does the following construct hold water? version(LittleEndian) { /// interpret an array of one type as an array of a different type. /// if the array has odd length, the highest elements are /// not accessible, at worst an empty slice is returned inout ref T[] arrayOf(T, V: U[])(inout ref V a) pure @safe nothrow if(isUnsigned!T && isUnsigned!U) { return (cast(T*)a.ptr)[0 .. a.length * U.sizeof / T.sizeof]; } unittest { ubyte a[5] = { 1, 2, 3, 4, 5 }; auto b = a.arrayOf!uint; assert(typeof(b) == uint[]); assert(b.length == 1); assert(b[0] == 0x04030201); assert(&b[0] == &a[0]); // b is a slice of a b[0] = 0x0a0b0c0d; // this will change a assert(a == { 13, 12, 11, 10, 5 }); ushort c[2] = { 257, 512 }; auto d = c.arrayOf!ubyte; assert(d.length == 4); assert(d[0] == 1); assert(d[1] == 1); assert(d[2] == 0); assert(d[3] == 2); } } I assume taking a slice of a pointer uses the GC, so this cannot be @nogc, am I right? And I assume it is @save, because if I would increase the length of the returned value, the GC will automatically re-allocate, but then of course the adress is no more the same, yes?