www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - reinterpret array

reply "Dominikus Dittes Scherkl" writes:
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
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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
parent "Dominikus Dittes Scherkl" writes:
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.
Jan 13 2015
prev sibling parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
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
parent reply "Dominikus Dittes Scherkl" writes:
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:

     /// 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...
Jan 13 2015
next sibling parent reply "anonymous" <anonymous example.com> writes:
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
next sibling parent reply "Dominikus Dittes Scherkl" writes:
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 :-/
Jan 13 2015
next sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
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:
 On Tuesday, 13 January 2015 at 20:00:57 UTC, Dominikus Dittes=20
 Scherkl wrote:
 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;
=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 :-/
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.
Jan 13 2015
prev sibling next sibling parent "anonymous" <anonymous example.com> writes:
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
prev sibling parent reply Artur Skawina via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
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
Jan 13 2015
parent "Dominikus Dittes Scherkl" writes:
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
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
anonymous:

 a |= 1 << 16;
In D there's also the 2 ^^ x syntax available. Bye, bearophile
Jan 13 2015
prev sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
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