Thread overview
random stuff you might find useful
May 22, 2007
Downs
May 22, 2007
Downs
May 22, 2007
torhu
May 22, 2007
Downs
May 22, 2007
Here's a collection of random stuff I made. Feel free to grab sniplets as you see fit.

module tools.Tools;
import std.string, std.thread, std.file, std.bind, std.stdio: FILE;
import std.c.stdio;

/// get the currently active thread (duh)
int getThread() { foreach (idx, thr; Thread.getAll) if (thr.isSelf) return idx; assert(false); }

// This _needs_ to be outside the function because it's a template func
Object logln_synch=null;
void _printf(T...)(char[] format, T t) { printf(toStringz(format), t); } /// tuple and C wrapper.
void _logln(T...)(T t) {
  foreach (index, part; t) {
    static if (is(typeof(part) : char[])) _printf("%.*s", part);
    else static if (is(typeof(part)==uint)) _printf("%u", part);
    else static if (is(typeof(part)==int)) _printf("%i", part);
    else static if (is(typeof(part)==char)) _printf("%c", part);
    else static if (is(typeof(part): Object)) _logln(part.toString);
    else static if (is(typeof(part)==bool)) _logln(part?"True":"False");
    else static if (isArray!(typeof(part))) {
      _logln("[");
      if (part.length) {
        foreach (elem; part[0..$-1]) { _logln(elem); _logln(", "); }
        _logln(part[$-1]);
      }
      _logln("]");
    }
    else static assert(false, "Type "~typeof(part).stringof~" not supported. Maybe you can add support for it?");
  }
}

void logln(T...)(T t) {
  if (!logln_synch) logln_synch=new Object;
  synchronized (logln_synch) _logln("[", getThread, "] ", t, "\n");
}

T[] toArray(T)(T *ptr) { int pos=0; while (ptr[pos]) pos++; return ptr[0..pos]; }

T *toPointer(T)(T[] array) { return (array~cast(T)0).ptr; }

// This is a straight C to D translation of the improved version of the Mersenne Twister algorithm,
// as available on http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c

// Period parameters
const N=624;
const M=397;
const MATRIX_A=0x9908b0df;   /* constant vector a */
const UPPER_MASK=0x80000000; /* most significant w-r bits */
const LOWER_MASK=0x7fffffff; /* least significant r bits */

struct mersenne {
  ulong mt[N]; /* the array for the state vector  */
  int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
  void init_genrand(ulong s) // initializes mt[N] with a seed
  {
      mt[0]=s;
      foreach (idx, inout elem; mt[1..$]) elem=(1812433253*(mt[idx]^(mt[idx]>>30))+idx);
      mti=mt.length;
  }
  /* generates a random number on [0,0xffffffff]-interval */
  ulong genrand_int32()
  {
    ulong y;
    static ulong mag01[]=[0, MATRIX_A];
    /* mag01[x] = x * MATRIX_A  for x=0,1 */
    if (mti >= mt.length) { /* generate N words at one time */
      int kk;
      if (mti == N+1)   /* if init_genrand() has not been called, */
        init_genrand(5489); /* a default initial seed is used */
      for (kk=0; kk<N-M; kk++) {
        y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
        mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[cast(int)y & 0x1];
      }
      for (;kk<N-1;kk++) {
        y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
        mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[cast(int)y & 0x1];
      }
      y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
      mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[cast(int)y & 0x1];
      mti = 0;
    }
    y = mt[mti++];
    /* Tempering */
    y ^= (y >> 11);
    y ^= (y << 7) & 0x9d2c5680;
    y ^= (y << 15) & 0xefc60000;
    y ^= (y >> 18);
    return y;
  }
  /* generates a random number on [0,1]-real-interval */
  real genrand_real1() {
    return genrand_int32()*(1.0/4294967295.0);
    /* divided by 2^32-1 */
  }
  /* generates a random number on [0,1)-real-interval */
  real genrand_real2() {
    return genrand_int32()*(1.0/4294967296.0);
    /* divided by 2^32 */
  }
  /* generates a random number on (0,1)-real-interval */
  real genrand_real3()
  {
    return ((cast(double)genrand_int32()) + 0.5)*(1.0/4294967296.0);
    /* divided by 2^32 */
  }
  /* These real versions are due to Isaku Wada, 2002/01/09 added */
}

class Random { mersenne m; this() { } void seed(uint v) { m.init_genrand(v); } uint next() { return cast(uint)m.genrand_int32; } }

bool has(T, U)(T[] array, U match) { static assert(is(U: T)); foreach (elem; array) if (elem==match) return true; return false; }

void remove(T)(inout T[] array, T key, bool all=true) {
  int pos=-1; foreach (i, e; array) if (e==key) { pos=i; break; }
  if (pos==-1) return;
  if (pos!=array.length-1) array[pos]=array[$-1];
  array=array[0..$-1];
  if (all) remove(array, key); /// tail recursion, theoretically
}

template isArray(T) { const isArray=false; }
template isArray(T: T[]) { const isArray=true; }

void swap(T)(inout T a, inout T b) { T c=a; a=b; b=c; }

/// if_is(myObject, (ObjectSubclass os) { os.doStuff; }, { logln("Error: can't cast myObject to subclass!"); });
void if_is(T, P)(P obj, void delegate(T) dg, call alt=null) { if (cast(T)obj) dg(cast(T)obj); else if (alt) alt(); }
void must_be(T, P) (P obj, void delegate(T) dg) { if (cast(T)obj) dg(cast(T)obj); else assert(false); }

template ArrayOf(Array) {
  static if (is(Array==void)) alias void ArrayOf;
  else alias Array[] ArrayOf;
}

/// int[] asciivalues=map("Test", (char e) { return cast(int)e; }); // yay waste of space
ArrayOf!(U) map(T, U)(T[] array, U delegate(T, size_t) dg) {
  static if (is(U==void)) {
    foreach (id, inout v; array) dg(v, id);
  } else {
    auto ret=new U[array.length];
    foreach (id, inout v; array) ret[id]=dg(v, id);
    return ret;
  }
}

ArrayOf!(U) map(T, U, Bogus=void)(T[] array, U delegate(T) dg) {
  static if (is(U==void)) map(array, (T t, size_t bogus) { dg(t); });
  else return map(array, (T t, size_t bogus) { return dg(t); });
}

alias void delegate() call;

void delegate(call) times(int e) { return bind((int foo, call dg) { for (int i=0; i<foo; ++i) dg(); }, e, _0).ptr; }

template tuple(T...) { alias T tuple; } // basics

template ptr(T...) { // the typetuple ptr!(T) consists of pointers to the types in T
  static if (T.length>1) alias tuple!(T[0]*, ptr!(T[1..$])) ptr;
  else alias T[0]* ptr;
}

struct multival(T...) { /// Simple holder for multiple values
  tuple!(T) val=void;
  static multival!(T) opCall(T t) { multival!(T) res=void; foreach (i, e; t) res.val[i]=e; return res; }
}

struct ptrlist(T...) { /// List of pointers to variables
  tuple!(ptr!(T)) v=void;
  static ptrlist!(T) opCall(inout T t) {
    ptrlist!(T) res=void;
    foreach (i, e; t) res.v[i]=&t[i]; // Ignore e because I can't make it inout anyway.
    return res;
  }
  void opAssign(multival!(T) res) {
    foreach (i, e; res.val) *v[i]=e;
  }
}

ptrlist!(T) list(T...)(inout T v) { return ptrlist!(T)(v); }
/// use that like, "multival!(char[], char[]) test() { return multival!(char[], char[])("Hello", "World"); } void main() { char[] a, b; list(a, b)=test(); }
May 22, 2007
Small improvement (is it actually? not sure ..) to the map function. This totally breaks the one-on-one mappingness and may also contain other subtle bugs, nevermind possibly be slower, so use it with care.
Works for me. No warranty. :p

ArrayOf!(U) map(T, U, V=Tuple!())(T[] array, U delegate(T, size_t) dg, bool delegate(V) valid=null) {
  static if (!is(U==void)) static assert(is(Tuple!(V)==Tuple!(U)), "Error: "~Tuple!(V).stringof~" is not "~Tuple!(U).stringof);
  static if (is(U==void)) {
    foreach (id, inout v; array) dg(v, id);
  } else {
    auto ret=new U[array.length];
    size_t i=0;
    foreach (id, inout v; array) { auto res=dg(v, id); static if (Tuple!(V).length) { if (!valid||valid(res)) ret[i++]=res; } else ret[i++]=res; }
    return ret[0..i];
  }
}

ArrayOf!(U) map(T, U, V=Tuple!(), Bogus=void)(T[] array, U delegate(T) dg, bool delegate(V) valid=null) {
  static if (is(U==void)) map!(T, U, V)(array, (T t, size_t bogus) { dg(t); }, valid);
  else return map!(T, U, V)(array, (T t, size_t bogus) { return dg(t); }, valid);
}
May 22, 2007
Downs wrote:
> Here's a collection of random stuff I made. Feel free to grab sniplets as you see fit.
> 
> module tools.Tools;
> import std.string, std.thread, std.file, std.bind, std.stdio: FILE;
> import std.c.stdio;
> 
> /// get the currently active thread (duh)
> int getThread() { foreach (idx, thr; Thread.getAll) if (thr.isSelf) return idx; assert(false); }
> 
<snip>

From std.thread docs:

static Thread getThis();
    Returns a reference to the Thread for the thread that called the function.

Isn't this what you're doing?
May 22, 2007
torhu wrote:
> Downs wrote:
>> Here's a collection of random stuff I made. Feel free to grab sniplets as you see fit.
>>
>> module tools.Tools;
>> import std.string, std.thread, std.file, std.bind, std.stdio: FILE;
>> import std.c.stdio;
>>
>> /// get the currently active thread (duh)
>> int getThread() { foreach (idx, thr; Thread.getAll) if (thr.isSelf) return idx; assert(false); }
>>
> <snip>
> 
>  From std.thread docs:
> 
> static Thread getThis();
>     Returns a reference to the Thread for the thread that called the function.
> 
> Isn't this what you're doing?
Basically yes, but in this case I needed an index for the current thread that is more easily readable than the reference address - note that getThread returns an integer.