]> git.llucax.com Git - software/dgc/dgcbench.git/commitdiff
Update micro benchmarks
authorLeandro Lucarella <llucax@gmail.com>
Sun, 14 Nov 2010 03:39:16 +0000 (00:39 -0300)
committerLeandro Lucarella <llucax@gmail.com>
Sun, 14 Nov 2010 03:39:16 +0000 (00:39 -0300)
Remove some micro benchmarks that provided no added value, rename others
to have shorter names and add a few; some Olden benchmarks and a couple
of benchmarks to exercise concurrency.

14 files changed:
Makefile
micro/bh.d [new file with mode: 0644]
micro/bigarr.d [moved from micro/big_arrays.d with 100% similarity]
micro/bisort.d [new file with mode: 0644]
micro/conalloc.d [new file with mode: 0644]
micro/concpu.d [new file with mode: 0644]
micro/em3d.d [new file with mode: 0644]
micro/mcore.d [moved from micro/multicore.d with 100% similarity]
micro/rnd_data_2.d [deleted file]
micro/rnddata.d [moved from micro/rnd_data.d with 52% similarity]
micro/sbtree.d [new file with mode: 0644]
micro/shootout_binarytrees.d [deleted file]
micro/tree.d [deleted file]
micro/tsp.d [new file with mode: 0644]

index 5ff8b622e1442f52944058bc6b4194bfae05604a..f32edb62ae29a89359ab1a75cdd78e23975b3a37 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,11 @@
 
 GC       := cdgc
-O        := build/$(GC)
-DC       := dmd
-LD       := dmd
+B        := build
+O        := $B/$(GC)
+DC       := ../dmd/src/dmd
+LD       := ../dmd/src/dmd
 LN       := ln
-GNUPLOT  := gnuplot
+TIME     := /usr/bin/time
 override DFLAGS ?= -release -inline -O -gc
 LDFLAGS  := -defaultlib=tango-$(GC) -debuglib=tango-$(GC)
 LIBTANGO := ../lib/libtango-$(GC).a
@@ -13,7 +14,7 @@ ifndef V
 P      = @
 P_DC   = @printf '   DC    %- 40s <-  %s\n' '$@' '$(if \
                $(subst 1,,$(words $^)),$< ... $(lastword $^),$<)';
-P_PLOT = @printf '   PLOT  %- 40s <-  %s\n' '$@' '$(filter %.csv,$^)';
+P_PLOT = @printf '   PLOT  %- 40s <-  %s\n' '$@' '$(notdir $(filter %.csv,$^))';
 P_AWK  = @printf '   AWK   %- 40s <-  %s\n' '$@' '$<';
 P_RUN  = @printf '   RUN   $< $(args)\n';
 P_MAKE = @printf '   MAKE  $@\n';
@@ -24,46 +25,81 @@ endif
 # create build directories if they don't already exist
 dummy_mkdir := $(shell mkdir -p $O $O/bin $O/time $O/stats)
 
+
+########################################################
+# general rules that doesn't depend on the GC variable #
+########################################################
+
 .PHONY: all
-all: cdgc basic
+all: basic cdgc
+
+.PHONY: micro-time
+micro: micro-time
+
+.PHONY: dil
+dil:
+       # TODO
+
+.PHONY: micro-time
+micro-time: $B/time.eps $B/time.svg
+$B/time.%: $(patsubst micro/%.d,$B/time-%.csv,$(wildcard micro/*.d)) \
+                       time-plot.tpl-gpi time-plot.sh templite.py
+       $(P_PLOT) ./time-plot.sh $* $@ $(filter %.csv,$^)
+
+.PRECIOUS: $B/time-%.csv
+$B/time-%.csv: $B/basic/time/%.csv | basic cdgc
+       $P echo -n > $@
+       $P for t in basic cdgc; do \
+               (echo -n $$t,; ./stats.py < $B/$$t/time/$*.csv) >> $@; \
+               echo "   STATS `tail -n1 $@` >> $@"; \
+          done
 
 .PHONY: cdgc basic
 cdgc basic:
-       $(P_MAKE) $(MAKE) --no-print-directory micro-time dil-build GC=$@
+       $(P_MAKE) $(MAKE) --no-print-directory micro-gc-build dil-gc-build GC=$@
 
 
+.PHONY: clean-all clean-cdgc clean-basic
+clean-all: clean-cdgc clean-basic
+clean-cdgc:
+       $(P_MAKE) $(MAKE) --no-print-directory clean GC=cdgc
+clean-basic:
+       $(P_MAKE) $(MAKE) --no-print-directory clean GC=basic
+
+
+#########################################
+# rules that depends on the GC variable #
+#########################################
+
 # micro
 ########
 
 micro-src := $(wildcard micro/*.d)
 
-.PHONY: micro-build
-micro-build: $(patsubst micro/%.d,$O/bin/%,$(wildcard micro/*.d))
+.PHONY: micro-gc-build
+micro-gc-build: $(patsubst micro/%.d,$O/bin/%,$(wildcard micro/*.d))
 
 .PRECIOUS: $O/bin/%
-$O/bin/%: $O/micro/%.o
+$O/bin/%: $O/micro/%.o $(LIBTANGO)
        $(P_DC) $(DC) $(LDFLAGS) -of$@ $^
 
-.PHONY: micro-time
-micro-time: $O/time/stats.csv
+.PHONY: micro-gc-time
+micro-gc-time: $(patsubst micro/%.d,$O/time/%.csv,$(wildcard micro/*.d))
 
-.PHONY: micro-stats
-micro-stats: $(patsubst micro/%.d,$O/stats/%.eps,$(wildcard micro/*.d))
+.PHONY: micro-gc-stats
+micro-gc-stats: $(patsubst micro/%.d,$O/stats/%.eps,$(wildcard micro/*.d))
 
 # special command line arguments for 'shootout_binarytrees' micro benchmark
-$O/time/shootout_binarytrees.t.csv $O/time/shootout_binarytrees.s.csv \
-               $O/stats/shootout_binarytrees.c.csv \
+$O/time/shootout_binarytrees.csv $O/stats/shootout_binarytrees.c.csv \
                $O/stats/shootout_binarytrees.a.csv: \
        override args := 16
 
 # special command line arguments for 'split' micro benchmark
-$O/time/split.t.csv $O/time/split.s.csv \
-               $O/stats/split.c.csv $O/stats/split.a.csv: \
-       override args := micro/bible.txt
+$O/time/split.csv $O/stats/split.c.csv $O/stats/split.a.csv: \
+       override args := micro/bible.txt 2
 
 # special command line arguments for 'voronoi' micro benchmark
-$O/time/voronoi.t.csv $O/time/voronoi.s.csv \
-               $O/stats/voronoi.c.csv $O/voronoi/split.a.csv: \
+$O/time/voronoi.csv $O/stats/voronoi.c.csv $O/voronoi/split.a.csv: \
        override args := -n 30000
 
 
@@ -73,17 +109,14 @@ $O/time/voronoi.t.csv $O/time/voronoi.s.csv \
 DIL_SRC = $(wildcard dil/src/*.d dil/src/cmd/*.d dil/src/util/*.d \
                        dil/src/dil/*.d dil/src/dil/*/*.d)
 
-.PHONY: dil-nop-stats
-dil-nop-stats: $O/stats/dil-nop.eps
-
-.PHONY: dil-build
-dil-build: $O/bin/dil
+.PHONY: dil-gc-build
+dil-gc-build: $O/bin/dil
 $O/bin/dil: override DFLAGS += -Idil/src
 $O/bin/dil: $(patsubst %.d,$O/%.o,$(DIL_SRC)) $(LIBTANGO)
        $(P_DC) $(DC) $(LDFLAGS) -L-lmpfr -L-lgmp -of$@ $^
 
-$O/bin/dil-nop: $O/bin/dil
-       @$(P_LN) $(LN) -sf $(<F) $@
+.PHONY: dil-gc-time
+dil-gc-time: $O/time/dil.csv
 
 
 # common rules
@@ -93,26 +126,18 @@ $O/bin/dil-nop: $O/bin/dil
 $O/%.o: %.d
        $(P_DC) $(DC) -c $(DFLAGS) -of$@ $^
 
-I := 10
-.PRECIOUS: $O/time/%.t.csv
+I := 3
+.PRECIOUS: $O/time/%.csv
 ifeq ($F,1)
 .PHONY: $(patsubst micro/%.d,$O/bin/%,$(wildcard micro/*.d))
 endif
-$O/time/%.t.csv: $O/bin/%
+$O/time/%.csv: $O/bin/%
        $P echo -n '   RUN   $* $(args) > $@ ($I)'
        $P echo -n > $@
        $P for i in `seq $I`; do \
                echo -n " $$i"; \
-               time -f%e -a -o $@ ./$< $(args); \
-          done; echo
-
-.PRECIOUS: $O/time/stats.csv
-$O/time/stats.csv: $(patsubst micro/%.d,$O/time/%.t.csv,$(micro-src))
-       $P echo -n > $@
-       $P for t in $^; do \
-               (echo -n `basename $$t`,; ./stats.py < $$t) >> $@; \
-               echo "   STATS `tail -n1 $@` >> $@"; \
-          done
+               $(TIME) -f%e -a -o $@ ./$< $(args); \
+       done; echo
 
 .PRECIOUS: $O/stats/%.c.csv $O/stats/%.a.csv
 $O/stats/%.c.csv $O/stats/%.a.csv: $O/bin/%
@@ -140,10 +165,3 @@ $O/stats/%.eps: $O/stats/%.c.csv $O/stats/%.a.csv $O/stats/%.h.csv \
 clean: $O/
        $(P_RM) $(RM) -r $^
 
-.PHONY: clean-all
-clean-all: clean-cdgc clean-basic
-clean-cdgc:
-       $(P_MAKE) $(MAKE) --no-print-directory clean GC=cdgc
-clean-basic:
-       $(P_MAKE) $(MAKE) --no-print-directory clean GC=basic
-
diff --git a/micro/bh.d b/micro/bh.d
new file mode 100644 (file)
index 0000000..a1c092a
--- /dev/null
@@ -0,0 +1,1045 @@
+/**\r
+A D implementation of the _bh_ Olden benchmark.\r
+The Olden benchmark implements the Barnes-Hut benchmark\r
+that is decribed in:\r
+\r
+J. Barnes and P. Hut, "A hierarchical o(N log N) force-calculation algorithm",\r
+Nature, 324:446-449, Dec. 1986\r
+\r
+The original code in the Olden benchmark suite is derived from the\r
+ftp://hubble.ifa.hawaii.edu/pub/barnes/treecode\r
+source distributed by Barnes.\r
+\r
+Java code converted to D by leonardo maffi, V.1.0, Dec 25 2009.\r
+\r
+Removed output unless an option is passed by Leandro Lucarella, 2010-08-04.\r
+Downloaded from http://www.fantascienza.net/leonardo/js/\r
+                http://www.fantascienza.net/leonardo/js/dolden_bh.zip\r
+*/\r
+\r
+\r
+version (Tango) {\r
+    import tango.stdc.stdio: printf, sprintf, fprintf, stderr;\r
+    import tango.stdc.stdlib: exit, malloc, free;\r
+    import tango.stdc.time: CLOCKS_PER_SEC, clock;\r
+    import tango.math.Math: sqrt, floor, PI, pow;\r
+\r
+    import Integer = tango.text.convert.Integer;\r
+    alias Integer.parse toInt;\r
+} else {\r
+    import std.c.stdio: printf, sprintf, fprintf, stderr;\r
+    import std.c.stdlib: exit, malloc, free;\r
+    import std.c.time: CLOCKS_PER_SEC, clock;\r
+    import std.math: sqrt, floor, PI, pow;\r
+\r
+    version (D_Version2) {\r
+        import std.conv: to;\r
+        alias to!(int, char[]) toInt;\r
+    } else {\r
+        import std.conv: toInt;\r
+    }\r
+}\r
+\r
+\r
+double myclock() {\r
+    return clock() / cast(double)CLOCKS_PER_SEC;\r
+}\r
+\r
+\r
+/*\r
+Basic uniform random generator: Minimal Standard in Park and\r
+Miller (1988): "Random Number Generators: Good Ones Are Hard to\r
+Find", Comm. of the ACM, 31, 1192-1201.\r
+Parameters: m = 2^31-1, a=48271.\r
+\r
+Adapted from Pascal code by Jesper Lund:\r
+http://www.gnu-pascal.de/crystal/gpc/en/mail1390.html\r
+*/\r
+struct Random {\r
+    const int m = int.max;\r
+    const int a = 48_271;\r
+    const int q = m / a;\r
+    const int r = m % a;\r
+    int seed;\r
+\r
+    public double uniform(double min, double max) {\r
+        int k = seed / q;\r
+        seed = a * (seed - k * q) - r * k;\r
+        if (seed < 1)\r
+            seed += m;\r
+        double r = cast(double)seed / m;\r
+        return r * (max - min) + min;\r
+    }\r
+}\r
+\r
+\r
+interface Enumeration {\r
+    bool hasMoreElements();\r
+    Object nextElement();\r
+}\r
+\r
+\r
+/**\r
+A class representing a three dimensional vector that implements\r
+several math operations.  To improve speed we implement the\r
+vector as an array of doubles rather than use the exising\r
+code in the java.util.Vec3 class.\r
+*/\r
+final class Vec3 {\r
+    /// The number of dimensions in the vector\r
+    // Can't be changed because of crossProduct()\r
+    const int NDIM = 3;\r
+\r
+    /// An array containing the values in the vector.\r
+    private double data[];\r
+\r
+    /// Construct an empty 3 dimensional vector for use in Barnes-Hut algorithm.\r
+    this() {\r
+        data.length = NDIM;\r
+        data[] = 0.0;\r
+    }\r
+\r
+    /// Create a copy of the vector. Return a clone of the math vector\r
+    public Vec3 clone() {\r
+        Vec3 v = new Vec3;\r
+        v.data.length = NDIM;\r
+        v.data[] = this.data[];\r
+        return v;\r
+    }\r
+\r
+    /**\r
+    Return the value at the i'th index of the vector.\r
+    @param i the vector index\r
+    @return the value at the i'th index of the vector.\r
+    */\r
+    final double value(int i) {\r
+        return data[i];\r
+    }\r
+\r
+    /**\r
+    Set the value of the i'th index of the vector.\r
+    @param i the vector index\r
+    @param v the value to store\r
+    */\r
+    final void value(int i, double v) {\r
+        data[i] = v;\r
+    }\r
+\r
+    /**\r
+    Set one of the dimensions of the vector to 1.0\r
+    param j the dimension to set.\r
+    */\r
+    final void unit(int j) {\r
+        for (int i = 0; i < NDIM; i++)\r
+            data[i] = (i == j) ? 1.0 : 0.0;\r
+    }\r
+\r
+    /**\r
+    Add two vectors and the result is placed in this vector.\r
+    @param u the other operand of the addition\r
+    */\r
+    final void addition(Vec3 u) {\r
+        for (int i = 0; i < NDIM; i++)\r
+            data[i] += u.data[i];\r
+    }\r
+\r
+    /**\r
+   * Subtract two vectors and the result is placed in this vector.\r
+   * This vector contain the first operand.\r
+   * @param u the other operand of the subtraction.\r
+   **/\r
+    final void subtraction(Vec3 u) {\r
+        for (int i = 0; i < NDIM; i++)\r
+            data[i] -= u.data[i];\r
+    }\r
+\r
+    /**\r
+    Subtract two vectors and the result is placed in this vector.\r
+    @param u the first operand of the subtraction.\r
+    @param v the second opernd of the subtraction\r
+    */\r
+    final void subtraction(Vec3 u, Vec3 v) {\r
+        for (int i = 0; i < NDIM; i++)\r
+            data[i] = u.data[i] - v.data[i];\r
+    }\r
+\r
+    /**\r
+    Multiply the vector times a scalar.\r
+    @param s the scalar value\r
+    **/\r
+    final void multScalar(double s) {\r
+        for (int i = 0; i < NDIM; i++)\r
+            data[i] *= s;\r
+    }\r
+\r
+    /**\r
+    * Multiply the vector times a scalar and place the result in this vector.\r
+    * @param u the vector\r
+    * @param s the scalar value\r
+    **/\r
+    final void multScalar(Vec3 u, double s) {\r
+        for (int i = 0; i < NDIM; i++)\r
+            data[i] = u.data[i] * s;\r
+    }\r
+\r
+    /**\r
+    * Divide each element of the vector by a scalar value.\r
+    * @param s the scalar value.\r
+    **/\r
+    final void divScalar(double s) {\r
+        for (int i = 0; i < NDIM; i++)\r
+            data[i] /= s;\r
+    }\r
+\r
+    /**\r
+    * Return the dot product of a vector.\r
+    * @return the dot product of a vector.\r
+    **/\r
+    final double dotProduct() {\r
+        double s = 0.0;\r
+        for (int i = 0; i < NDIM; i++)\r
+            s += data[i] * data[i];\r
+        return s;\r
+    }\r
+\r
+    final double absolute() {\r
+        double tmp = 0.0;\r
+        for (int i = 0; i < NDIM; i++)\r
+            tmp += data[i] * data[i];\r
+        return sqrt(tmp);\r
+    }\r
+\r
+    final double distance(Vec3 v) {\r
+        double tmp = 0.0;\r
+        for (int i = 0; i < NDIM; i++)\r
+            tmp += ((data[i] - v.data[i]) * (data[i] - v.data[i]));\r
+        return sqrt(tmp);\r
+    }\r
+\r
+    final void crossProduct(Vec3 u, Vec3 w) {\r
+        data[0] = u.data[1] * w.data[2] - u.data[2] * w.data[1];\r
+        data[1] = u.data[2] * w.data[0] - u.data[0] * w.data[2];\r
+        data[2] = u.data[0] * w.data[1] - u.data[1] * w.data[0];\r
+    }\r
+\r
+    final void incrementalAdd(Vec3 u) {\r
+        for (int i = 0; i < NDIM; i++)\r
+            data[i] += u.data[i];\r
+    }\r
+\r
+    final void incrementalSub(Vec3 u) {\r
+        for (int i = 0; i < NDIM; i++)\r
+            data[i] -= u.data[i];\r
+    }\r
+\r
+    final void incrementalMultScalar(double s) {\r
+        for (int i = 0; i < NDIM; i++)\r
+            data[i] *= s;\r
+    }\r
+\r
+    final void incrementalDivScalar(double s) {\r
+        for (int i = 0; i < NDIM; i++)\r
+            data[i] /= s;\r
+    }\r
+\r
+    final void addScalar(Vec3 u, double s) {\r
+        for (int i = 0; i < NDIM; i++)\r
+            data[i] = u.data[i] + s;\r
+    }\r
+\r
+    public char* toCString() {\r
+        // this is not generic code at all\r
+        char* result = cast(char*)malloc(100);\r
+        if (result == null) exit(1);\r
+        sprintf(result, "%.17f %.17f %.17f ", data[0], data[1], data[2]);\r
+        return result;\r
+    }\r
+}\r
+\r
+\r
+/// A class that represents the common fields of a cell or body data structure.\r
+abstract class Node {\r
+    // mass of the node\r
+    double mass;\r
+\r
+    // Position of the node\r
+    Vec3 pos;\r
+\r
+    // highest bit of int coord\r
+    const int IMAX = 1073741824;\r
+\r
+    // potential softening parameter\r
+    const double EPS = 0.05;\r
+\r
+    /// Construct an empty node\r
+    protected this() {\r
+        mass = 0.0;\r
+        pos = new Vec3();\r
+    }\r
+\r
+    abstract Node loadTree(Body p, Vec3 xpic, int l, Tree root);\r
+\r
+    abstract double hackcofm();\r
+\r
+    abstract HG walkSubTree(double dsq, HG hg);\r
+\r
+    static final int oldSubindex(Vec3 ic, int l) {\r
+        int i = 0;\r
+        for (int k = 0; k < Vec3.NDIM; k++)\r
+            if ((cast(int)ic.value(k) & l) != 0)\r
+                i += Cell.NSUB >> (k + 1);\r
+        return i;\r
+    }\r
+\r
+    public char* toCString() {\r
+        char* result = cast(char*)malloc(130);\r
+        if (result == null) exit(1);\r
+        char* pos_str = pos.toCString();\r
+        sprintf(result, "%f : %s", mass, pos_str);\r
+        free(pos_str);\r
+        return result;\r
+    }\r
+\r
+    /// Compute a single body-body or body-cell interaction\r
+    final HG gravSub(HG hg) {\r
+        Vec3 dr = new Vec3();\r
+        dr.subtraction(pos, hg.pos0);\r
+\r
+        double drsq = dr.dotProduct() + (EPS * EPS);\r
+        double drabs = sqrt(drsq);\r
+\r
+        double phii = mass / drabs;\r
+        hg.phi0 -= phii;\r
+        double mor3 = phii / drsq;\r
+        dr.multScalar(mor3);\r
+        hg.acc0.addition(dr);\r
+        return hg;\r
+    }\r
+\r
+    /**\r
+    * A sub class which is used to compute and save information during the\r
+    * gravity computation phase.\r
+    **/\r
+    static protected final class HG {\r
+        /// Body to skip in force evaluation\r
+        Body pskip;\r
+\r
+        /// Point at which to evaluate field\r
+        Vec3 pos0;\r
+\r
+        /// Computed potential at pos0\r
+\r
+        double phi0;\r
+\r
+        /// computed acceleration at pos0\r
+        Vec3 acc0;\r
+\r
+        /**\r
+        * Create a HG  object.\r
+        * @param b the body object\r
+        * @param p a vector that represents the body\r
+        **/\r
+        this(Body b, Vec3 p) {\r
+            pskip = b;\r
+            pos0 = p.clone();\r
+            phi0 = 0.0;\r
+            acc0 = new Vec3();\r
+        }\r
+    }\r
+}\r
+\r
+\r
+/// A class used to representing particles in the N-body simulation.\r
+final class Body : Node {\r
+    Vec3 vel, acc, newAcc;\r
+    double phi = 0.0;\r
+    private Body next, procNext;\r
+\r
+    /// Create an empty body.\r
+    this() {\r
+        vel = new Vec3();\r
+        acc = new Vec3();\r
+        newAcc = new Vec3();\r
+    }\r
+\r
+    /**\r
+    * Set the next body in the list.\r
+    * @param n the body\r
+    **/\r
+    final void setNext(Body n) {\r
+        next = n;\r
+    }\r
+\r
+    /**\r
+    * Get the next body in the list.\r
+    * @return the next body\r
+    **/\r
+    final Body getNext() {\r
+        return next;\r
+    }\r
+\r
+    /**\r
+    * Set the next body in the list.\r
+    * @param n the body\r
+    **/\r
+    final void setProcNext(Body n) {\r
+        procNext = n;\r
+    }\r
+\r
+    /**\r
+    * Get the next body in the list.\r
+    * @return the next body\r
+    **/\r
+    final Body getProcNext() {\r
+        return procNext;\r
+    }\r
+\r
+    /**\r
+    * Enlarge cubical "box", salvaging existing tree structure.\r
+    * @param tree the root of the tree.\r
+    * @param nsteps the current time step\r
+    **/\r
+    final void expandBox(Tree tree, int nsteps) {\r
+        Vec3 rmid = new Vec3();\r
+\r
+        bool inbox = icTest(tree);\r
+        while (!inbox) {\r
+            double rsize = tree.rsize;\r
+            rmid.addScalar(tree.rmin, 0.5 * rsize);\r
+\r
+            for (int k = 0; k < Vec3.NDIM; k++)\r
+                if (pos.value(k) < rmid.value(k)) {\r
+                    double rmin = tree.rmin.value(k);\r
+                    tree.rmin.value(k, rmin - rsize);\r
+                }\r
+\r
+            tree.rsize = 2.0 * rsize;\r
+            if (tree.root !is null) {\r
+                Vec3 ic = tree.intcoord(rmid);\r
+                if (ic is null)\r
+                    throw new Exception("Value is out of bounds");\r
+                int k = oldSubindex(ic, IMAX >> 1);\r
+                Cell newt = new Cell();\r
+                newt.subp[k] = tree.root;\r
+                tree.root = newt;\r
+                inbox = icTest(tree);\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+    * Check the bounds of the body and return true if it isn't in the\r
+    * correct bounds.\r
+    **/\r
+    final bool icTest(Tree tree) {\r
+        double pos0 = pos.value(0);\r
+        double pos1 = pos.value(1);\r
+        double pos2 = pos.value(2);\r
+\r
+        // by default, it is in bounds\r
+        bool result = true;\r
+\r
+        double xsc = (pos0 - tree.rmin.value(0)) / tree.rsize;\r
+        if (!(0.0 < xsc && xsc < 1.0))\r
+            result = false;\r
+\r
+        xsc = (pos1 - tree.rmin.value(1)) / tree.rsize;\r
+        if (!(0.0 < xsc && xsc < 1.0))\r
+            result = false;\r
+\r
+        xsc = (pos2 - tree.rmin.value(2)) / tree.rsize;\r
+        if (!(0.0 < xsc && xsc < 1.0))\r
+            result = false;\r
+\r
+        return result;\r
+    }\r
+\r
+    /**\r
+    * Descend Tree and insert particle.  We're at a body so we need to\r
+    * create a cell and attach this body to the cell.\r
+    * @param p the body to insert\r
+    * @param xpic\r
+    * @param l\r
+    * @param tree the root of the data structure\r
+    * @return the subtree with the new body inserted\r
+    **/\r
+    final Node loadTree(Body p, Vec3 xpic, int l, Tree tree) {\r
+        // create a Cell\r
+        Cell retval = new Cell();\r
+        int si = subindex(tree, l);\r
+        // attach this Body node to the cell\r
+        retval.subp[si] = this;\r
+\r
+        // move down one level\r
+        si = oldSubindex(xpic, l);\r
+        Node rt = retval.subp[si];\r
+        if (rt !is null)\r
+            retval.subp[si] = rt.loadTree(p, xpic, l >> 1, tree);\r
+        else\r
+            retval.subp[si] = p;\r
+        return retval;\r
+    }\r
+\r
+    /**\r
+    * Descend tree finding center of mass coordinates\r
+    * @return the mass of this node\r
+    **/\r
+    final double hackcofm() {\r
+        return mass;\r
+    }\r
+\r
+    /// iteration of the bodies\r
+    int opApply(int delegate(ref Body) dg) {\r
+        int result;\r
+        Body current = this;\r
+        while (current !is null) {\r
+            result = dg(current);\r
+            current = current.next;\r
+            if (result)\r
+                break;\r
+        }\r
+        return result;\r
+    }\r
+\r
+    /// inverse iteration of the bodies\r
+    int opApplyReverse(int delegate(ref Body) dg) {\r
+        int result;\r
+        Body current = this;\r
+        while (current !is null) {\r
+            result = dg(current);\r
+            current = current.procNext;\r
+            if (result)\r
+                break;\r
+        }\r
+        return result;\r
+    }\r
+\r
+\r
+    /**\r
+    * Return an enumeration of the bodies\r
+    * @return an enumeration of the bodies\r
+    **/\r
+    final Enumeration elements() {\r
+        // a local class that implements the enumerator\r
+        static final class Enumerate : Enumeration {\r
+            private Body current;\r
+            public this(Body outer) {\r
+                //this.current = Body.this;\r
+                this.current = outer;\r
+            }\r
+            public bool hasMoreElements() {\r
+                return current !is null;\r
+            }\r
+            public Object nextElement() {\r
+                Object retval = current;\r
+                current = current.next;\r
+                return retval;\r
+            }\r
+        }\r
+\r
+        return new Enumerate(this);\r
+    }\r
+\r
+    final Enumeration elementsRev() {\r
+        // a local class that implements the enumerator\r
+        static class Enumerate : Enumeration {\r
+            private Body current;\r
+            public this(Body outer) {\r
+                //this.current = Body.this;\r
+                this.current = outer;\r
+            }\r
+            public bool hasMoreElements() {\r
+                return current !is null;\r
+            }\r
+            public Object nextElement() {\r
+                Object retval = current;\r
+                current = current.procNext;\r
+                return retval;\r
+            }\r
+        }\r
+\r
+        return new Enumerate(this);\r
+    }\r
+\r
+    /**\r
+    * Determine which subcell to select.\r
+    * Combination of intcoord and oldSubindex.\r
+    * @param t the root of the tree\r
+    **/\r
+    final int subindex(Tree tree, int l) {\r
+        Vec3 xp = new Vec3();\r
+\r
+        double xsc = (pos.value(0) - tree.rmin.value(0)) / tree.rsize;\r
+        xp.value(0, floor(IMAX * xsc));\r
+\r
+        xsc = (pos.value(1) - tree.rmin.value(1)) / tree.rsize;\r
+        xp.value(1, floor(IMAX * xsc));\r
+\r
+        xsc = (pos.value(2) - tree.rmin.value(2)) / tree.rsize;\r
+        xp.value(2, floor(IMAX * xsc));\r
+\r
+        int i = 0;\r
+        for (int k = 0; k < Vec3.NDIM; k++)\r
+            if ((cast(int)xp.value(k) & l) != 0)\r
+                i += Cell.NSUB >> (k + 1);\r
+        return i;\r
+    }\r
+\r
+    /**\r
+    * Evaluate gravitational field on the body.\r
+    * The original olden version calls a routine named "walkscan",\r
+    * but we use the same name that is in the Barnes code.\r
+    **/\r
+    final void hackGravity(double rsize, Node root) {\r
+        Vec3 pos0 = pos.clone();\r
+        HG hg = new HG(this, pos);\r
+        hg = root.walkSubTree(rsize * rsize, hg);\r
+        phi = hg.phi0;\r
+        newAcc = hg.acc0;\r
+    }\r
+\r
+    /// Recursively walk the tree to do hackwalk calculation\r
+    final HG walkSubTree(double dsq, HG hg) {\r
+        if (this != hg.pskip)\r
+            hg = gravSub(hg);\r
+        return hg;\r
+    }\r
+\r
+    /**\r
+    * Return a string represenation of a body.\r
+    * @return a string represenation of a body.\r
+    **/\r
+    public char* toCString() {\r
+        char* result = cast(char*)malloc(140);\r
+        if (result == null) exit(1);\r
+        char* super_str = super.toCString();\r
+        sprintf(result, "Body %s", super_str);\r
+        free(super_str);\r
+        return result;\r
+    }\r
+}\r
+\r
+\r
+\r
+/// A class used to represent internal nodes in the tree\r
+final class Cell : Node {\r
+    // subcells per cell\r
+    const int NSUB = 1 << Vec3.NDIM;\r
+\r
+    /**\r
+    * The children of this cell node.  Each entry may contain either\r
+    * another cell or a body.\r
+    **/\r
+    Node[] subp;\r
+    Cell next;\r
+\r
+    this() {\r
+        subp.length = NSUB;\r
+    }\r
+\r
+    /**\r
+    * Descend Tree and insert particle.  We're at a cell so\r
+    * we need to move down the tree.\r
+    * @param p the body to insert into the tree\r
+    * @param xpic\r
+    * @param l\r
+    * @param tree the root of the tree\r
+    * @return the subtree with the new body inserted\r
+    **/\r
+    Node loadTree(Body p, Vec3 xpic, int l, Tree tree) {\r
+        // move down one level\r
+        int si = oldSubindex(xpic, l);\r
+        Node rt = subp[si];\r
+        if (rt !is null)\r
+            subp[si] = rt.loadTree(p, xpic, l >> 1, tree);\r
+        else\r
+            subp[si] = p;\r
+        return this;\r
+    }\r
+\r
+    /**\r
+    * Descend tree finding center of mass coordinates\r
+    * @return the mass of this node\r
+    **/\r
+    double hackcofm() {\r
+        double mq = 0.0;\r
+        Vec3 tmpPos = new Vec3();\r
+        Vec3 tmpv = new Vec3();\r
+        for (int i = 0; i < NSUB; i++) {\r
+            Node r = subp[i];\r
+            if (r !is null) {\r
+                double mr = r.hackcofm();\r
+                mq = mr + mq;\r
+                tmpv.multScalar(r.pos, mr);\r
+                tmpPos.addition(tmpv);\r
+            }\r
+        }\r
+        mass = mq;\r
+        pos = tmpPos;\r
+        pos.divScalar(mass);\r
+\r
+        return mq;\r
+    }\r
+\r
+    /// Recursively walk the tree to do hackwalk calculation\r
+    HG walkSubTree(double dsq, HG hg) {\r
+        if (subdivp(dsq, hg)) {\r
+            for (int k = 0; k < Cell.NSUB; k++) {\r
+                Node r = subp[k];\r
+                if (r !is null)\r
+                    hg = r.walkSubTree(dsq / 4.0, hg);\r
+            }\r
+        } else {\r
+            hg = gravSub(hg);\r
+        }\r
+        return hg;\r
+    }\r
+\r
+    /**\r
+    * Decide if the cell is too close to accept as a single term.\r
+    * @return true if the cell is too close.\r
+    **/\r
+    bool subdivp(double dsq, HG hg) {\r
+        Vec3 dr = new Vec3();\r
+        dr.subtraction(pos, hg.pos0);\r
+        double drsq = dr.dotProduct();\r
+\r
+        // in the original olden version drsp is multiplied by 1.0\r
+        return drsq < dsq;\r
+    }\r
+\r
+    /**\r
+    * Return a string represenation of a cell.\r
+    * @return a string represenation of a cell.\r
+    **/\r
+    public char* toCString() {\r
+        char* result = cast(char*)malloc(140);\r
+        if (result == null) exit(1);\r
+        char* super_str = super.toCString();\r
+        sprintf(result, "Cell %s", super_str);\r
+        free(super_str);\r
+        return result;\r
+    }\r
+}\r
+\r
+\r
+/**\r
+* A class that represents the root of the data structure used\r
+* to represent the N-bodies in the Barnes-Hut algorithm.\r
+**/\r
+final class Tree {\r
+    Vec3 rmin;\r
+    double rsize;\r
+\r
+    /// A reference to the root node.\r
+    Node root;\r
+\r
+    /// The complete list of bodies that have been created.\r
+    private Body bodyTab;\r
+\r
+    /// The complete list of bodies that have been created - in reverse.\r
+    private Body bodyTabRev;\r
+\r
+    /// Construct the root of the data structure that represents the N-bodies.\r
+    this() {\r
+        rmin = new Vec3();\r
+        rsize = -2.0 * -2.0;\r
+        root = null;\r
+        bodyTab = null;\r
+        bodyTabRev = null;\r
+        rmin.value(0, -2.0);\r
+        rmin.value(1, -2.0);\r
+        rmin.value(2, -2.0);\r
+    }\r
+\r
+    /**\r
+    * Return an enumeration of the bodies.\r
+    * @return an enumeration of the bodies.\r
+    **/\r
+    final Enumeration bodies() {\r
+        return bodyTab.elements();\r
+    }\r
+\r
+    /**\r
+    * Return an enumeration of the bodies - in reverse.\r
+    * @return an enumeration of the bodies - in reverse.\r
+    **/\r
+    final Enumeration bodiesRev() {\r
+        return bodyTabRev.elementsRev();\r
+    }\r
+\r
+    /**\r
+    * Create the testdata used in the benchmark.\r
+    * @param nbody the number of bodies to create\r
+    **/\r
+    final void createTestData(int nbody) {\r
+        Vec3 cmr = new Vec3();\r
+        Vec3 cmv = new Vec3();\r
+        Body head = new Body();\r
+        Body prev = head;\r
+\r
+        double rsc = 3.0 * PI / 16.0;\r
+        double vsc = sqrt(1.0 / rsc);\r
+        int seed = 123;\r
+        Random rnd = Random(seed);\r
+\r
+        for (int i = 0; i < nbody; i++) {\r
+            Body p = new Body();\r
+\r
+            prev.setNext(p);\r
+            prev = p;\r
+            p.mass = 1.0 / cast(double)nbody;\r
+\r
+            double t1 = rnd.uniform(0.0, 0.999);\r
+            t1 = pow(t1, (-2.0 / 3.0)) - 1.0;\r
+            double r = 1.0 / sqrt(t1);\r
+\r
+            double coeff = 4.0;\r
+            for (int k = 0; k < Vec3.NDIM; k++) {\r
+                r = rnd.uniform(0.0, 0.999);\r
+                p.pos.value(k, coeff * r);\r
+            }\r
+\r
+            cmr.addition(p.pos);\r
+\r
+            double x, y;\r
+            do {\r
+                x = rnd.uniform(0.0, 1.0);\r
+                y = rnd.uniform(0.0, 0.1);\r
+            } while (y > (x * x * pow(1.0 - x * x, 3.5)));\r
+\r
+            double v = sqrt(2.0) * x / pow(1 + r * r, 0.25);\r
+\r
+            double rad = vsc * v;\r
+            double rsq;\r
+            do {\r
+                for (int k = 0; k < Vec3.NDIM; k++)\r
+                    p.vel.value(k, rnd.uniform(-1.0, 1.0));\r
+                rsq = p.vel.dotProduct();\r
+            } while (rsq > 1.0);\r
+            double rsc1 = rad / sqrt(rsq);\r
+            p.vel.multScalar(rsc1);\r
+            cmv.addition(p.vel);\r
+        }\r
+\r
+        // mark end of list\r
+        prev.setNext(null);\r
+\r
+        // toss the dummy node at the beginning and set a reference to the first element\r
+        bodyTab = head.getNext();\r
+\r
+        cmr.divScalar(cast(double)nbody);\r
+        cmv.divScalar(cast(double)nbody);\r
+\r
+        prev = null;\r
+\r
+        for (Enumeration e = bodyTab.elements(); e.hasMoreElements();) {\r
+            Body b = cast(Body)e.nextElement();\r
+            b.pos.subtraction(cmr);\r
+            b.vel.subtraction(cmv);\r
+            b.setProcNext(prev);\r
+            prev = b;\r
+        }\r
+\r
+        // set the reference to the last element\r
+        bodyTabRev = prev;\r
+    }\r
+\r
+\r
+    /**\r
+    * Advance the N-body system one time-step.\r
+    * @param nstep the current time step\r
+    **/\r
+    void stepSystem(int nstep) {\r
+        // free the tree\r
+        root = null;\r
+\r
+        makeTree(nstep);\r
+\r
+        // compute the gravity for all the particles\r
+        for (Enumeration e = bodyTabRev.elementsRev(); e.hasMoreElements();) {\r
+            Body b = cast(Body)e.nextElement();\r
+            b.hackGravity(rsize, root);\r
+        }\r
+        vp(bodyTabRev, nstep);\r
+    }\r
+\r
+    /**\r
+    * Initialize the tree structure for hack force calculation.\r
+    * @param nsteps the current time step\r
+    **/\r
+    private void makeTree(int nstep) {\r
+        for (Enumeration e = bodiesRev(); e.hasMoreElements();) {\r
+            Body q = cast(Body)e.nextElement();\r
+            if (q.mass != 0.0) {\r
+                q.expandBox(this, nstep);\r
+                Vec3 xqic = intcoord(q.pos);\r
+                if (root is null) {\r
+                    root = q;\r
+                } else {\r
+                    root = root.loadTree(q, xqic, Node.IMAX >> 1, this);\r
+                }\r
+            }\r
+        }\r
+        root.hackcofm();\r
+    }\r
+\r
+    /**\r
+    * Compute integerized coordinates.\r
+    * @return the coordinates or null if rp is out of bounds\r
+    **/\r
+    final Vec3 intcoord(Vec3 vp) {\r
+        Vec3 xp = new Vec3();\r
+\r
+        double xsc = (vp.value(0) - rmin.value(0)) / rsize;\r
+        if (0.0 <= xsc && xsc < 1.0)\r
+            xp.value(0, floor(Node.IMAX * xsc));\r
+        else\r
+            return null;\r
+\r
+        xsc = (vp.value(1) - rmin.value(1)) / rsize;\r
+        if (0.0 <= xsc && xsc < 1.0)\r
+            xp.value(1, floor(Node.IMAX * xsc));\r
+        else\r
+            return null;\r
+\r
+        xsc = (vp.value(2) - rmin.value(2)) / rsize;\r
+        if (0.0 <= xsc && xsc < 1.0)\r
+            xp.value(2, floor(Node.IMAX * xsc));\r
+        else\r
+            return null;\r
+\r
+        return xp;\r
+    }\r
+\r
+    static final private void vp(Body p, int nstep) {\r
+        Vec3 dacc = new Vec3();\r
+        Vec3 dvel = new Vec3();\r
+        double dthf = 0.5 * BH.DTIME;\r
+\r
+        for (Enumeration e = p.elementsRev(); e.hasMoreElements();) {\r
+            Body b = cast(Body)e.nextElement();\r
+            Vec3 acc1 = b.newAcc.clone();\r
+            if (nstep > 0) {\r
+                dacc.subtraction(acc1, b.acc);\r
+                dvel.multScalar(dacc, dthf);\r
+                dvel.addition(b.vel);\r
+                b.vel = dvel.clone();\r
+            }\r
+\r
+            b.acc = acc1.clone();\r
+            dvel.multScalar(b.acc, dthf);\r
+\r
+            Vec3 vel1 = b.vel.clone();\r
+            vel1.addition(dvel);\r
+            Vec3 dpos = vel1.clone();\r
+            dpos.multScalar(BH.DTIME);\r
+            dpos.addition(b.pos);\r
+            b.pos = dpos.clone();\r
+            vel1.addition(dvel);\r
+            b.vel = vel1.clone();\r
+        }\r
+    }\r
+}\r
+\r
+\r
+final class BH {\r
+    /// The user specified number of bodies to create.\r
+    private static int nbody = 0;\r
+\r
+    /// The maximum number of time steps to take in the simulation\r
+    private static int nsteps = 10;\r
+\r
+    /// Should we print information messsages\r
+    private static bool printMsgs = false;\r
+\r
+    /// Should we print detailed results\r
+    private static bool printResults = false;\r
+\r
+    const double DTIME = 0.0125;\r
+    private const double TSTOP = 2.0;\r
+\r
+    public static final void main(char[][] args) {\r
+        parseCmdLine(args);\r
+\r
+        if (printMsgs)\r
+            printf("nbody = %d\n", nbody);\r
+\r
+        auto start0 = myclock();\r
+        Tree root = new Tree();\r
+        root.createTestData(nbody);\r
+        auto end0 = myclock();\r
+        if (printMsgs)\r
+              printf("Bodies created\n");\r
+\r
+        auto start1 = myclock();\r
+        double tnow = 0.0;\r
+        int i = 0;\r
+        while ((tnow < TSTOP + 0.1 * DTIME) && (i < nsteps)) {\r
+            root.stepSystem(i++);\r
+            tnow += DTIME;\r
+        }\r
+        auto end1 = myclock();\r
+\r
+        if (printResults) {\r
+            int j = 0;\r
+            for (Enumeration e = root.bodies(); e.hasMoreElements();) {\r
+                Body b = cast(Body)e.nextElement();\r
+                char* str_ptr = b.pos.toCString();\r
+                printf("body %d: %s\n", j++, str_ptr);\r
+                free(str_ptr);\r
+            }\r
+        }\r
+\r
+        if (printMsgs) {\r
+            printf("Build time %.2f\n", end0 - start0);\r
+            printf("Compute Time %.2f\n", end1 - start1);\r
+            printf("Total Time %.2f\n", end1 - start0);\r
+            printf("Done!\n");\r
+        }\r
+    }\r
+\r
+    private static final void parseCmdLine(char[][] args) {\r
+        int i = 1;\r
+        while (i < args.length && args[i][0] == '-') {\r
+            char[] arg = args[i++];\r
+\r
+            // check for options that require arguments\r
+            if (arg == "-b") {\r
+                if (i < args.length)\r
+                    nbody = toInt(args[i++]);\r
+                else\r
+                    throw new Exception("-l requires the number of levels");\r
+            } else if (arg == "-s") {\r
+                if (i < args.length)\r
+                    nsteps = toInt(args[i++]);\r
+                else\r
+                    throw new Exception("-l requires the number of levels");\r
+            } else if (arg == "-m") {\r
+                printMsgs = true;\r
+            } else if (arg == "-p") {\r
+                printResults = true;\r
+            } else if (arg == "-h") {\r
+                usage();\r
+            }\r
+        }\r
+\r
+        if (nbody == 0)\r
+            usage();\r
+    }\r
+\r
+    /// The usage routine which describes the program options.\r
+    private static final void usage() {\r
+        fprintf(stderr, "usage: BH -b <size> [-s <steps>] [-p] [-m] [-h]\n");\r
+        fprintf(stderr, "  -b the number of bodies\n");\r
+        fprintf(stderr, "  -s the max. number of time steps (default=10)\n");\r
+        fprintf(stderr, "  -p (print detailed results)\n");\r
+        fprintf(stderr, "  -m (print information messages\n");\r
+        exit(0);\r
+    }\r
+}\r
+\r
+\r
+void main(char[][] args) {\r
+    BH.main(args);\r
+}\r
similarity index 100%
rename from micro/big_arrays.d
rename to micro/bigarr.d
diff --git a/micro/bisort.d b/micro/bisort.d
new file mode 100644 (file)
index 0000000..6425535
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+A Java implementation of the bisort Olden benchmark.
+The Olden benchmark implements a Bitonic Sort as described in:
+
+G. Bilardi and A. Nicolau, "Adaptive Bitonic Sorting: An optimal parallel
+algorithm for shared-memory machines." SIAM J. Comput. 18(2):216-228, 1998.
+
+The benchmarks sorts N numbers where N is a power of 2. If the user provides
+an input value that is not a power of 2, then we use the nearest power of
+2 value that is less than the input value.
+
+Converted to D and obtimized by leonardo maffi, V.1.0, Oct 31 2009.
+
+Removed output unless an option is passed by Leandro Lucarella, 2010-08-04.
+Downloaded from http://www.fantascienza.net/leonardo/js/
+                http://www.fantascienza.net/leonardo/js/dolden_bisort.zip
+*/
+
+version (Tango) {
+    import tango.stdc.stdio: printf, fprintf, stderr;
+    import tango.stdc.stdlib: exit;
+    import Integer = tango.text.convert.Integer;
+    alias Integer.parse toInt;
+    import tango.stdc.time: CLOCKS_PER_SEC, clock;
+} else {
+    import std.c.stdio: printf, fprintf, stderr;
+    import std.c.stdlib: exit;
+    import std.conv: toInt;
+    import std.c.time: CLOCKS_PER_SEC, clock;
+}
+
+
+double myclock() {
+    return clock() / cast(float)CLOCKS_PER_SEC;
+}
+
+
+/**
+ * A class that represents a value to be sorted by the <tt>BiSort</tt>
+ * algorithm.    We represents a values as a node in a binary tree.
+ **/
+final class Value {
+    private int value;
+    private Value left, right;
+
+    const bool FORWARD = false;
+    const bool BACKWARD = true;
+
+    // These are used by the Olden benchmark random no. generator
+    private const int CONST_m1 = 10000;
+    private const int CONST_b = 31415821;
+    const int RANGE = 100;
+
+    /**
+     * Constructor for a node representing a value in the bitonic sort tree.
+     * @param v the integer value which is the sort key
+     **/
+    this(int v) {
+        value = v;
+        left = right = null;
+    }
+
+
+    /**
+     * Create a random tree of value to be sorted using the bitonic sorting algorithm.
+     *
+     * @param size the number of values to create.
+     * @param seed a random number generator seed value
+     * @return the root of the (sub) tree.
+     **/
+    static Value createTree(int size, int seed) {
+        if (size > 1) {
+            seed = random(seed);
+            int next_val = seed % RANGE;
+
+            Value retval = new Value(next_val);
+            retval.left = createTree(size/2, seed);
+            retval.right = createTree(size/2, skiprand(seed, size+1));
+            return retval;
+        } else {
+            return null;
+        }
+    }
+
+
+    /**
+     * Perform a bitonic sort based upon the Bilardi and Nicolau algorithm.
+     *
+     * @param spr_val the "spare" value in the algorithm.
+     * @param direction the direction of the sort (forward or backward)
+     * @return the new "spare" value.
+     **/
+    int bisort(int spr_val, bool direction) {
+        if (left is null) {
+            if ((value > spr_val) ^ direction) {
+                int tmpval = spr_val;
+                spr_val = value;
+                value = tmpval;
+            }
+        } else {
+            int val = value;
+            value = left.bisort(val, direction);
+            bool ndir = !direction;
+            spr_val = right.bisort(spr_val, ndir);
+            spr_val = bimerge(spr_val, direction);
+        }
+        return spr_val;
+    }
+
+
+    /**
+     * Perform the merge part of the bitonic sort. The merge part does
+     * the actualy sorting.
+     * @param spr_val the "spare" value in the algorithm.
+     * @param direction the direction of the sort (forward or backward)
+     * @return the new "spare" value
+     **/
+    int bimerge(int spr_val, bool direction) {
+        int rv = value;
+        Value pl = left;
+        Value pr = right;
+
+        bool rightexchange = (rv > spr_val) ^ direction;
+        if (rightexchange) {
+            value = spr_val;
+            spr_val = rv;
+        }
+
+        while (pl !is null) {
+            int lv = pl.value;
+            Value pll = pl.left;
+            Value plr = pl.right;
+            rv = pr.value;
+            Value prl = pr.left;
+            Value prr = pr.right;
+
+            bool elementexchange = (lv > rv) ^ direction;
+            if (rightexchange) {
+                if (elementexchange) {
+                    pl.swapValRight(pr);
+                    pl = pll;
+                    pr = prl;
+                } else {
+                    pl = plr;
+                    pr = prr;
+                }
+            } else {
+                if (elementexchange) {
+                    pl.swapValLeft(pr);
+                    pl = plr;
+                    pr = prr;
+                } else {
+                    pl = pll;
+                    pr = prl;
+                }
+            }
+        }
+
+        if (left !is null) {
+            value = left.bimerge(value, direction);
+            spr_val = right.bimerge(spr_val, direction);
+        }
+        return spr_val;
+    }
+
+
+    /**
+     * Swap the values and the right subtrees.
+     * @param n the other subtree involved in the swap.
+     **/
+    void swapValRight(Value n) {
+        int tmpv = n.value;
+        Value tmpr = n.right;
+
+        n.value = value;
+        n.right = right;
+
+        value = tmpv;
+        right = tmpr;
+    }
+
+
+    /**
+     * Swap the values and the left subtrees.
+     * @param n the other subtree involved in the swap.
+     **/
+    void swapValLeft(Value n) {
+        int tmpv = n.value;
+        Value tmpl = n.left;
+
+        n.value = value;
+        n.left = left;
+
+        value = tmpv;
+        left = tmpl;
+    }
+
+
+    /**
+     * Print out the nodes in the binary tree in infix order.
+     **/
+    void inOrder() {
+        if (left !is null)
+            left.inOrder();
+        printf("%d\n", value);
+        if (right !is null)
+            right.inOrder();
+    }
+
+
+    /**
+     * A random generator.    The original Olden benchmark uses its
+     * own random generator.    We use the same one in the Java version.
+     * @return the next random number in the sequence.
+     **/
+    private static int mult(int p, int q) {
+        int p1 = p / CONST_m1;
+        int p0 = p % CONST_m1;
+        int q1 = q / CONST_m1;
+        int q0 = q % CONST_m1;
+        return ((p0 * q1 + p1 * q0) % CONST_m1) * CONST_m1 + p0 * q0;
+    }
+
+
+    /**
+     * A routine to skip the next <i>n</i> random numbers.
+     * @param seed the current random no. seed
+     * @param n the number of numbers to skip
+     **/
+    private static int skiprand(int seed, int n) {
+        for (; n != 0; n--)
+            seed = random(seed);
+        return seed;
+    }
+
+
+    /**
+     * Return a random number based upon the seed value.
+     * @param seed the random number seed value
+     * @return a random number based upon the seed value.
+     **/
+    static int random(int seed) {
+        int tmp = mult(seed, CONST_b) + 1;
+        return tmp;
+    }
+}
+
+
+final public class BiSort {
+    private static int size = 0; // The number of values to sort.
+    private static bool printMsgs = false; // Print information messages
+    private static bool printResults = false; // Print the tree after each step
+
+
+    /**
+     * The main routine which creates a tree and sorts it a couple of times.
+     * @param args the command line arguments
+     **/
+    public static final void main(char[][] args) {
+        parseCmdLine(args);
+
+        if (printMsgs)
+            printf("Bisort with %d values\n", nextPow2(size+1) - 1);
+
+        auto start2 = myclock();
+        Value tree = Value.createTree(size, 12345768);
+        auto end2 = myclock();
+        int sval = Value.random(245867) % Value.RANGE;
+
+        if (printResults) {
+            tree.inOrder();
+            printf("%d\n", sval);
+        }
+
+        if (printMsgs)
+            printf("Beginning bitonic sort\n");
+
+        auto start0 = myclock();
+        sval = tree.bisort(sval, Value.FORWARD);
+        auto end0 = myclock();
+
+        if (printResults) {
+            tree.inOrder();
+            printf("%d\n", sval);
+        }
+
+        auto start1 = myclock();
+        sval = tree.bisort(sval, Value.BACKWARD);
+        auto end1 = myclock();
+
+        if (printResults) {
+            tree.inOrder();
+            printf("%d\n", sval);
+        }
+
+        if (printMsgs) {
+            printf("Creation time: %f\n", end2 - start2);
+            printf("Time to sort forward = %f\n", end0 - start0);
+            printf("Time to sort backward = %f\n", end1 - start1);
+            printf("Total: %f\n", end1 - start0);
+            printf("Done!\n");
+        }
+    }
+
+
+    /**
+     * Parse the command line options.
+     * @param args the command line options.
+     **/
+    private static final void parseCmdLine(char[][] args) {
+        int i = 1;
+        char[] arg;
+
+        while (i < args.length && args[i][0] == '-') {
+            arg = args[i++];
+
+            // check for options that require arguments
+            if (arg == "-s") {
+                if (i < args.length) {
+                    size = toInt(args[i++]);
+                } else {
+                    throw new Exception("-l requires the number of levels");
+                }
+            } else if (arg == "-m") {
+                printMsgs = true;
+            } else if (arg == "-p") {
+                printResults = true;
+            } else if (arg == "-h") {
+                usage();
+            }
+        }
+        if (size == 0)
+            usage();
+    }
+
+
+    /**
+     * The usage routine which describes the program options.
+     **/
+    private static final void usage() {
+        fprintf(stderr, "usage: bisort_d -s <size> [-p] [-i] [-h]\n");
+        fprintf(stderr, "  -s the number of values to sort\n");
+        fprintf(stderr, "  -m (print informative messages)\n");
+        fprintf(stderr, "  -p (print the binary tree after each step)\n");
+        fprintf(stderr, "  -h (print this message)\n");
+        exit(0);
+    }
+
+
+    private static /*unsigned*/ int nextPow2(/*unsigned*/ int x) {
+        if (x < 0)
+            throw new Exception("x must be >= 0");
+        x -= 1;
+        x |= x >>  1;
+        x |= x >>  2;
+        x |= x >>  4;
+        x |= x >>  8;
+        x |= x >> 16;
+        return x + 1;
+    }
+}
+
+
+void main(char[][] args) {
+    BiSort.main(args);
+}
diff --git a/micro/conalloc.d b/micro/conalloc.d
new file mode 100644 (file)
index 0000000..fba0f20
--- /dev/null
@@ -0,0 +1,50 @@
+// Written by Leandro Lucarella
+//
+// The goal of this program is to do very CPU intensive work in threads
+
+import tango.core.Thread: Thread;
+import tango.core.sync.Atomic: atomicStore, atomicLoad, atomicAdd;
+import tango.io.device.File: File;
+import tango.util.digest.Sha512: Sha512;
+import tango.util.Convert: to;
+
+auto N = 100;
+auto NT = 2;
+ubyte[] BYTES;
+int running; // Atomic
+
+void main(char[][] args)
+{
+       auto fname = args[0];
+       if (args.length > 3)
+               fname = args[3];
+       if (args.length > 2)
+               NT = to!(int)(args[2]);
+       if (args.length > 1)
+               N = to!(int)(args[1]);
+       N /= NT;
+       atomicStore(running, NT);
+       BYTES = cast(ubyte[]) File.get(fname);
+       auto threads = new Thread[NT];
+       foreach(ref thread; threads) {
+               thread = new Thread(&doSha);
+               thread.start();
+       }
+       while (atomicLoad(running)) {
+               auto a = new void[](BYTES.length / 4);
+               a[] = cast(void[]) BYTES[];
+               Thread.yield();
+       }
+       foreach(thread; threads)
+               thread.join();
+}
+
+void doSha()
+{
+       for (size_t i = 0; i < N; i++) {
+               auto sha = new Sha512;
+               sha.update(BYTES);
+       }
+       atomicAdd(running, -1);
+}
+
diff --git a/micro/concpu.d b/micro/concpu.d
new file mode 100644 (file)
index 0000000..6a123b2
--- /dev/null
@@ -0,0 +1,50 @@
+// Written by Leandro Lucarella
+//
+// The goal of this program is to do very CPU intensive work in threads
+
+import tango.core.Thread: Thread;
+import tango.core.sync.Atomic: atomicStore, atomicLoad, atomicAdd;
+import tango.io.device.File: File;
+import tango.util.digest.Sha512: Sha512;
+import tango.util.Convert: to;
+
+auto N = 100;
+auto NT = 2;
+ubyte[] BYTES;
+int running; // Atomic
+
+void main(char[][] args)
+{
+       auto fname = args[0];
+       if (args.length > 3)
+               fname = args[3];
+       if (args.length > 2)
+               NT = to!(int)(args[2]);
+       if (args.length > 1)
+               N = to!(int)(args[1]);
+       N /= NT;
+       atomicStore(running, NT);
+       BYTES = cast(ubyte[]) File.get(fname);
+       auto threads = new Thread[NT];
+       foreach(ref thread; threads) {
+               thread = new Thread(&doSha);
+               thread.start();
+       }
+       while (atomicLoad(running)) {
+               auto a = new void[](BYTES.length / 4);
+               a[] = cast(void[]) BYTES[];
+               Thread.yield();
+       }
+       foreach(thread; threads)
+               thread.join();
+}
+
+void doSha()
+{
+       auto sha = new Sha512;
+       for (size_t i = 0; i < N; i++) {
+               sha.update(BYTES);
+       }
+       atomicAdd(running, -1);
+}
+
diff --git a/micro/em3d.d b/micro/em3d.d
new file mode 100644 (file)
index 0000000..349f6a7
--- /dev/null
@@ -0,0 +1,468 @@
+/**
+ * Java implementation of the <tt>em3d</tt> Olden benchmark.  This Olden
+ * benchmark models the propagation of electromagnetic waves through
+ * objects in 3 dimensions. It is a simple computation on an irregular
+ * bipartite graph containing nodes representing electric and magnetic
+ * field values.
+ *
+ * <p><cite>
+ * D. Culler, A. Dusseau, S. Goldstein, A. Krishnamurthy, S. Lumetta, T. von
+ * Eicken and K. Yelick. "Parallel Programming in Split-C".  Supercomputing
+ * 1993, pages 262-273.
+ * </cite>
+ *
+ * Java code converted to D by leonardo maffi, V.1.0, Oct 25 2009.
+ *
+ * Removed output unless an option is passed by Leandro Lucarella, 2010-08-04.
+ * Downloaded from http://www.fantascienza.net/leonardo/js/
+ *                 http://www.fantascienza.net/leonardo/js/dolden_em3d.zip
+ **/
+
+
+version (Tango) {
+    import tango.stdc.stdio: printf, sprintf;
+    import tango.stdc.stdlib: exit;
+    import tango.stdc.time: CLOCKS_PER_SEC, clock;
+
+    import Integer = tango.text.convert.Integer;
+    alias Integer.parse toInt;
+} else {
+    import std.c.stdio: printf, sprintf;
+    import std.c.stdlib: exit;
+    import std.c.time: CLOCKS_PER_SEC, clock;
+
+    version (D_Version2) {
+        import std.conv: to;
+        alias to!(int, char[]) toInt;
+    } else {
+        import std.conv: toInt;
+    }
+}
+
+
+double myclock() {
+    return clock() / cast(double)CLOCKS_PER_SEC;
+}
+
+
+/**
+Basic uniform random generator: Minimal Standard in Park and
+Miller (1988): "Random Number Generators: Good Ones Are Hard to
+Find", Comm. of the ACM, 31, 1192-1201.
+Parameters: m = 2^31-1, a=48271.
+
+Adapted from Pascal code by Jesper Lund:
+http://www.gnu-pascal.de/crystal/gpc/en/mail1390.html
+*/
+final class Random {
+    const int m = int.max;
+    const int a = 48_271;
+    const int q = m / a;
+    const int r = m % a;
+    public int seed;
+
+    this(int the_seed) {
+        this.seed = the_seed;
+    }
+
+    public double nextDouble() {
+        int k = seed / q;
+        seed = a * (seed - k * q) - r * k;
+        if (seed < 1)
+            seed += m;
+        return cast(double)seed / m;
+    }
+
+    public int nextInt(int max) {
+        int n = max + 1;
+        int k = cast(int)(n * this.nextDouble());
+        return (k == n) ? k - 1 : k;
+    }
+}
+
+
+/**
+ * This class implements nodes (both E- and H-nodes) of the EM graph. Sets
+ * up random neighbors and propagates field values among neighbors.
+ */
+final class Node
+{
+  /**
+   * The value of the node.
+   **/
+  double value;
+  /**
+   * The next node in the list.
+   **/
+  private Node next;
+  /**
+   * Array of nodes to which we send our value.
+   **/
+  Node[] toNodes;
+  /**
+   * Array of nodes from which we receive values.
+   **/
+  Node[] fromNodes;
+  /**
+   * Coefficients on the fromNodes edges
+   **/
+  double[] coeffs;
+  /**
+   * The number of fromNodes edges
+   **/
+  int fromCount;
+  /**
+   * Used to create the fromEdges - keeps track of the number of edges that have
+   * been added
+   **/
+  int fromLength;
+
+  /**
+   * A random number generator.
+   **/
+  private static Random rand;
+
+  /**
+   * Initialize the random number generator
+   **/
+  public static void initSeed(long seed)
+  {
+    rand = new Random(seed);
+  }
+
+  /**
+   * Constructor for a node with given `degree'.   The value of the
+   * node is initialized to a random value.
+   **/
+  this(int degree)
+  {
+    value = rand.nextDouble();
+    // create empty array for holding toNodes
+    toNodes = new Node[degree];
+
+    next = null;
+    fromNodes = null;
+    coeffs = null;
+    fromCount = 0;
+    fromLength = 0;
+  }
+
+  /**
+   * Create the linked list of E or H nodes.  We create a table which is used
+   * later to create links among the nodes.
+   * @param size the no. of nodes to create
+   * @param degree the out degree of each node
+   * @return a table containing all the nodes.
+   **/
+  static Node[] fillTable(int size, int degree)
+  {
+    Node[] table = new Node[size];
+
+    Node prevNode = new Node(degree);
+    table[0] = prevNode;
+    for (int i = 1; i < size; i++) {
+      Node curNode = new Node(degree);
+      table[i] = curNode;
+      prevNode.next = curNode;
+      prevNode = curNode;
+    }
+    return table;
+  }
+
+  /**
+   * Create unique `degree' neighbors from the nodes given in nodeTable.
+   * We do this by selecting a random node from the give nodeTable to
+   * be neighbor. If this neighbor has been previously selected, then
+   * a different random neighbor is chosen.
+   * @param nodeTable the list of nodes to choose from.
+   **/
+  void makeUniqueNeighbors(Node[] nodeTable)
+  {
+    for (int filled = 0; filled < toNodes.length; filled++) {
+      int k;
+      Node otherNode;
+
+      do {
+    // generate a random number in the correct range
+    int index = rand.nextInt(nodeTable.length - 1);
+
+    // find a node with the random index in the given table
+    otherNode = nodeTable[index];
+
+    for (k = 0; k < filled; k++) {
+      if (otherNode == toNodes[k]) break; // fixed a bug of the original Java code
+    }
+      } while (k < filled);
+
+      // other node is definitely unique among "filled" toNodes
+      toNodes[filled] = otherNode;
+
+      // update fromCount for the other node
+      otherNode.fromCount++;
+    }
+  }
+
+  /**
+   * Allocate the right number of FromNodes for this node. This
+   * step can only happen once we know the right number of from nodes
+   * to allocate. Can be done after unique neighbors are created and known.
+   *
+   * It also initializes random coefficients on the edges.
+   **/
+  void makeFromNodes()
+  {
+    fromNodes = new Node[fromCount]; // nodes fill be filled in later
+    coeffs = new double[fromCount];
+  }
+
+  /**
+   * Fill in the fromNode field in "other" nodes which are pointed to
+   * by this node.
+   **/
+  void updateFromNodes()
+  {
+    for (int i = 0; i < toNodes.length; i++) {
+      Node otherNode = toNodes[i];
+      int count = otherNode.fromLength++;
+      otherNode.fromNodes[count] = this;
+      otherNode.coeffs[count] = rand.nextDouble();
+    }
+  }
+
+  /**
+   * Get the new value of the current node based on its neighboring
+   * from_nodes and coefficients.
+   **/
+  void computeNewValue()
+  {
+    for (int i = 0; i < fromCount; i++) {
+      value -= coeffs[i] * fromNodes[i].value;
+    }
+  }
+
+  int opApply(int delegate(ref Node) dg) {
+    int result;
+    for (Node current = this; current !is null; current = current.next) {
+      result = dg(current);
+      if (result)
+        break;
+    }
+    return result;
+  }
+
+  public char* toCString()
+  {
+    static char[256] repr;
+    sprintf(repr.ptr, "value %.17f, from_count %d", value, fromCount);
+    return repr.ptr;
+  }
+}
+
+
+/**
+ * A class that represents the irregular bipartite graph used in
+ * EM3D.  The graph contains two linked structures that represent the
+ * E nodes and the N nodes in the application.
+ **/
+final class BiGraph
+{
+  /**
+   * Nodes that represent the electrical field.
+   **/
+  Node eNodes;
+  /**
+   * Nodes that representhe the magnetic field.
+   **/
+  Node hNodes;
+
+  /**
+   * Construct the bipartite graph.
+   * @param e the nodes representing the electric fields
+   * @param h the nodes representing the magnetic fields
+   **/
+  this(Node e, Node h)
+  {
+    eNodes = e;
+    hNodes = h;
+  }
+
+  /**
+   * Create the bi graph that contains the linked list of
+   * e and h nodes.
+   * @param numNodes the number of nodes to create
+   * @param numDegree the out-degree of each node
+   * @param verbose should we print out runtime messages
+   * @return the bi graph that we've created.
+   **/
+  static BiGraph create(int numNodes, int numDegree, bool verbose)
+  {
+    Node.initSeed(783);
+
+    // making nodes (we create a table)
+    if (verbose) printf("making nodes (tables in orig. version)\n");
+    Node[] hTable = Node.fillTable(numNodes, numDegree);
+    Node[] eTable = Node.fillTable(numNodes, numDegree);
+
+    // making neighbors
+    if (verbose) printf("updating from and coeffs\n");
+    foreach (n; hTable[0])
+      n.makeUniqueNeighbors(eTable);
+    foreach (n; eTable[0])
+      n.makeUniqueNeighbors(hTable);
+
+    // Create the fromNodes and coeff field
+    if (verbose) printf("filling from fields\n");
+    foreach (n; hTable[0])
+      n.makeFromNodes();
+    foreach (n; eTable[0])
+      n.makeFromNodes();
+
+    // Update the fromNodes
+    foreach (n; hTable[0])
+      n.updateFromNodes();
+    foreach (n; eTable[0])
+      n.updateFromNodes();
+
+    BiGraph g = new BiGraph(eTable[0], hTable[0]);
+    return g;
+  }
+
+  /**
+  * Update the field values of e-nodes based on the values of
+  * neighboring h-nodes and vice-versa.
+  **/
+  void compute() {
+    foreach (n; eNodes)
+      n.computeNewValue();
+    foreach (n; hNodes)
+      n.computeNewValue();
+  }
+
+  /**
+  * Print out the values of the e and h nodes.
+  **/
+  public void print() {
+    foreach (n; eNodes)
+      printf("E: %s\n", n.toCString());
+    foreach (n; hNodes)
+      printf("H: %s\n", n.toCString());
+    printf("\n");
+  }
+}
+
+public class Em3d1
+{
+  /**
+   * The number of nodes (E and H)
+   **/
+  private static int numNodes = 0;
+  /**
+   * The out-degree of each node.
+   **/
+  private static int numDegree = 0;
+  /**
+   * The number of compute iterations
+   **/
+  private static int numIter = 1;
+  /**
+   * Should we print the results and other runtime messages
+   **/
+  private static bool printResult = false;
+  /**
+   * Print information messages?
+   **/
+  private static bool printMsgs = false;
+
+  /**
+   * The main roitine that creates the irregular, linked data structure
+   * that represents the electric and magnetic fields and propagates the
+   * waves through the graph.
+   * @param args the command line arguments
+   **/
+  public static final void main(char[] args[])
+  {
+    parseCmdLine(args);
+
+    if (printMsgs)
+      printf("Initializing em3d random graph...\n");
+    auto start0 = myclock();
+    BiGraph graph = BiGraph.create(numNodes, numDegree, printResult);
+    auto end0 = myclock();
+
+    // compute a single iteration of electro-magnetic propagation
+    if (printMsgs)
+      printf("Propagating field values for %d iteration(s)...\n", numIter);
+    auto start1 = myclock();
+    for (int i = 0; i < numIter; i++) {
+      graph.compute();
+    }
+    auto end1 = myclock();
+
+    // print current field values
+    if (printResult)
+      graph.print();
+
+    if (printMsgs) {
+      printf("EM3D build time %.2f\n", end0 - start0);
+      printf("EM3D compute time %.2f\n", end1 - start1);
+      printf("EM3D total time %.2f\n", end1 - start0);
+      printf("Done!\n");
+    }
+  }
+
+
+  /**
+   * Parse the command line options.
+   * @param args the command line options.
+   **/
+  private static final void parseCmdLine(char[] args[])
+  {
+    int i = 1;
+    char[] arg;
+
+    while (i < args.length && args[i][0] == '-') {
+      arg = args[i++];
+
+      // check for options that require arguments
+      if (arg == "-n") {
+        if (i < args.length) {
+          numNodes = toInt(args[i++]);
+        } else throw new Exception("-n requires the number of nodes");
+      } else if (arg == "-d") {
+    if (i < args.length) {
+      numDegree = toInt(args[i++]);
+    } else throw new Exception("-d requires the out degree");
+      } else if (arg == "-i") {
+    if (i < args.length) {
+      numIter = toInt(args[i++]);
+    } else throw new Exception("-i requires the number of iterations");
+      } else if (arg == "-p") {
+        printResult = true;
+      } else if (arg == "-m") {
+        printMsgs = true;
+      } else if (arg == "-h") {
+    usage();
+      }
+    }
+    if (numNodes == 0 || numDegree == 0) usage();
+  }
+
+  /**
+  * The usage routine which describes the program options.
+  **/
+    private static final void usage() {
+    printf("usage: em3d -n <nodes> -d <degree> [-p] [-m] [-h]\n");
+    printf("    -n the number of nodes\n");
+    printf("    -d the out-degree of each node\n");
+    printf("    -i the number of iterations\n");
+    printf("    -p (print detailed results)\n");
+    printf("    -m (print informative messages)\n");
+    printf("    -h (this message)\n");
+    exit(0);
+  }
+}
+
+
+void main(char[][] args) {
+    Em3d1.main(args);
+}
similarity index 100%
rename from micro/multicore.d
rename to micro/mcore.d
diff --git a/micro/rnd_data_2.d b/micro/rnd_data_2.d
deleted file mode 100644 (file)
index 545d588..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-// Written by Kevin Bealer <kevinbealer@gmail.com>
-// Found at http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.announce&article_id=6978
-// Sightly modified by Leandro Lucarella <llucax@gmail.com>
-// (changed not to print anything and lower the total iterations; ported to
-// Tango)
-
-// Total residency should be ~160 MiB, but it usually increases a lot because
-// of false positives (probably in the static memory area)
-
-import tango.math.random.Random;
-
-const N = 2_000_000;
-const L = 20;
-const I = 50; // original: 200
-
-int main(char[][] args)
-{
-     int[][] stuff;
-
-     stuff.length = L;
-
-     auto rand = new Random();
-
-     for(int i = 0; i < I; i++) {
-         int[] arr = new int[N];
-
-         for(int j = 0; j < arr.length; j++) {
-             rand(arr[j]);
-         }
-
-         int zig = i;
-         if (zig >= stuff.length)
-             zig = rand.uniform!(int) % stuff.length;
-
-         stuff[zig] = arr;
-     }
-
-     return 0;
-}
-
similarity index 52%
rename from micro/rnd_data.d
rename to micro/rnddata.d
index aa713553bfbf8da02a8396f605eca6acf49e3802..c0d2294ed249faadbc4a9e60f5bd7994a0f671dd 100644 (file)
@@ -5,20 +5,28 @@
 
 import tango.math.random.Random;
 
-const IT = 50_000;
+const IT = 125; // number of iterations, each creates an object
+const BYTES = 1_000_000; // ~1MiB per object
+const N = 50; // ~50MiB of initial objects
+
+class C
+{
+       C c; // makes the compiler not set NO_SCAN
+       long[BYTES/long.sizeof] data;
+}
 
 void main() {
-       // The real memory use, ~55 KiB (original: ~20 MiB)
-       uint[] data;
-       data.length = 10_000; // original: 5_000_000
        auto rand = new Random();
-       foreach (ref x; data)
-               rand(x);
+       C[] objs;
+               objs.length = N;
+       foreach (ref o; objs) {
+               o = new C;
+               foreach (ref x; o.data)
+                       rand(x);
+       }
        for (int i = 0; i < IT; ++i) {
-               // simulate reading a few kb of data (14 KiB +/- 10 KiB)
-               uint[] incoming;
-               incoming.length = 1000 + rand.uniform!(uint) % 5000;
-               foreach (ref x; incoming)
+               C o = new C;
+               foreach (ref x; o.data)
                        rand(x);
                // do something with the data...
        }
diff --git a/micro/sbtree.d b/micro/sbtree.d
new file mode 100644 (file)
index 0000000..3f8c904
--- /dev/null
@@ -0,0 +1,63 @@
+// Written by Andrey Khropov <andkhropov_nosp@m_mtu-net.ru>
+// Found at http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=43991
+// Modified by Leandro Lucarella
+// (ported to Tango, fixed some stylistic issues)
+
+import tango.util.Convert;
+
+alias char[] string;
+
+int main(string[] args)
+{
+   int N = args.length > 1 ? to!(int)(args[1]) : 1;
+
+   int minDepth = 4;
+   int maxDepth = (minDepth + 2) > N ? minDepth + 2 : N;
+   int stretchDepth = maxDepth + 1;
+
+   int check = TreeNode.BottomUpTree(0, stretchDepth).ItemCheck;
+   TreeNode longLivedTree = TreeNode.BottomUpTree(0, maxDepth);
+
+   for (int depth = minDepth; depth <= maxDepth; depth += 2) {
+      int iterations = 1 << (maxDepth - depth + minDepth);
+      check = 0;
+
+      for (int i = 1; i <= iterations; i++) {
+         check += TreeNode.BottomUpTree(i, depth).ItemCheck;
+         check += TreeNode.BottomUpTree(-i, depth).ItemCheck;
+      }
+
+   }
+
+   return 0;
+}
+
+class TreeNode
+{
+   TreeNode left, right;
+   int item;
+
+   this(int item, TreeNode left = null, TreeNode right = null)
+   {
+      this.item = item;
+      this.left = left;
+      this.right = right;
+   }
+
+   static TreeNode BottomUpTree(int item, int depth)
+   {
+      if (depth > 0)
+         return new TreeNode(item,
+               BottomUpTree(2 * item - 1, depth - 1),
+               BottomUpTree(2 * item, depth - 1));
+      return new TreeNode(item);
+   }
+
+   int ItemCheck()
+   {
+      if (left)
+         return item + left.ItemCheck() - right.ItemCheck();
+      return item;
+   }
+}
+
diff --git a/micro/shootout_binarytrees.d b/micro/shootout_binarytrees.d
deleted file mode 100644 (file)
index 7663458..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// Written by Andrey Khropov <andkhropov_nosp@m_mtu-net.ru>
-// Found at http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=43991
-// Modified by Leandro Lucarella
-// (ported to Tango)
-
-import tango.util.Convert;
-
-alias char[] string;
-
-int main(string[] args)
-{
-       int N = args.length > 1 ? to!(int)(args[1]) : 1;
-
-       int minDepth = 4;
-       int maxDepth = (minDepth + 2) > N ? minDepth + 2 : N;
-       int stretchDepth = maxDepth + 1;
-
-       TreeNode stretchTree = TreeNode.BottomUpTree(0, stretchDepth);
-
-       TreeNode longLivedTree = TreeNode.BottomUpTree(0, maxDepth);
-
-       int depth;
-       for(depth = minDepth; depth <= maxDepth; depth += 2)
-       {
-               int check, iterations = 1 << (maxDepth - depth + minDepth);
-
-               for(int i = 1; i <= iterations; i++)
-               {
-                       auto tempTree = TreeNode.BottomUpTree(i, depth);
-                       check += tempTree.ItemCheck;
-                       //delete tempTree;
-
-                       tempTree = TreeNode.BottomUpTree(-i, depth);
-                       check += tempTree.ItemCheck;
-                       //delete tempTree;
-               }
-
-       }
-
-       return 0;
-}
-
-class TreeNode
-{
-public:
-       this(int item, TreeNode left = null, TreeNode right = null)
-       {
-               this.item  = item;
-               this.left  = left;
-               this.right = right;
-       }
-
-       static TreeNode BottomUpTree(int item, int depth)
-       {
-               if(depth > 0)
-                       return new TreeNode(item
-                                       ,BottomUpTree(2 * item - 1, depth - 1)
-                                       ,BottomUpTree(2 * item, depth - 1));
-               return new TreeNode(item);
-       }
-
-       int ItemCheck()
-       {
-               if(left)
-                       return item + left.ItemCheck() - right.ItemCheck();
-               return item;
-       }
-private:
-       TreeNode            left, right;
-       int                 item;
-}
-
diff --git a/micro/tree.d b/micro/tree.d
deleted file mode 100644 (file)
index a5179a3..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-// Written by Piotr Modzelewski <http://petermodzelewski.blogspot.com/>
-// Found at http://www.dsource.org/projects/tango/wiki/GCBenchmark
-
-class TreeNode {
-       int item;
-       TreeNode left, right;
-
-       this(int item, TreeNode left=null, TreeNode right=null) {
-               this.item = item;
-               this.left = left;
-               this.right = right;
-       }
-
-       int check() {
-               return left is null ? item : item + left.check - right.check;
-       }
-}
-
-TreeNode makeTree(int item, int depth) {
-       if (depth > 0)
-               return new TreeNode(item, makeTree(2*item-1, depth-1),
-                               makeTree(2*item, depth-1));
-       else
-               return new TreeNode(item);
-}
-
-void main(char[][] args) {
-       const minDepth = 5;
-       int n = 15;
-       int maxDepth = (minDepth + 2) > n ? minDepth + 2 : n;
-
-       int check = makeTree(0, maxDepth + 1).check;
-
-       auto longLivedTree = makeTree(0, maxDepth);
-
-       for (int depth = minDepth; depth <= maxDepth; depth += 2) {
-               int iterations = 1 << (maxDepth - depth + minDepth);
-               check = 0;
-
-               for (int i = 1; i <= iterations; i++)
-                       check += (makeTree(i, depth)).check
-                                       + (makeTree(-i, depth)).check;
-       }
-
-}
-
diff --git a/micro/tsp.d b/micro/tsp.d
new file mode 100644 (file)
index 0000000..26f0376
--- /dev/null
@@ -0,0 +1,650 @@
+/**\r
+A D implementation of the "tsp" Olden benchmark, the traveling\r
+salesman problem.\r
+\r
+R. Karp, "Probabilistic analysis of partitioning algorithms for the\r
+traveling-salesman problem in the plane."  Mathematics of Operations Research\r
+2(3):209-224, August 1977.\r
+\r
+Converted to D and optimized by leonardo maffi, V.1.0, Oct 29 2009.\r
+\r
+Removed output unless an option is passed by Leandro Lucarella, 2010-08-04.\r
+Downloaded from http://www.fantascienza.net/leonardo/js/\r
+                http://www.fantascienza.net/leonardo/js/dolden_tsp.zip\r
+*/\r
+\r
+version (Tango) {\r
+    import tango.stdc.stdio: printf, fprintf, stderr;\r
+    import tango.stdc.time: CLOCKS_PER_SEC, clock;\r
+    import tango.math.Math: sqrt, log;\r
+\r
+    import Integer = tango.text.convert.Integer;\r
+    alias Integer.parse toInt;\r
+} else {\r
+    import std.c.stdio: printf, fprintf, stderr;\r
+    import std.c.time: CLOCKS_PER_SEC, clock;\r
+    import std.math: sqrt, log;\r
+\r
+    version (D_Version2) {\r
+        import std.conv: to;\r
+        alias to!(int, char[]) toInt;\r
+    } else {\r
+        import std.conv: toInt;\r
+    }\r
+}\r
+\r
+\r
+double myclock() {\r
+    return clock() / cast(double)CLOCKS_PER_SEC;\r
+}\r
+\r
+\r
+/**\r
+Basic uniform random generator: Minimal Standard in Park and\r
+Miller (1988): "Random Number Generators: Good Ones Are Hard to\r
+Find", Comm. of the ACM, 31, 1192-1201.\r
+Parameters: m = 2^31-1, a=48271.\r
+\r
+Very simple portable random number generator adapted\r
+from Pascal code by Jesper Lund:\r
+http://www.gnu-pascal.de/crystal/gpc/en/mail1390.html\r
+*/\r
+final class Random {\r
+    const int m = int.max;\r
+    const int a = 48271;\r
+    const int q = m / a;\r
+    const int r = m % a;\r
+\r
+    public int seed;\r
+\r
+    this(int the_seed) {\r
+        this.seed = the_seed;\r
+    }\r
+\r
+    public double nextDouble() {\r
+        int k = seed / q;\r
+        seed = a * (seed - k * q) - r * k;\r
+        if (seed < 1)\r
+        seed += m;\r
+        return cast(double)seed / m;\r
+    }\r
+\r
+    public int nextInt(int max) {\r
+        int n = max + 1;\r
+        int k = cast(int)(n * this.nextDouble());\r
+        return (k == n) ? k - 1 : k;\r
+    }\r
+}\r
+\r
+\r
+\r
+/**\r
+* A class that represents a node in a binary tree.  Each node represents\r
+* a city in the TSP benchmark.\r
+**/\r
+final class Tree {\r
+    /**\r
+    * The number of nodes (cities) in this subtree\r
+    **/\r
+    private int sz;\r
+\r
+    /**\r
+    * The coordinates that this node represents\r
+    **/\r
+    private double x, y;\r
+\r
+    /**\r
+    * Left and right child of tree\r
+    **/\r
+    private Tree left, right;\r
+\r
+    /**\r
+    * The next pointer in a linked list of nodes in the subtree.  The list\r
+    * contains the order of the cities to visit.\r
+    **/\r
+    private Tree next;\r
+\r
+    /**\r
+    * The previous pointer in a linked list of nodes in the subtree. The list\r
+    * contains the order of the cities to visit.\r
+    **/\r
+    private Tree prev;\r
+\r
+    static Random rnd;\r
+\r
+    // used by the random number generator\r
+    private const double M_E2  = 7.3890560989306502274;\r
+    private const double M_E3  = 20.08553692318766774179;\r
+    private const double M_E6  = 403.42879349273512264299;\r
+    private const double M_E12 = 162754.79141900392083592475;\r
+\r
+    public static void initRnd(int seed) {\r
+        rnd = new Random(seed);\r
+    }\r
+\r
+    /**\r
+    * Construct a Tree node (a city) with the specified size\r
+    * @param size the number of nodes in the (sub)tree\r
+    * @param x the x coordinate of the city\r
+    * @param y the y coordinate of the city\r
+    * @param left the left subtree\r
+    * @param right the right subtree\r
+    **/\r
+    this(int size, double x, double y, Tree l, Tree r) {\r
+        sz = size;\r
+        this.x = x;\r
+        this.y = y;\r
+        left = l;\r
+        right = r;\r
+        next = null;\r
+        prev = null;\r
+    }\r
+\r
+    /**\r
+    * Find Euclidean distance between this node and the specified node.\r
+    * @param b the specified node\r
+    * @return the Euclidean distance between two tree nodes.\r
+    **/\r
+    double distance(Tree b) {\r
+        return sqrt((x - b.x) * (x - b.x) + (y - b.y) * (y - b.y));\r
+    }\r
+\r
+    /**\r
+    * Create a list of tree nodes.  Requires root to be the tail of the list.\r
+    * Only fills in next field, not prev.\r
+    * @return the linked list of nodes\r
+    **/\r
+    Tree makeList() {\r
+        Tree myleft, myright, tleft, tright;\r
+        Tree retval = this;\r
+\r
+        // head of left list\r
+        if (left !is null)\r
+            myleft = left.makeList();\r
+        else\r
+            myleft = null;\r
+\r
+        // head of right list\r
+        if (right !is null)\r
+            myright = right.makeList();\r
+        else\r
+            myright = null;\r
+\r
+        if (myright !is null) {\r
+            retval = myright;\r
+            right.next = this;\r
+        }\r
+\r
+        if (myleft !is null) {\r
+            retval = myleft;\r
+            if (myright !is null)\r
+                left.next = myright;\r
+            else\r
+                left.next = this;\r
+        }\r
+        next = null;\r
+\r
+        return retval;\r
+    }\r
+\r
+    /**\r
+    * Reverse the linked list.  Assumes that there is a dummy "prev"\r
+    * node at the beginning.\r
+    **/\r
+    void reverse() {\r
+        Tree prev = this.prev;\r
+        prev.next = null;\r
+        this.prev = null;\r
+        Tree back = this;\r
+        Tree tmp = this;\r
+\r
+        // reverse the list for the other nodes\r
+        Tree next;\r
+        for (Tree t = this.next; t !is null; back = t, t = next) {\r
+            next = t.next;\r
+            t.next = back;\r
+            back.prev = t;\r
+        }\r
+\r
+        // reverse the list for this node\r
+        tmp.next = prev;\r
+        prev.prev = tmp;\r
+    }\r
+\r
+    /**\r
+    * Use closest-point heuristic from Cormen, Leiserson, and Rivest.\r
+    * @return a\r
+    **/\r
+    Tree conquer() {\r
+        // create the list of nodes\r
+        Tree t = makeList();\r
+\r
+        // Create initial cycle\r
+        Tree cycle = t;\r
+        t = t.next;\r
+        cycle.next = cycle;\r
+        cycle.prev = cycle;\r
+\r
+        // Loop over remaining points\r
+        Tree donext;\r
+        for ( ; t !is null; t = donext) {\r
+            donext = t.next; /* value won't be around later */\r
+            Tree min = cycle;\r
+            double mindist = t.distance(cycle);\r
+            for (Tree tmp = cycle.next; tmp != cycle; tmp = tmp.next) {\r
+                double test = tmp.distance(t);\r
+                if (test < mindist) {\r
+                    mindist = test;\r
+                    min = tmp;\r
+                }\r
+            }\r
+\r
+            Tree next = min.next;\r
+            Tree prev = min.prev;\r
+\r
+            double mintonext = min.distance(next);\r
+            double mintoprev = min.distance(prev);\r
+            double ttonext = t.distance(next);\r
+            double ttoprev = t.distance(prev);\r
+\r
+            if ((ttoprev - mintoprev) < (ttonext - mintonext)) {\r
+                // insert between min and prev\r
+                prev.next = t;\r
+                t.next = min;\r
+                t.prev = prev;\r
+                min.prev = t;\r
+            } else {\r
+                next.prev = t;\r
+                t.next = next;\r
+                min.next = t;\r
+                t.prev = min;\r
+            }\r
+        }\r
+\r
+        return cycle;\r
+    }\r
+\r
+    /**\r
+    * Merge two cycles as per Karp.\r
+    * @param a a subtree with one cycle\r
+    * @param b a subtree with the other cycle\r
+    **/\r
+    Tree merge(Tree a, Tree b) {\r
+        // Compute location for first cycle\r
+        Tree min = a;\r
+        double mindist = distance(a);\r
+        Tree tmp = a;\r
+        for (a = a.next; a != tmp; a = a.next) {\r
+            double test = distance(a);\r
+            if (test < mindist) {\r
+                mindist = test;\r
+                min = a;\r
+            }\r
+        }\r
+\r
+        Tree next = min.next;\r
+        Tree prev = min.prev;\r
+        double mintonext = min.distance(next);\r
+        double mintoprev = min.distance(prev);\r
+        double ttonext   = distance(next);\r
+        double ttoprev   = distance(prev);\r
+\r
+        Tree p1, n1;\r
+        double tton1, ttop1;\r
+        if ((ttoprev - mintoprev) < (ttonext - mintonext)) {\r
+            // would insert between min and prev\r
+            p1 = prev;\r
+            n1 = min;\r
+            tton1 = mindist;\r
+            ttop1 = ttoprev;\r
+        } else {\r
+            // would insert between min and next\r
+            p1 = min;\r
+            n1 = next;\r
+            ttop1 = mindist;\r
+            tton1 = ttonext;\r
+        }\r
+\r
+        // Compute location for second cycle\r
+        min = b;\r
+        mindist = distance(b);\r
+        tmp = b;\r
+        for (b = b.next; b != tmp; b = b.next) {\r
+            double test = distance(b);\r
+            if (test < mindist) {\r
+                mindist = test;\r
+                min = b;\r
+            }\r
+        }\r
+\r
+        next = min.next;\r
+        prev = min.prev;\r
+        mintonext = min.distance(next);\r
+        mintoprev = min.distance(prev);\r
+        ttonext = this.distance(next);\r
+        ttoprev = this.distance(prev);\r
+\r
+        Tree p2, n2;\r
+        double tton2, ttop2;\r
+        if ((ttoprev - mintoprev) < (ttonext - mintonext)) {\r
+            // would insert between min and prev\r
+            p2 = prev;\r
+            n2 = min;\r
+            tton2 = mindist;\r
+            ttop2 = ttoprev;\r
+        } else {\r
+            // would insert between min andn ext\r
+            p2 = min;\r
+            n2 = next;\r
+            ttop2 = mindist;\r
+            tton2 = ttonext;\r
+        }\r
+\r
+        // Now we have 4 choices to complete:\r
+        // 1:t,p1 t,p2 n1,n2\r
+        // 2:t,p1 t,n2 n1,p2\r
+        // 3:t,n1 t,p2 p1,n2\r
+        // 4:t,n1 t,n2 p1,p2\r
+        double n1ton2 = n1.distance(n2);\r
+        double n1top2 = n1.distance(p2);\r
+        double p1ton2 = p1.distance(n2);\r
+        double p1top2 = p1.distance(p2);\r
+\r
+        mindist = ttop1 + ttop2 + n1ton2;\r
+        int choice = 1;\r
+\r
+        double test = ttop1 + tton2 + n1top2;\r
+        if (test < mindist) {\r
+            choice = 2;\r
+            mindist = test;\r
+        }\r
+\r
+        test = tton1 + ttop2 + p1ton2;\r
+        if (test < mindist) {\r
+            choice = 3;\r
+            mindist = test;\r
+        }\r
+\r
+        test = tton1 + tton2 + p1top2;\r
+        if (test < mindist)\r
+            choice = 4;\r
+\r
+        switch (choice) {\r
+            case 1:\r
+                // 1:p1,this this,p2 n2,n1 -- reverse 2!\r
+                n2.reverse();\r
+                p1.next = this;\r
+                this.prev = p1;\r
+                this.next = p2;\r
+                p2.prev = this;\r
+                n2.next = n1;\r
+                n1.prev = n2;\r
+                break;\r
+\r
+            case 2:\r
+                // 2:p1,this this,n2 p2,n1 -- OK\r
+                p1.next = this;\r
+                this.prev = p1;\r
+                this.next = n2;\r
+                n2.prev = this;\r
+                p2.next = n1;\r
+                n1.prev = p2;\r
+                break;\r
+\r
+            case 3:\r
+                // 3:p2,this this,n1 p1,n2 -- OK\r
+                p2.next = this;\r
+                this.prev = p2;\r
+                this.next = n1;\r
+                n1.prev = this;\r
+                p1.next = n2;\r
+                n2.prev = p1;\r
+                break;\r
+\r
+            default: // case 4:\r
+                // 4:n1,this this,n2 p2,p1 -- reverse 1!\r
+                n1.reverse();\r
+                n1.next = this;\r
+                this.prev = n1;\r
+                this.next = n2;\r
+                n2.prev = this;\r
+                p2.next = p1;\r
+                p1.prev = p2;\r
+                break;\r
+        }\r
+\r
+        return this;\r
+    } // end merge\r
+\r
+    /**\r
+    * Compute TSP for the tree t. Use conquer for problems <= sz\r
+    * @param sz the cutoff point for using conquer vs. merge\r
+    **/\r
+    Tree tsp(int sz) {\r
+        if (this.sz <= sz)\r
+            return conquer();\r
+        Tree leftval  = left.tsp(sz);\r
+        Tree rightval = right.tsp(sz);\r
+        return merge(leftval, rightval);\r
+    }\r
+\r
+    /**\r
+    * Print the list of cities to visit from the current node.  The\r
+    * list is the result of computing the TSP problem.\r
+    * The list for the root node (city) should contain every other node\r
+    * (city).\r
+    **/\r
+    void printVisitOrder() {\r
+        printf("x = %.15f y = %.15f\n", x, y);\r
+        for (Tree tmp = next; tmp != this; tmp = tmp.next)\r
+            printf("x = %.15f y = %.15f\n", tmp.x, tmp.y);\r
+    }\r
+\r
+    /**\r
+    * Computes the total length of the current tour.\r
+    **/\r
+    double tourLength() {\r
+        double total = 0.0;\r
+        Tree precedent = next;\r
+        Tree current = next.next;\r
+        if (current == this)\r
+            return total;\r
+\r
+        do {\r
+            total += current.distance(precedent);\r
+            precedent = current;\r
+            current = current.next;\r
+        } while (precedent != this);\r
+\r
+        total += current.distance(this);\r
+        return total;\r
+    }\r
+\r
+\r
+    // static methods ===============================================\r
+\r
+    /**\r
+    * Return an estimate of median of n values distributed in [min, max)\r
+    * @param min the minimum value\r
+    * @param max the maximum value\r
+    * @param n\r
+    * @return an estimate of median of n values distributed in [min, max)\r
+    **/\r
+    private static double median(double min, double max, int n) {\r
+        // get random value in [0.0, 1.0)\r
+        double t = rnd.nextDouble();\r
+\r
+        double retval;\r
+        if (t > 0.5)\r
+            retval = log(1.0 - (2.0 * (M_E12 - 1) * (t - 0.5) / M_E12)) / 12.0;\r
+        else\r
+            retval = -log(1.0 - (2.0 * (M_E12 - 1) * t / M_E12)) / 12.0;\r
+\r
+        // We now have something distributed on (-1.0, 1.0)\r
+        retval = (retval + 1.0) * (max - min) / 2.0;\r
+        return retval + min;\r
+    }\r
+\r
+    /**\r
+    * Get double uniformly distributed over [min,max)\r
+    * @return double uniformily distributed over [min,max)\r
+    **/\r
+    private static double uniform(double min, double max) {\r
+        // get random value between [0.0, 1.0)\r
+        double retval = rnd.nextDouble();\r
+        retval = retval * (max - min);\r
+        return retval + min;\r
+    }\r
+\r
+    /**\r
+    * Builds a 2D tree of n nodes in specified range with dir as primary\r
+    * axis (false for x, true for y)\r
+    *\r
+    * @param n the size of the subtree to create\r
+    * @param dir the primary axis\r
+    * @param min_x the minimum x coordinate\r
+    * @param max_x the maximum x coordinate\r
+    * @param min_y the minimum y coordinate\r
+    * @param max_y the maximum y coordinate\r
+    * @return a reference to the root of the subtree\r
+    **/\r
+    public static Tree buildTree(int n, bool dir, double min_x,\r
+                                 double max_x, double min_y, double max_y) {\r
+        if (n == 0)\r
+            return null;\r
+\r
+        Tree left, right;\r
+        double x, y;\r
+        if (dir) {\r
+            dir = !dir;\r
+            double med = median(min_x, max_x, n);\r
+            left = buildTree(n/2, dir, min_x, med, min_y, max_y);\r
+            right = buildTree(n/2, dir, med, max_x, min_y, max_y);\r
+            x = med;\r
+            y = uniform(min_y, max_y);\r
+        } else {\r
+            dir = !dir;\r
+            double med = median(min_y,max_y,n);\r
+            left = buildTree(n/2, dir, min_x, max_x, min_y, med);\r
+            right = buildTree(n/2, dir, min_x, max_x, med, max_y);\r
+            y = med;\r
+            x = uniform(min_x, max_x);\r
+        }\r
+\r
+        return new Tree(n, x, y, left, right);\r
+    }\r
+}\r
+\r
+\r
+public class TSP {\r
+    /**\r
+    * Number of cities in the problem.\r
+    **/\r
+    private static int cities;\r
+\r
+    /**\r
+    * Set to true if the result should be printed\r
+    **/\r
+    private static bool printResult = false;\r
+\r
+    /**\r
+    * Set to true to print informative messages\r
+    **/\r
+    private static bool printMsgs = false;\r
+\r
+    /**\r
+    * The main routine which creates a tree and traverses it.\r
+    * @param args the arguments to the program\r
+    **/\r
+    public static void main(char[] args[]) {\r
+        if (!parseCmdLine(args))\r
+            return;\r
+\r
+        if (printMsgs)\r
+            printf("Building tree of size: %d\n", nextPow2(cities+1) - 1);\r
+\r
+        Tree.initRnd(1);\r
+\r
+        auto t0 = myclock();\r
+        Tree t = Tree.buildTree(cities, false, 0.0, 1.0, 0.0, 1.0);\r
+\r
+        auto t1 = myclock();\r
+        t.tsp(150);\r
+        auto t2 = myclock();\r
+\r
+        if (printMsgs)\r
+            printf("Total tour length: %.15f\n", t.tourLength());\r
+        auto t3 = myclock();\r
+\r
+        if (printResult)\r
+            // if the user specifies, print the final result\r
+            t.printVisitOrder();\r
+\r
+        if (printMsgs) {\r
+            printf("Tsp build time: %.2f\n", t1 - t0);\r
+            printf("Tsp computing time: %.2f\n", t2 - t1);\r
+            printf("Tsp total time: %.2f\n", t3 - t0);\r
+        }\r
+    }\r
+\r
+    private static /*unsigned*/ int nextPow2(/*unsigned*/ int x) {\r
+        if (x < 0)\r
+            throw new Exception("x must be >= 0");\r
+        x = x - 1;\r
+        x = x | (x >>  1);\r
+        x = x | (x >>  2);\r
+        x = x | (x >>  4);\r
+        x = x | (x >>  8);\r
+        x = x | (x >> 16);\r
+       return x + 1;\r
+    }\r
+\r
+    /**\r
+    * Parse the command line options.\r
+    * @param args the command line options.\r
+    **/\r
+    private static final bool parseCmdLine(char[] args[]) {\r
+        int i = 1;\r
+\r
+        while (i < args.length && args[i][0] == '-') {\r
+            char[] arg = args[i++];\r
+\r
+            if (arg == "-c") {\r
+                if (i < args.length)\r
+                    cities = toInt(args[i++]);\r
+                else\r
+                    throw new Exception("-c requires the size of tree");\r
+                if (cities < 1)\r
+                    throw new Exception("Number of cities must be > 0");\r
+            } else if (arg == "-p") {\r
+                printResult = true;\r
+            } else if (arg == "-m") {\r
+                printMsgs = true;\r
+            } else if (arg == "-h") {\r
+                return usage();\r
+            }\r
+        }\r
+\r
+        if (cities == 0)\r
+            return usage();\r
+\r
+        return true;\r
+    }\r
+\r
+    /**\r
+    * The usage routine which describes the program options.\r
+    **/\r
+    private static final bool usage() {\r
+        fprintf(stderr, "usage: tsp_d -c <num> [-p] [-m] [-h]\n");\r
+        fprintf(stderr, "  -c number of cities (rounds up to the next power of 2 minus 1)\n");\r
+        fprintf(stderr, "  -p (print the final result)\n");\r
+        fprintf(stderr, "  -m (print informative messages)\n");\r
+        fprintf(stderr, "  -h (print this message)\n");\r
+        return false;\r
+    }\r
+}\r
+\r
+\r
+void main(char[][] args) {\r
+    TSP.main(args);\r
+}\r