Re: reinterpret array

2015-01-14 Thread Dominikus Dittes Scherkl via Digitalmars-d-learn
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

2015-01-13 Thread Artur Skawina via Digitalmars-d-learn
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

2015-01-13 Thread ketmar via Digitalmars-d-learn
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

2015-01-13 Thread anonymous via Digitalmars-d-learn
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

2015-01-13 Thread bearophile via Digitalmars-d-learn

anonymous:


a |= 1 << 16;


In D there's also the 2 ^^ x syntax available.

Bye,
bearophile


Re: reinterpret array

2015-01-13 Thread ketmar via Digitalmars-d-learn
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

2015-01-13 Thread Dominikus Dittes Scherkl via Digitalmars-d-learn

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

2015-01-13 Thread anonymous via Digitalmars-d-learn
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

2015-01-13 Thread Dominikus Dittes Scherkl via Digitalmars-d-learn
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

2015-01-13 Thread ketmar via Digitalmars-d-learn
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

2015-01-13 Thread Dominikus Dittes Scherkl via Digitalmars-d-learn

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

2015-01-13 Thread Adam D. Ruppe via Digitalmars-d-learn
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

2015-01-13 Thread Dominikus Dittes Scherkl via Digitalmars-d-learn

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?