www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - random stuff you might find useful

reply Downs <default_357-line yahoo.de> writes:
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
next sibling parent Downs <default_357-line yahoo.de> writes:
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
prev sibling parent reply torhu <fake address.dude> writes:
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
parent Downs <default_357-line yahoo.de> writes:
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.
May 22 2007