digitalmars.D.learn - reinterpret array
- Dominikus Dittes Scherkl (37/37) Jan 13 2015 Does the following construct hold water?
- Adam D. Ruppe (6/8) Jan 13 2015 Nope, slicing never allocates, it just takes an address and
- Dominikus Dittes Scherkl (3/11) Jan 13 2015 Cool. So I can make the above even @nogc ?
- ketmar via Digitalmars-d-learn (10/12) Jan 13 2015 On Tue, 13 Jan 2015 17:09:31 +0000
- Dominikus Dittes Scherkl (12/24) Jan 13 2015 I see. So this function is completely superfluous :-/
- anonymous (3/8) Jan 13 2015 a |= 1 << 16;
- Dominikus Dittes Scherkl (14/24) Jan 13 2015 Of course you can calculate it, but the
- ketmar via Digitalmars-d-learn (9/45) Jan 13 2015 On Tue, 13 Jan 2015 20:52:13 +0000
- anonymous (11/24) Jan 13 2015 I didn't mean to put a stop to your idea just because we have
- Artur Skawina via Digitalmars-d-learn (37/72) Jan 13 2015 It's neat, but the real problems with it are:
- Dominikus Dittes Scherkl (43/52) Jan 14 2015 Ok, but this is the case with any function - and this modulo stuff
- bearophile (4/5) Jan 13 2015 In D there's also the 2 ^^ x syntax available.
- ketmar via Digitalmars-d-learn (7/7) Jan 13 2015 On Tue, 13 Jan 2015 20:00:56 +0000
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?
Jan 13 2015
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.
Jan 13 2015
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:Cool. So I can make the above even nogc ? Great.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.
Jan 13 2015
On Tue, 13 Jan 2015 17:09:31 +0000 Dominikus Dittes Scherkl via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:/// interpret an array of one type as an array of a different=20 type.may i point you to this? import std.stdio; void main () { ubyte[] a =3D [42,0,0,0, 155,2,0,0]; auto b =3D cast(uint[])a; writeln(b); // "[42, 667]" }
Jan 13 2015
On Tuesday, 13 January 2015 at 18:25:38 UTC, ketmar via Digitalmars-d-learn wrote:On Tue, 13 Jan 2015 17:09:31 +0000 Dominikus Dittes Scherkl via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote: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.../// 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]" }
Jan 13 2015
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;
Jan 13 2015
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: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 :-/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;
Jan 13 2015
On Tue, 13 Jan 2015 20:52:13 +0000 Dominikus Dittes Scherkl via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:On Tuesday, 13 January 2015 at 20:11:45 UTC, anonymous wrote: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.On Tuesday, 13 January 2015 at 20:00:57 UTC, Dominikus Dittes=20 Scherkl wrote:=20 Of course you can calculate it, but the syntax looks quite different if you want to do a.bit[22] =3D false: =20 a &=3D ~(1<<16); =20 Or if you want to test a bit: =20 if(a.bit[16]) =20 instead of =20 if(a & (1<<16)) =20 much more convenient for arrays: =20 ulong[100] a; =20 a.bit[3000] =3D true; =20 doing this directly with shifts is lousy (and error prone) =20 But ok. I see, it's not really awesome :-/So if I have a function that allowes to do this: uint a; a.bit[16] =3D true; writeln(a); // 65536 Is it also already available?a |=3D 1 << 16;
Jan 13 2015
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;
Jan 13 2015
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: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); } arturOn Tuesday, 13 January 2015 at 20:00:57 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 :-/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;
Jan 13 2015
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); }
Jan 14 2015
anonymous:a |= 1 << 16;In D there's also the 2 ^^ x syntax available. Bye, bearophile
Jan 13 2015
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!"
Jan 13 2015